-
Notifications
You must be signed in to change notification settings - Fork 2
Update coaching sessions #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
6f0be1a
3b21b68
413981c
f18b415
704b933
e9cb3e7
d79bbce
dbc6966
a17885a
962040b
3982109
c851b3a
28cd840
e29da27
6e64e99
536a763
0630dbb
66000f8
14ddebb
e3ef1f5
7c6ada9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| "use client"; | ||
|
|
||
| import { useState } from "react"; | ||
| import type * as React from "react"; | ||
| import { cn } from "@/components/lib/utils"; | ||
| import SelectCoachingRelationship from "@/components/ui/dashboard/select-coaching-relationship"; | ||
| import CoachingSessionList from "@/components/ui/dashboard/coaching-session-list"; | ||
| import AddEntities from "@/components/ui/dashboard/add-entities"; | ||
| import { CoachingSessionDialog } from "@/components/ui/dashboard/coaching-session-dialog"; | ||
| import type { CoachingSession } from "@/types/coaching-session"; | ||
|
|
||
| function DashboardContainer({ | ||
| className, | ||
| ...props | ||
| }: React.HTMLAttributes<HTMLDivElement>) { | ||
| return ( | ||
| <div | ||
| className={cn( | ||
| // Base styles | ||
| "p-4", | ||
| // Mobile: stack vertically | ||
| "flex flex-col gap-6", | ||
| // Tablet and up (640px+): side by side | ||
| "sm:grid sm:grid-cols-2", | ||
| // Never grow wider than the site-header | ||
| "max-w-screen-2xl", | ||
| // Ensure full width for children | ||
| "[&>*]:w-full", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export function DashboardContent() { | ||
| const [dialogOpen, setDialogOpen] = useState(false); | ||
| const [sessionToEdit, setSessionToEdit] = useState<CoachingSession | undefined>(); | ||
|
|
||
| const handleOpenDialog = (session?: CoachingSession) => { | ||
| setSessionToEdit(session); | ||
| setDialogOpen(true); | ||
| }; | ||
|
|
||
| const handleCloseDialog = () => { | ||
| setDialogOpen(false); | ||
| setSessionToEdit(undefined); | ||
| }; | ||
|
|
||
| return ( | ||
| <> | ||
| <div className="p-4 max-w-screen-2xl"> | ||
| <div className="mb-8 w-full"> | ||
| <AddEntities onCreateSession={() => handleOpenDialog()} /> | ||
| </div> | ||
| </div> | ||
| <DashboardContainer> | ||
| <SelectCoachingRelationship /> | ||
| <CoachingSessionList onUpdateSession={handleOpenDialog} /> | ||
| </DashboardContainer> | ||
|
|
||
| <CoachingSessionDialog | ||
| open={dialogOpen} | ||
| onOpenChange={handleCloseDialog} | ||
| coachingSessionToEdit={sessionToEdit} | ||
| /> | ||
| </> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,51 +1,11 @@ | ||
| import type { Metadata } from "next"; | ||
| import type * as React from "react"; | ||
| import { cn } from "@/components/lib/utils"; | ||
| import SelectCoachingRelationship from "@/components/ui/dashboard/select-coaching-relationship"; | ||
| import CoachingSessionList from "@/components/ui/dashboard/coaching-session-list"; | ||
| import AddEntities from "@/components/ui/dashboard/add-entities"; | ||
| import { DashboardContent } from "./dashboard-content"; | ||
|
|
||
| export const metadata: Metadata = { | ||
| title: "Dashboard", | ||
| description: "Coaching dashboard", | ||
| }; | ||
|
|
||
| function DashboardContainer({ | ||
| className, | ||
| ...props | ||
| }: React.HTMLAttributes<HTMLDivElement>) { | ||
| return ( | ||
| <div | ||
| className={cn( | ||
| // Base styles | ||
| "p-4", | ||
| // Mobile: stack vertically | ||
| "flex flex-col gap-6", | ||
| // Tablet and up (640px+): side by side | ||
| "sm:grid sm:grid-cols-2", | ||
| // Never grow wider than the site-header | ||
| "max-w-screen-2xl", | ||
| // Ensure full width for children | ||
| "[&>*]:w-full", | ||
| className | ||
| )} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| export default function DashboardPage() { | ||
| return ( | ||
| <> | ||
| <div className="p-4 max-w-screen-2xl"> | ||
| <div className="mb-8 w-full"> | ||
| <AddEntities /> | ||
| </div> | ||
| </div> | ||
| <DashboardContainer> | ||
| <SelectCoachingRelationship /> | ||
| <CoachingSessionList /> | ||
| </DashboardContainer> | ||
| </> | ||
| ); | ||
| return <DashboardContent />; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,6 @@ | ||
| "use client"; | ||
|
|
||
| import React, { useState } from "react"; | ||
| import React from "react"; | ||
| import { format } from "date-fns"; | ||
| import { Card, CardHeader } from "@/components/ui/card"; | ||
| import { Button } from "@/components/ui/button"; | ||
|
|
@@ -15,56 +15,49 @@ import { | |
| DropdownMenuTrigger, | ||
| } from "@/components/ui/dropdown-menu"; | ||
| import { MoreHorizontal } from "lucide-react"; | ||
| import { CoachingSessionDialog } from "@/components/ui/dashboard/coaching-session-dialog"; | ||
| import { DateTime } from "ts-luxon"; | ||
| import { CoachingSession as CoachingSessionType } from "@/types/coaching-session"; | ||
|
|
||
| interface CoachingSessionProps { | ||
| coachingSession: { | ||
| id: Id; | ||
| date: string; | ||
| coaching_relationship_id: Id; | ||
| created_at: DateTime; | ||
| updated_at: DateTime; | ||
| }; | ||
| coachingSession: CoachingSessionType; | ||
| onUpdate: () => void; | ||
| } | ||
|
|
||
| const CoachingSession: React.FC<CoachingSessionProps> = ({ | ||
| coachingSession, | ||
| onUpdate, | ||
| }) => { | ||
| const { setCurrentCoachingSessionId } = useCoachingSessionStateStore( | ||
| (state) => state | ||
| ); | ||
| const [updateDialogOpen, setUpdateDialogOpen] = useState(false); | ||
|
|
||
| return ( | ||
| <> | ||
| <Card> | ||
| <CardHeader className="p-4"> | ||
| <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2"> | ||
| <div className="space-y-1"> | ||
| <OverarchingGoal coachingSessionId={coachingSession.id} /> | ||
| <div className="text-sm text-muted-foreground"> | ||
| {format(new Date(coachingSession.date), "MMMM d, yyyy h:mm a")} | ||
| </div> | ||
| <Card> | ||
| <CardHeader className="p-4"> | ||
| <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2"> | ||
| <div className="space-y-1"> | ||
| <OverarchingGoal coachingSessionId={coachingSession.id} /> | ||
| <div className="text-sm text-muted-foreground"> | ||
| {format(new Date(coachingSession.date), "MMMM d, yyyy h:mm a")} | ||
| </div> | ||
| </div> | ||
| <div className="flex items-center gap-2"> | ||
| <Link href={`/coaching-sessions/${coachingSession.id}`} passHref> | ||
| <Button | ||
| size="sm" | ||
| className="w-full sm:w-auto mt-2 sm:mt-0 text-sm px-3 py-1" | ||
| onClick={() => setCurrentCoachingSessionId(coachingSession.id)} | ||
| > | ||
| Join Session | ||
| </Button> | ||
| </Link> | ||
| <DropdownMenu> | ||
| <DropdownMenuTrigger asChild> | ||
| <Button variant="ghost" size="icon"> | ||
| <MoreHorizontal className="h-4 w-4" /> | ||
| </Button> | ||
| </DropdownMenuTrigger> | ||
| <DropdownMenuContent align="end"> | ||
| <DropdownMenuItem asChild> | ||
| <Link | ||
| href={`/coaching-sessions/${coachingSession.id}`} | ||
| onClick={() => | ||
| setCurrentCoachingSessionId(coachingSession.id) | ||
| } | ||
| > | ||
| Join Session | ||
| </Link> | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem onClick={() => setUpdateDialogOpen(true)}> | ||
| <DropdownMenuItem onClick={onUpdate}> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be consistent with Agreements and Actions, can you update the drop down menu item text to be "Edit" and "Delete" instead of "Update Session" and "Delete Session"?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated 536a763 |
||
| Update Session | ||
| </DropdownMenuItem> | ||
| <DropdownMenuItem className="text-destructive"> | ||
|
|
@@ -73,19 +66,9 @@ const CoachingSession: React.FC<CoachingSessionProps> = ({ | |
| </DropdownMenuContent> | ||
| </DropdownMenu> | ||
| </div> | ||
| </CardHeader> | ||
| </Card> | ||
| <CoachingSessionDialog | ||
| open={updateDialogOpen} | ||
| onOpenChange={setUpdateDialogOpen} | ||
| onCoachingSessionUpdated={() => { | ||
| // Refresh the list of coaching sessions | ||
| window.location.reload(); | ||
| }} | ||
| existingSession={coachingSession} | ||
| mode="update" | ||
| /> | ||
| </> | ||
| </div> | ||
| </CardHeader> | ||
| </Card> | ||
| ); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,20 @@ | ||
| "use client"; | ||
|
|
||
| import { useState } from "react"; | ||
| import { CoachingSessionDialog } from "./coaching-session-dialog"; | ||
| import { AddCoachingSessionButton } from "./add-coaching-session-button"; | ||
| import { AddMemberButton } from "./add-member-button"; | ||
| import { useRouter } from "next/navigation"; | ||
| import { useOrganizationStateStore } from "@/lib/providers/organization-state-store-provider"; | ||
| import { useAuthStore } from "@/lib/providers/auth-store-provider"; | ||
|
|
||
| export default function AddEntities() { | ||
| interface AddEntitiesProps { | ||
| onCreateSession: () => void; | ||
| } | ||
|
|
||
| export default function AddEntities({ onCreateSession }: AddEntitiesProps) { | ||
| const router = useRouter(); | ||
| const [open, setOpen] = useState(false); | ||
| const { currentOrganizationId } = useOrganizationStateStore((state) => state); | ||
| const { isCoach } = useAuthStore((state) => state); | ||
|
|
||
| const onCoachingSessionAdded = () => { | ||
| setOpen(false); | ||
| }; | ||
|
|
||
| const onMemberButtonClicked = () => { | ||
| router.push(`/organizations/${currentOrganizationId}/members`); | ||
| }; | ||
|
|
@@ -28,27 +25,16 @@ export default function AddEntities() { | |
| Add New | ||
| </h3> | ||
| <div className="grid grid-cols-1 gap-4 md:grid-cols-2"> | ||
| <CoachingSessionDialog | ||
| mode="create" | ||
| open={open} | ||
| onOpenChange={setOpen} | ||
| onCoachingSessionUpdated={onCoachingSessionAdded} | ||
| dialogTrigger={ | ||
| <AddCoachingSessionButton | ||
| disabled={!isCoach || !currentOrganizationId} | ||
| /> | ||
| } | ||
| <AddCoachingSessionButton | ||
| disabled={!isCoach || !currentOrganizationId} | ||
| onClick={onCreateSession} | ||
|
Comment on lines
+33
to
+35
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes!! This fulfills my TODO item, so thank you for refactoring this to match the style of AddMemberButton. What a pleasant surprise to discover. :) |
||
| /> | ||
|
|
||
| {/* TODO: Refactor the AddMemberButton and AddMemberDialog to work just like | ||
| AddCoachingSessionDialog does above, where the dialog is the parent container | ||
| and it accepts a AddMemberButton as the dialogTrigger parameter. | ||
| */} | ||
| <AddMemberButton | ||
| disabled={!isCoach || !currentOrganizationId} | ||
| onClick={onMemberButtonClicked} | ||
| /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to suggest that we should merge
DashboardContainerandDashboardContentand I suggestDashboardContaineras the name since we have precedence for this already. Unless I'm misunderstanding things, I don't see any value or requirement to have the extra div layer.I do think you did take the right approach though in making the Dashboard page as simple as possible and trying to keep it rendered on the server side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some updating here, but not all of what I suggested. But you'll want to check it out so we don't step on each other directly: https://github.com/refactor-group/refactor-platform-fe/pull/102/files#diff-1b7538b3757a933d976e1a796af3bbf3bc3895ae83f60d5a0562db4d2f6bbc02
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jhodapp thanks for the heads up! It looks like that branch is based off of this one right? Do you have a preference of making this change in this branch vs yours?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calebbourg It is based off of this one indeed. I'm good either way. Maybe it makes the most sense to retarget my PR to merge into yours instead of into main?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok made this change e3ef1f5