Skip to content

Commit 14ddebb

Browse files
authored
Merge pull request #104 from refactor-group/remove_org_and_rel_selectors_and_enhance_sessions_list
2 parents 536a763 + 66000f8 commit 14ddebb

File tree

9 files changed

+193
-395
lines changed

9 files changed

+193
-395
lines changed

src/app/dashboard/dashboard-content.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import { useState } from "react";
44
import type * as React from "react";
55
import { cn } from "@/components/lib/utils";
6-
import SelectCoachingRelationship from "@/components/ui/dashboard/select-coaching-relationship";
76
import CoachingSessionList from "@/components/ui/dashboard/coaching-session-list";
87
import AddEntities from "@/components/ui/dashboard/add-entities";
98
import { CoachingSessionDialog } from "@/components/ui/dashboard/coaching-session-dialog";
@@ -20,8 +19,6 @@ function DashboardContainer({
2019
"p-4",
2120
// Mobile: stack vertically
2221
"flex flex-col gap-6",
23-
// Tablet and up (640px+): side by side
24-
"sm:grid sm:grid-cols-2",
2522
// Never grow wider than the site-header
2623
"max-w-screen-2xl",
2724
// Ensure full width for children
@@ -35,7 +32,9 @@ function DashboardContainer({
3532

3633
export function DashboardContent() {
3734
const [dialogOpen, setDialogOpen] = useState(false);
38-
const [sessionToEdit, setSessionToEdit] = useState<CoachingSession | undefined>();
35+
const [sessionToEdit, setSessionToEdit] = useState<
36+
CoachingSession | undefined
37+
>();
3938

4039
const handleOpenDialog = (session?: CoachingSession) => {
4140
setSessionToEdit(session);
@@ -49,13 +48,11 @@ export function DashboardContent() {
4948

5049
return (
5150
<>
52-
<div className="p-4 max-w-screen-2xl">
53-
<div className="mb-8 w-full">
54-
<AddEntities onCreateSession={() => handleOpenDialog()} />
55-
</div>
56-
</div>
5751
<DashboardContainer>
58-
<SelectCoachingRelationship />
52+
<AddEntities
53+
className="mb-8"
54+
onCreateSession={() => handleOpenDialog()}
55+
/>
5956
<CoachingSessionList onUpdateSession={handleOpenDialog} />
6057
</DashboardContainer>
6158

src/components/ui/coaching-relationship-selector.tsx

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import { useEffect } from "react";
1414
import { useAuthStore } from "@/lib/providers/auth-store-provider";
1515
import { useCoachingRelationshipStateStore } from "@/lib/providers/coaching-relationship-state-store-provider";
1616
import { useCoachingSessionStateStore } from "@/lib/providers/coaching-session-state-store-provider";
17+
import { cn } from "../lib/utils";
1718

1819
interface CoachingRelationshipsSelectorProps extends PopoverProps {
20+
className?: string;
1921
/// The Organization's Id for which to get a list of associated CoachingRelationships
2022
organizationId: Id;
2123
/// Disable the component from interaction with the user
@@ -38,18 +40,13 @@ function CoachingRelationshipsSelectItems({
3840
// Be sure to cache the list of current coaching relationships in the CoachingRelationshipStateStore
3941
useEffect(() => {
4042
if (!relationships.length) return;
41-
console.debug(
42-
`relationships (useEffect): ${JSON.stringify(relationships)}`
43-
);
4443
setCurrentCoachingRelationships(relationships);
4544
}, [relationships, setCurrentCoachingRelationships]);
4645

4746
if (isLoading) return <div>Loading...</div>;
4847
if (isError) return <div>Error loading coaching relationships</div>;
4948
if (!relationships?.length) return <div>No coaching relationships found</div>;
5049

51-
console.debug(`relationships: ${JSON.stringify(relationships)}`);
52-
5350
return (
5451
<>
5552
{relationships.map((rel) => (
@@ -63,6 +60,7 @@ function CoachingRelationshipsSelectItems({
6360
}
6461

6562
export default function CoachingRelationshipSelector({
63+
className,
6664
organizationId,
6765
disabled,
6866
onSelect,
@@ -101,29 +99,32 @@ export default function CoachingRelationshipSelector({
10199
? getCurrentCoachingRelationship(currentCoachingRelationshipId)
102100
: null;
103101

104-
const displayValue = currentRelationship ? (
105-
<>
106-
{currentRelationship.coach_first_name}{" "}
107-
{currentRelationship.coach_last_name} -&gt;{" "}
108-
{currentRelationship.coachee_first_name}{" "}
109-
{currentRelationship.coachee_last_name}
110-
</>
111-
) : undefined;
102+
const displayValue =
103+
currentRelationship && currentRelationship.id ? (
104+
<>
105+
{currentRelationship.coach_first_name}{" "}
106+
{currentRelationship.coach_last_name} -&gt;{" "}
107+
{currentRelationship.coachee_first_name}{" "}
108+
{currentRelationship.coachee_last_name}
109+
</>
110+
) : undefined;
112111

113112
return (
114-
<Select
115-
disabled={disabled}
116-
value={currentCoachingRelationshipId ?? undefined}
117-
onValueChange={handleSetCoachingRelationship}
118-
>
119-
<SelectTrigger id="coaching-relationship-selector">
120-
<SelectValue placeholder="Select coaching relationship">
121-
{displayValue}
122-
</SelectValue>
123-
</SelectTrigger>
124-
<SelectContent>
125-
<CoachingRelationshipsSelectItems organizationId={organizationId} />
126-
</SelectContent>
127-
</Select>
113+
<div className={cn("font-normal", className)}>
114+
<Select
115+
disabled={disabled}
116+
value={currentCoachingRelationshipId ?? undefined}
117+
onValueChange={handleSetCoachingRelationship}
118+
>
119+
<SelectTrigger id="coaching-relationship-selector">
120+
<SelectValue placeholder="Select coaching relationship">
121+
{displayValue}
122+
</SelectValue>
123+
</SelectTrigger>
124+
<SelectContent>
125+
<CoachingRelationshipsSelectItems organizationId={organizationId} />
126+
</SelectContent>
127+
</Select>
128+
</div>
128129
);
129130
}

src/components/ui/dashboard/add-entities.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@ import { AddMemberButton } from "./add-member-button";
55
import { useRouter } from "next/navigation";
66
import { useOrganizationStateStore } from "@/lib/providers/organization-state-store-provider";
77
import { useAuthStore } from "@/lib/providers/auth-store-provider";
8+
import { cn } from "@/components/lib/utils";
89

910
interface AddEntitiesProps {
11+
className?: string;
1012
onCreateSession: () => void;
1113
}
1214

13-
export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
15+
export default function AddEntities({
16+
className,
17+
onCreateSession,
18+
}: AddEntitiesProps) {
1419
const router = useRouter();
1520
const { currentOrganizationId } = useOrganizationStateStore((state) => state);
1621
const { isCoach } = useAuthStore((state) => state);
@@ -20,7 +25,7 @@ export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
2025
};
2126

2227
return (
23-
<div className="space-y-4">
28+
<div className={cn("space-y-4", className)}>
2429
<h3 className="text-xl sm:text-2xl font-semibold tracking-tight">
2530
Add New
2631
</h3>
@@ -37,4 +42,4 @@ export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
3742
</div>
3843
</div>
3944
);
40-
}
45+
}

src/components/ui/dashboard/coaching-session-list.tsx

Lines changed: 109 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
"use client";
22

3-
import { useState } from "react";
4-
import { Button } from "@/components/ui/button";
53
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
6-
import { ArrowUpDown } from "lucide-react";
74
import { useCoachingRelationshipStateStore } from "@/lib/providers/coaching-relationship-state-store-provider";
85
import { useCoachingSessionList } from "@/lib/api/coaching-sessions";
96
import { useCoachingSessionMutation } from "@/lib/api/coaching-sessions";
107
import { CoachingSession as CoachingSessionComponent } from "@/components/ui/coaching-session";
118
import { DateTime } from "ts-luxon";
12-
import type { CoachingSession } from "@/types/coaching-session";
13-
import { Id } from "@/types/general";
9+
import {
10+
filterAndSortCoachingSessions,
11+
type CoachingSession,
12+
} from "@/types/coaching-session";
13+
import { Id, SortOrder } from "@/types/general";
14+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
15+
import CoachingRelationshipSelector from "../coaching-relationship-selector";
16+
import { useOrganizationStateStore } from "@/lib/providers/organization-state-store-provider";
17+
import { cn } from "@/components/lib/utils";
1418

1519
interface CoachingSessionListProps {
20+
className?: string;
1621
onUpdateSession: (session: CoachingSession) => void;
1722
}
1823

19-
export default function CoachingSessionList({ onUpdateSession }: CoachingSessionListProps) {
24+
export default function CoachingSessionList({
25+
className,
26+
onUpdateSession,
27+
}: CoachingSessionListProps) {
28+
const { currentOrganizationId } = useOrganizationStateStore((state) => state);
2029
const { currentCoachingRelationshipId } = useCoachingRelationshipStateStore(
2130
(state) => state
2231
);
@@ -47,66 +56,107 @@ export default function CoachingSessionList({ onUpdateSession }: CoachingSession
4756
}
4857
};
4958

50-
const [sortByDate, setSortByDate] = useState(true);
59+
const upcomingSessions = coachingSessions
60+
? filterAndSortCoachingSessions(coachingSessions, SortOrder.Ascending, true)
61+
: [];
5162

52-
const sortedSessions = coachingSessions
53-
? [...coachingSessions].sort((a, b) => {
54-
return new Date(b.date).getTime() - new Date(a.date).getTime();
55-
})
63+
const previousSessions = coachingSessions
64+
? filterAndSortCoachingSessions(
65+
coachingSessions,
66+
SortOrder.Descending,
67+
false
68+
)
5669
: [];
5770

58-
if (isLoadingCoachingSessions) return <div>Loading coaching sessions...</div>;
59-
if (isErrorCoachingSessions)
60-
return <div>Error loading coaching sessions</div>;
71+
let loadingCoachingSessions = (
72+
<div className="flex items-center justify-center py-8">
73+
<p className="text-lg text-muted-foreground">
74+
Loading your coaching sessions...
75+
</p>
76+
</div>
77+
);
78+
79+
let noCoachingSessions = (
80+
<div className="flex items-center justify-center py-8">
81+
<p className="text-lg text-muted-foreground">
82+
Select a coaching relationship to view your coaching sessions.
83+
</p>
84+
</div>
85+
);
86+
87+
let errorLoadingCoachingSessions = (
88+
<div className="flex items-center justify-center py-8">
89+
<p className="text-lg font-bold">
90+
There was an error trying to load your coaching sessions.
91+
</p>
92+
</div>
93+
);
6194

6295
return (
63-
<Card className="flex-1">
64-
<CardHeader className="space-y-4">
65-
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4">
66-
<CardTitle className="text-xl sm:text-2xl">
67-
Coaching Sessions
68-
</CardTitle>
69-
</div>
70-
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-2">
71-
<Button
72-
variant="ghost"
73-
size="sm"
74-
className="text-muted-foreground w-full sm:w-auto justify-between"
75-
onClick={() => setSortByDate(true)}
76-
>
77-
<span>Date and Time</span>
78-
<ArrowUpDown className="ml-2 h-4 w-4" />
79-
</Button>
80-
<Button
81-
variant="ghost"
82-
size="sm"
83-
className="text-muted-foreground w-full sm:w-auto justify-between"
84-
onClick={() => setSortByDate(false)}
85-
>
86-
<span>Overarching Goal</span>
87-
<ArrowUpDown className="ml-2 h-4 w-4" />
88-
</Button>
89-
</div>
96+
<Card className={cn("min-w-96", className)}>
97+
<CardHeader>
98+
<CardTitle>
99+
<div className="flex justify-between flex-col lg:flex-row">
100+
<div>Coaching Sessions</div>
101+
<CoachingRelationshipSelector
102+
className="pt-4 lg:min-w-64"
103+
organizationId={currentOrganizationId}
104+
disabled={!currentOrganizationId}
105+
/>
106+
</div>
107+
</CardTitle>
90108
</CardHeader>
91109
<CardContent>
92-
{!currentCoachingRelationshipId ? (
93-
<div className="flex items-center justify-center py-8">
94-
<p className="text-lg text-muted-foreground">
95-
Choose a Relationship to view Coaching Sessions
96-
</p>
97-
</div>
98-
) : (
99-
<div className="space-y-4">
100-
{sortedSessions.map((coachingSession) => (
101-
<CoachingSessionComponent
102-
key={coachingSession.id}
103-
coachingSession={coachingSession}
104-
onUpdate={() => onUpdateSession(coachingSession)}
105-
onDelete={() => handleDeleteCoachingSession(coachingSession.id)}
106-
/>
107-
))}
108-
</div>
109-
)}
110+
<Tabs defaultValue="upcoming" className="w-full items-start">
111+
<TabsList className="grid w-full grid-cols-2">
112+
<TabsTrigger value="upcoming">Upcoming</TabsTrigger>
113+
<TabsTrigger value="previous">Previous</TabsTrigger>
114+
</TabsList>
115+
<TabsContent value="upcoming" className="mt-4">
116+
{isLoadingCoachingSessions ? (
117+
loadingCoachingSessions
118+
) : isErrorCoachingSessions ? (
119+
errorLoadingCoachingSessions
120+
) : !currentCoachingRelationshipId ? (
121+
noCoachingSessions
122+
) : (
123+
<div className="space-y-4">
124+
{upcomingSessions.map((coachingSession) => (
125+
<CoachingSessionComponent
126+
key={coachingSession.id}
127+
coachingSession={coachingSession}
128+
onUpdate={() => onUpdateSession(coachingSession)}
129+
onDelete={() =>
130+
handleDeleteCoachingSession(coachingSession.id)
131+
}
132+
/>
133+
))}
134+
</div>
135+
)}
136+
</TabsContent>
137+
<TabsContent value="previous" className="mt-4">
138+
{isLoadingCoachingSessions ? (
139+
loadingCoachingSessions
140+
) : isErrorCoachingSessions ? (
141+
errorLoadingCoachingSessions
142+
) : !currentCoachingRelationshipId ? (
143+
noCoachingSessions
144+
) : (
145+
<div className="space-y-4">
146+
{previousSessions.map((coachingSession) => (
147+
<CoachingSessionComponent
148+
key={coachingSession.id}
149+
coachingSession={coachingSession}
150+
onUpdate={() => onUpdateSession(coachingSession)}
151+
onDelete={() =>
152+
handleDeleteCoachingSession(coachingSession.id)
153+
}
154+
/>
155+
))}
156+
</div>
157+
)}
158+
</TabsContent>
159+
</Tabs>
110160
</CardContent>
111161
</Card>
112162
);

0 commit comments

Comments
 (0)