From 962040be2ac9effb2c23297430cc0e3eaba182da Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Sat, 5 Apr 2025 16:33:08 -0500
Subject: [PATCH 1/8] Removes the SelectCoachingRelationship component from the
Dashboard page. Moves CoachingSessionList left. Adds a tab bar splitting
sessions out by upcoming/previous sessions.
---
src/app/dashboard/dashboard-content.tsx | 8 +-
.../ui/dashboard/coaching-session-list.tsx | 173 +++++++++++++-----
src/types/coaching-session.ts | 51 +++++-
3 files changed, 177 insertions(+), 55 deletions(-)
diff --git a/src/app/dashboard/dashboard-content.tsx b/src/app/dashboard/dashboard-content.tsx
index f1282697..96f0dce7 100644
--- a/src/app/dashboard/dashboard-content.tsx
+++ b/src/app/dashboard/dashboard-content.tsx
@@ -35,7 +35,9 @@ function DashboardContainer({
export function DashboardContent() {
const [dialogOpen, setDialogOpen] = useState(false);
- const [sessionToEdit, setSessionToEdit] = useState();
+ const [sessionToEdit, setSessionToEdit] = useState<
+ CoachingSession | undefined
+ >();
const handleOpenDialog = (session?: CoachingSession) => {
setSessionToEdit(session);
@@ -54,8 +56,8 @@ export function DashboardContent() {
handleOpenDialog()} />
-
-
+
+ {/* */}
diff --git a/src/components/ui/dashboard/coaching-session-list.tsx b/src/components/ui/dashboard/coaching-session-list.tsx
index 5aca6dec..ab83f97c 100644
--- a/src/components/ui/dashboard/coaching-session-list.tsx
+++ b/src/components/ui/dashboard/coaching-session-list.tsx
@@ -9,14 +9,20 @@ import { useCoachingSessionList } from "@/lib/api/coaching-sessions";
import { useCoachingSessionMutation } from "@/lib/api/coaching-sessions";
import { CoachingSession as CoachingSessionComponent } from "@/components/ui/coaching-session";
import { DateTime } from "ts-luxon";
-import type { CoachingSession } from "@/types/coaching-session";
-import { Id } from "@/types/general";
+import {
+ filterAndSortCoachingSessions,
+ type CoachingSession,
+} from "@/types/coaching-session";
+import { Id, SortOrder } from "@/types/general";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
interface CoachingSessionListProps {
onUpdateSession: (session: CoachingSession) => void;
}
-export default function CoachingSessionList({ onUpdateSession }: CoachingSessionListProps) {
+export default function CoachingSessionList({
+ onUpdateSession,
+}: CoachingSessionListProps) {
const { currentCoachingRelationshipId } = useCoachingRelationshipStateStore(
(state) => state
);
@@ -47,12 +53,18 @@ export default function CoachingSessionList({ onUpdateSession }: CoachingSession
}
};
- const [sortByDate, setSortByDate] = useState(true);
+ // const [sortByDate, setSortByDate] = useState(true);
- const sortedSessions = coachingSessions
- ? [...coachingSessions].sort((a, b) => {
- return new Date(b.date).getTime() - new Date(a.date).getTime();
- })
+ const upcomingSessions = coachingSessions
+ ? filterAndSortCoachingSessions(coachingSessions, SortOrder.Ascending, true)
+ : [];
+
+ const previousSessions = coachingSessions
+ ? filterAndSortCoachingSessions(
+ coachingSessions,
+ SortOrder.Descending,
+ false
+ )
: [];
if (isLoadingCoachingSessions) return Loading coaching sessions...
;
@@ -60,33 +72,9 @@ export default function CoachingSessionList({ onUpdateSession }: CoachingSession
return Error loading coaching sessions
;
return (
-
-
-
-
- Coaching Sessions
-
-
-
-
-
-
+
+
+ Coaching Sessions
{!currentCoachingRelationshipId ? (
@@ -96,18 +84,113 @@ export default function CoachingSessionList({ onUpdateSession }: CoachingSession
) : (
-
- {sortedSessions.map((coachingSession) => (
- onUpdateSession(coachingSession)}
- onDelete={() => handleDeleteCoachingSession(coachingSession.id)}
- />
- ))}
-
+
+
+ Upcoming
+ Previous
+
+
+ {/*
+
+
+
*/}
+
+ {upcomingSessions.map((coachingSession) => (
+ onUpdateSession(coachingSession)}
+ onDelete={() =>
+ handleDeleteCoachingSession(coachingSession.id)
+ }
+ />
+ ))}
+
+
+
+
+ {previousSessions.map((coachingSession) => (
+ onUpdateSession(coachingSession)}
+ onDelete={() =>
+ handleDeleteCoachingSession(coachingSession.id)
+ }
+ />
+ ))}
+
+
+
)}
);
+ // return (
+ //
+ //
+ //
+ //
+ // Coaching Sessions
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ //
+ // {!currentCoachingRelationshipId ? (
+ //
+ //
+ // Choose a Relationship to view Coaching Sessions
+ //
+ //
+ // ) : (
+ //
+ // {sortedSessions.map((coachingSession) => (
+ // onUpdateSession(coachingSession)}
+ // onDelete={() => handleDeleteCoachingSession(coachingSession.id)}
+ // />
+ // ))}
+ //
+ // )}
+ //
+ //
+ // );
}
diff --git a/src/types/coaching-session.ts b/src/types/coaching-session.ts
index 348f09ae..e316a257 100644
--- a/src/types/coaching-session.ts
+++ b/src/types/coaching-session.ts
@@ -32,26 +32,63 @@ export function isCoachingSessionArray(
return Array.isArray(value) && value.every(isCoachingSession);
}
-export function sortCoachingSessionArray(
+export function filterAndSortCoachingSessions(
sessions: CoachingSession[],
- order: SortOrder
+ order: SortOrder,
+ returnUpcoming: boolean
): CoachingSession[] {
- if (order == SortOrder.Ascending) {
- sessions.sort(
+ const now = new Date();
+
+ // Filter sessions based on the `showUpcoming` parameter
+ const filteredSessions = sessions.filter((session) => {
+ const sessionDate = new Date(session.date.toString());
+ if (returnUpcoming) {
+ // Include sessions today that haven't started yet or are in the future
+ return sessionDate >= now;
+ } else {
+ // Include past sessions only
+ return sessionDate < now;
+ }
+ });
+
+ // Sort the filtered sessions based on the order parameter
+ if (order === SortOrder.Ascending) {
+ filteredSessions.sort(
(a, b) =>
new Date(a.date.toString()).getTime() -
new Date(b.date.toString()).getTime()
);
- } else if (order == SortOrder.Descending) {
- sessions.sort(
+ } else if (order === SortOrder.Descending) {
+ filteredSessions.sort(
(a, b) =>
new Date(b.date.toString()).getTime() -
new Date(a.date.toString()).getTime()
);
}
- return sessions;
+
+ return filteredSessions;
}
+// export function sortCoachingSessionArray(
+// sessions: CoachingSession[],
+// order: SortOrder
+// ): CoachingSession[] {
+// if (order == SortOrder.Ascending) {
+// sessions.sort(
+// (a, b) =>
+// new Date(a.date.toString()).getTime() -
+// new Date(b.date.toString()).getTime()
+// );
+// } else if (order == SortOrder.Descending) {
+// sessions.sort(
+// (a, b) =>
+// new Date(b.date.toString()).getTime() -
+// new Date(a.date.toString()).getTime()
+// );
+// }
+// return sessions;
+// }
+
export function getCoachingSessionById(
id: string,
sessions: CoachingSession[]
From 39821099a3590c128d239ebd26526251648b0969 Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Mon, 7 Apr 2025 16:38:08 -0500
Subject: [PATCH 2/8] Move the CoachingSessionSelector into the
CoachingSessionList, refactor the layout of this component on the Dashboard
page, and make logout more robust.
---
src/app/dashboard/dashboard-content.tsx | 14 +-
.../ui/coaching-relationship-selector.tsx | 49 +--
src/components/ui/dashboard/add-entities.tsx | 11 +-
.../ui/dashboard/coaching-session-list.tsx | 139 +++------
src/components/ui/main-nav-menu.tsx | 278 ------------------
src/components/ui/user-nav.tsx | 20 +-
src/lib/api/users.ts | 2 +-
src/middleware.ts | 6 +-
8 files changed, 100 insertions(+), 419 deletions(-)
delete mode 100644 src/components/ui/main-nav-menu.tsx
diff --git a/src/app/dashboard/dashboard-content.tsx b/src/app/dashboard/dashboard-content.tsx
index 96f0dce7..c1a5da09 100644
--- a/src/app/dashboard/dashboard-content.tsx
+++ b/src/app/dashboard/dashboard-content.tsx
@@ -20,8 +20,6 @@ function DashboardContainer({
"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
@@ -51,13 +49,11 @@ export function DashboardContent() {
return (
<>
-
-
-
handleOpenDialog()} />
-
-
-
- {/* */}
+
+ handleOpenDialog()}
+ />
diff --git a/src/components/ui/coaching-relationship-selector.tsx b/src/components/ui/coaching-relationship-selector.tsx
index cb75ddab..09fb8ad0 100644
--- a/src/components/ui/coaching-relationship-selector.tsx
+++ b/src/components/ui/coaching-relationship-selector.tsx
@@ -16,6 +16,7 @@ import { useCoachingRelationshipStateStore } from "@/lib/providers/coaching-rela
import { useCoachingSessionStateStore } from "@/lib/providers/coaching-session-state-store-provider";
interface CoachingRelationshipsSelectorProps extends PopoverProps {
+ className?: string;
/// The Organization's Id for which to get a list of associated CoachingRelationships
organizationId: Id;
/// Disable the component from interaction with the user
@@ -63,6 +64,7 @@ function CoachingRelationshipsSelectItems({
}
export default function CoachingRelationshipSelector({
+ className,
organizationId,
disabled,
onSelect,
@@ -101,29 +103,32 @@ export default function CoachingRelationshipSelector({
? getCurrentCoachingRelationship(currentCoachingRelationshipId)
: null;
- const displayValue = currentRelationship ? (
- <>
- {currentRelationship.coach_first_name}{" "}
- {currentRelationship.coach_last_name} ->{" "}
- {currentRelationship.coachee_first_name}{" "}
- {currentRelationship.coachee_last_name}
- >
- ) : undefined;
+ const displayValue =
+ currentRelationship && currentRelationship.id ? (
+ <>
+ {currentRelationship.coach_first_name}{" "}
+ {currentRelationship.coach_last_name} ->{" "}
+ {currentRelationship.coachee_first_name}{" "}
+ {currentRelationship.coachee_last_name}
+ >
+ ) : undefined;
return (
-
+
+
+
);
}
diff --git a/src/components/ui/dashboard/add-entities.tsx b/src/components/ui/dashboard/add-entities.tsx
index dfe2cf38..38ccc504 100644
--- a/src/components/ui/dashboard/add-entities.tsx
+++ b/src/components/ui/dashboard/add-entities.tsx
@@ -5,12 +5,17 @@ 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";
+import { cn } from "@/components/lib/utils";
interface AddEntitiesProps {
+ className?: string;
onCreateSession: () => void;
}
-export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
+export default function AddEntities({
+ className,
+ onCreateSession,
+}: AddEntitiesProps) {
const router = useRouter();
const { currentOrganizationId } = useOrganizationStateStore((state) => state);
const { isCoach } = useAuthStore((state) => state);
@@ -20,7 +25,7 @@ export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
};
return (
-
+
Add New
@@ -37,4 +42,4 @@ export default function AddEntities({ onCreateSession }: AddEntitiesProps) {
);
-}
\ No newline at end of file
+}
diff --git a/src/components/ui/dashboard/coaching-session-list.tsx b/src/components/ui/dashboard/coaching-session-list.tsx
index ab83f97c..71d4c330 100644
--- a/src/components/ui/dashboard/coaching-session-list.tsx
+++ b/src/components/ui/dashboard/coaching-session-list.tsx
@@ -1,9 +1,6 @@
"use client";
-import { useState } from "react";
-import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { ArrowUpDown } from "lucide-react";
import { useCoachingRelationshipStateStore } from "@/lib/providers/coaching-relationship-state-store-provider";
import { useCoachingSessionList } from "@/lib/api/coaching-sessions";
import { useCoachingSessionMutation } from "@/lib/api/coaching-sessions";
@@ -15,14 +12,20 @@ import {
} from "@/types/coaching-session";
import { Id, SortOrder } from "@/types/general";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import CoachingRelationshipSelector from "../coaching-relationship-selector";
+import { useOrganizationStateStore } from "@/lib/providers/organization-state-store-provider";
+import { cn } from "@/components/lib/utils";
interface CoachingSessionListProps {
+ className?: string;
onUpdateSession: (session: CoachingSession) => void;
}
export default function CoachingSessionList({
+ className,
onUpdateSession,
}: CoachingSessionListProps) {
+ const { currentOrganizationId } = useOrganizationStateStore((state) => state);
const { currentCoachingRelationshipId } = useCoachingRelationshipStateStore(
(state) => state
);
@@ -53,8 +56,6 @@ export default function CoachingSessionList({
}
};
- // const [sortByDate, setSortByDate] = useState(true);
-
const upcomingSessions = coachingSessions
? filterAndSortCoachingSessions(coachingSessions, SortOrder.Ascending, true)
: [];
@@ -67,49 +68,42 @@ export default function CoachingSessionList({
)
: [];
+ let noCoachingSessions = (
+
+
+ Select a coaching relationship to view Coaching Sessions
+
+
+ );
+
if (isLoadingCoachingSessions) return Loading coaching sessions...
;
if (isErrorCoachingSessions)
return Error loading coaching sessions
;
return (
-
+
- Coaching Sessions
+
+
+
- {!currentCoachingRelationshipId ? (
-
-
- Choose a Relationship to view Coaching Sessions
-
-
- ) : (
-
-
- Upcoming
- Previous
-
-
- {/*
-
-
-
*/}
+
+
+ Upcoming
+ Previous
+
+
+ {!currentCoachingRelationshipId ? (
+ noCoachingSessions
+ ) : (
{upcomingSessions.map((coachingSession) => (
))}
-
-
+ )}
+
+
+ {!currentCoachingRelationshipId ? (
+ noCoachingSessions
+ ) : (
{previousSessions.map((coachingSession) => (
))}
-
-
- )}
+ )}
+
+
);
- // return (
- //
- //
- //
- //
- // Coaching Sessions
- //
- //
- //
- //
- //
- //
- //
- //
- // {!currentCoachingRelationshipId ? (
- //
- //
- // Choose a Relationship to view Coaching Sessions
- //
- //
- // ) : (
- //
- // {sortedSessions.map((coachingSession) => (
- // onUpdateSession(coachingSession)}
- // onDelete={() => handleDeleteCoachingSession(coachingSession.id)}
- // />
- // ))}
- //
- // )}
- //
- //
- // );
}
diff --git a/src/components/ui/main-nav-menu.tsx b/src/components/ui/main-nav-menu.tsx
deleted file mode 100644
index 3c8fecb9..00000000
--- a/src/components/ui/main-nav-menu.tsx
+++ /dev/null
@@ -1,278 +0,0 @@
-"use client";
-
-import { cn } from "@/components/lib/utils";
-
-import { Dialog } from "@radix-ui/react-dialog";
-
-import { Button } from "@/components/ui/button";
-import {
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
-} from "@/components/ui/dialog";
-import { Icons } from "@/components/ui/icons";
-import {
- NavigationMenu,
- NavigationMenuContent,
- NavigationMenuItem,
- NavigationMenuLink,
- NavigationMenuList,
- NavigationMenuTrigger,
-} from "@/components/ui/navigation-menu";
-import { PresetSelector } from "@/components/ui/preset-selector";
-
-import { current, future, past } from "../../data/presets";
-
-import { ChevronDownIcon } from "@radix-ui/react-icons";
-
-import {
- Card,
- CardContent,
- CardDescription,
- CardHeader,
- CardTitle,
-} from "@/components/ui/card";
-import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
-} from "@/components/ui/command";
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from "@/components/ui/popover";
-import { siteConfig } from "@/site.config";
-import { forwardRef, useState } from "react";
-import { useOrganizationStateStore } from "@/lib/providers/organization-state-store-provider";
-
-export function MainNavMenu() {
- const [open, setIsOpen] = useState(false);
- const { currentOrganizationId, getCurrentOrganization } =
- useOrganizationStateStore((state) => state);
-
- const organization = getCurrentOrganization(currentOrganizationId);
-
- return (
- <>
-
-
-
-
-
- {organization.name.length > 0
- ? organization.name
- : siteConfig.name}
-
-
-
-
- -
-
-
-
-
- {organization.name.length > 0
- ? organization.name
- : siteConfig.name}
-
-
- {siteConfig.description}
-
-
-
-
-
- {/* Hidden for MVP */}
-
-
- Organization & Relationship
-
- Set your current organization and coaching relationship.
-
-
-
-
-
-
-
-
-
-
-
-
-
- No roles found.
-
-
- Viewer
-
- Can view and comment.
-
-
-
- Developer
-
- Can view, comment and edit.
-
-
-
- Billing
-
- Can view, comment and manage billing.
-
-
-
- Owner
-
- Admin-level access to all resources.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No roles found.
-
-
- Viewer
-
- Can view and comment.
-
-
-
- Developer
-
- Can view, comment and edit.
-
-
-
- Billing
-
- Can view, comment and manage billing.
-
-
-
- Owner
-
- Admin-level access to all resources.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
-
-const ListItem = forwardRef<
- React.ElementRef<"a">,
- React.ComponentPropsWithoutRef<"a">
->(({ className, title, children, ...props }, ref) => {
- return (
-
-
-
- {title}
-
- {children}
-
-
-
-
- );
-});
-ListItem.displayName = "ListItem";
diff --git a/src/components/ui/user-nav.tsx b/src/components/ui/user-nav.tsx
index 0d3ad7fc..275fd188 100644
--- a/src/components/ui/user-nav.tsx
+++ b/src/components/ui/user-nav.tsx
@@ -40,9 +40,6 @@ export function UserNav() {
async function logout_user() {
try {
- console.trace("Deleting active user session: ", userSession.id);
- await deleteUserSession(userSession.id);
-
console.trace("Resetting CoachingSessionStateStore state");
resetCoachingSessionState();
@@ -52,12 +49,21 @@ export function UserNav() {
console.trace("Resetting OrganizationStateStore state");
resetOrganizationState();
+ console.trace(
+ "Deleting current user session from backend: ",
+ userSession.id
+ );
+ await deleteUserSession(userSession.id);
+ } catch (err) {
+ console.warn("Error while logging out session: ", userSession.id, err);
+ } finally {
+ // Ensure we still log out of the frontend even if the backend request
+ // to delete the user session fails.
console.trace("Resetting AuthStore state");
logout();
-
- router.push("/");
- } catch (err) {
- console.error("Error while logging out session: ", userSession.id, err);
+ console.debug("Navigating to /");
+ await router.push("/");
+ console.debug("Navigation to / completed successfully.");
}
}
diff --git a/src/lib/api/users.ts b/src/lib/api/users.ts
index 7385ba2e..7498266f 100644
--- a/src/lib/api/users.ts
+++ b/src/lib/api/users.ts
@@ -55,7 +55,7 @@ export const UserApi = {
* @param userId The ID of the user to delete
* @returns Promise resolving to the deleted User object
*/
- deleteNested: async (_entityId: Id, userId: Id): Promise => {
+ deleteNested: async (_entityId: Id, _userId: Id): Promise => {
throw new Error("Delete nested operation not implemented");
},
};
diff --git a/src/middleware.ts b/src/middleware.ts
index 983f80b7..f35ede54 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -19,18 +19,18 @@ export default async function middleware(req: NextRequest) {
// 3. Get the session from the cookie
const sessionCookie = req.cookies.get("id");
- const session = sessionCookie?.value;
+ const validSession = sessionCookie?.value;
// 4. Redirect to / if the user is not authenticated
// 4b. TODO: Check session validity/expiration?
- if (isProtectedRoute && !session) {
+ if (isProtectedRoute && !validSession) {
return NextResponse.redirect(new URL("/", req.nextUrl));
}
// 5. Redirect to /dashboard if the user is authenticated
if (
isPublicRoute &&
- session &&
+ validSession &&
!req.nextUrl.pathname.startsWith("/dashboard")
) {
return NextResponse.redirect(new URL("/dashboard", req.nextUrl));
From c851b3a279318fc170e2363693694fc1283baa39 Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Mon, 7 Apr 2025 16:44:39 -0500
Subject: [PATCH 3/8] Clean up the select coaching relationship placeholder
text to be clearer and nicer to read.
---
src/components/ui/dashboard/coaching-session-list.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/ui/dashboard/coaching-session-list.tsx b/src/components/ui/dashboard/coaching-session-list.tsx
index 71d4c330..d058ec57 100644
--- a/src/components/ui/dashboard/coaching-session-list.tsx
+++ b/src/components/ui/dashboard/coaching-session-list.tsx
@@ -71,7 +71,7 @@ export default function CoachingSessionList({
let noCoachingSessions = (
- Select a coaching relationship to view Coaching Sessions
+ Select a coaching relationship to view your coaching sessions.
);
From 28cd840e7d4b83d035c37c1a50ac9863abbc5c36 Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Mon, 7 Apr 2025 17:13:27 -0500
Subject: [PATCH 4/8] We no longer need to debug print relationships.
---
src/components/ui/coaching-relationship-selector.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/ui/coaching-relationship-selector.tsx b/src/components/ui/coaching-relationship-selector.tsx
index 09fb8ad0..85c780a9 100644
--- a/src/components/ui/coaching-relationship-selector.tsx
+++ b/src/components/ui/coaching-relationship-selector.tsx
@@ -49,8 +49,6 @@ function CoachingRelationshipsSelectItems({
if (isError) return Error loading coaching relationships
;
if (!relationships?.length) return No coaching relationships found
;
- console.debug(`relationships: ${JSON.stringify(relationships)}`);
-
return (
<>
{relationships.map((rel) => (
From e29da278817688d65e379259ab8b4cf6b43037da Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Mon, 7 Apr 2025 17:14:11 -0500
Subject: [PATCH 5/8] We no longer need to debug print relationships in
useEffect either.
---
src/components/ui/coaching-relationship-selector.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/components/ui/coaching-relationship-selector.tsx b/src/components/ui/coaching-relationship-selector.tsx
index 85c780a9..f425ac68 100644
--- a/src/components/ui/coaching-relationship-selector.tsx
+++ b/src/components/ui/coaching-relationship-selector.tsx
@@ -39,9 +39,6 @@ function CoachingRelationshipsSelectItems({
// Be sure to cache the list of current coaching relationships in the CoachingRelationshipStateStore
useEffect(() => {
if (!relationships.length) return;
- console.debug(
- `relationships (useEffect): ${JSON.stringify(relationships)}`
- );
setCurrentCoachingRelationships(relationships);
}, [relationships, setCurrentCoachingRelationships]);
From 6e64e9954bc0a933339dfc3dc39432564590df70 Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Mon, 7 Apr 2025 17:43:33 -0500
Subject: [PATCH 6/8] Handle loading/loading error cases better for the
coaching session list.
---
src/app/dashboard/dashboard-content.tsx | 1 -
.../ui/coaching-relationship-selector.tsx | 3 +-
.../ui/dashboard/coaching-session-list.tsx | 30 +++++++++++++++----
3 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/src/app/dashboard/dashboard-content.tsx b/src/app/dashboard/dashboard-content.tsx
index c1a5da09..3386ff92 100644
--- a/src/app/dashboard/dashboard-content.tsx
+++ b/src/app/dashboard/dashboard-content.tsx
@@ -3,7 +3,6 @@
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";
diff --git a/src/components/ui/coaching-relationship-selector.tsx b/src/components/ui/coaching-relationship-selector.tsx
index f425ac68..1ca7f24f 100644
--- a/src/components/ui/coaching-relationship-selector.tsx
+++ b/src/components/ui/coaching-relationship-selector.tsx
@@ -14,6 +14,7 @@ import { useEffect } from "react";
import { useAuthStore } from "@/lib/providers/auth-store-provider";
import { useCoachingRelationshipStateStore } from "@/lib/providers/coaching-relationship-state-store-provider";
import { useCoachingSessionStateStore } from "@/lib/providers/coaching-session-state-store-provider";
+import { cn } from "../lib/utils";
interface CoachingRelationshipsSelectorProps extends PopoverProps {
className?: string;
@@ -109,7 +110,7 @@ export default function CoachingRelationshipSelector({
) : undefined;
return (
-
+
+ );
+
let noCoachingSessions = (
@@ -76,9 +84,13 @@ export default function CoachingSessionList({
);
- if (isLoadingCoachingSessions) return
Loading coaching sessions...
;
- if (isErrorCoachingSessions)
- return
Error loading coaching sessions
;
+ let errorLoadingCoachingSessions = (
+
+
+ There was an error trying to load your coaching sessions.
+
+
+ );
return (
@@ -101,7 +113,11 @@ export default function CoachingSessionList({
Previous
- {!currentCoachingRelationshipId ? (
+ {isLoadingCoachingSessions ? (
+ loadingCoachingSessions
+ ) : isErrorCoachingSessions ? (
+ errorLoadingCoachingSessions
+ ) : !currentCoachingRelationshipId ? (
noCoachingSessions
) : (
@@ -119,7 +135,11 @@ export default function CoachingSessionList({
)}
- {!currentCoachingRelationshipId ? (
+ {isLoadingCoachingSessions ? (
+ loadingCoachingSessions
+ ) : isErrorCoachingSessions ? (
+ errorLoadingCoachingSessions
+ ) : !currentCoachingRelationshipId ? (
noCoachingSessions
) : (
From 0630dbb88d1e01c604d4b5a66dc33387eb24f3ca Mon Sep 17 00:00:00 2001
From: Caleb Bourg
Date: Tue, 8 Apr 2025 09:57:09 -0400
Subject: [PATCH 7/8] use edit and delete language
---
src/components/ui/coaching-session.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/ui/coaching-session.tsx b/src/components/ui/coaching-session.tsx
index 2b59b756..0b381531 100644
--- a/src/components/ui/coaching-session.tsx
+++ b/src/components/ui/coaching-session.tsx
@@ -62,11 +62,11 @@ const CoachingSession: React.FC = ({
- Update Session
+ Edit
{isCoach && (
- Delete Session
+ Delete
)}
From 66000f87e5acce50a14607a7607143563447f406 Mon Sep 17 00:00:00 2001
From: Jim Hodapp
Date: Tue, 8 Apr 2025 17:12:27 -0500
Subject: [PATCH 8/8] Address review comments
---
src/middleware.ts | 6 +++---
src/types/coaching-session.ts | 20 --------------------
2 files changed, 3 insertions(+), 23 deletions(-)
diff --git a/src/middleware.ts b/src/middleware.ts
index f35ede54..b39f292d 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -19,18 +19,18 @@ export default async function middleware(req: NextRequest) {
// 3. Get the session from the cookie
const sessionCookie = req.cookies.get("id");
- const validSession = sessionCookie?.value;
+ const isValidSession = sessionCookie?.value;
// 4. Redirect to / if the user is not authenticated
// 4b. TODO: Check session validity/expiration?
- if (isProtectedRoute && !validSession) {
+ if (isProtectedRoute && !isValidSession) {
return NextResponse.redirect(new URL("/", req.nextUrl));
}
// 5. Redirect to /dashboard if the user is authenticated
if (
isPublicRoute &&
- validSession &&
+ isValidSession &&
!req.nextUrl.pathname.startsWith("/dashboard")
) {
return NextResponse.redirect(new URL("/dashboard", req.nextUrl));
diff --git a/src/types/coaching-session.ts b/src/types/coaching-session.ts
index e316a257..a29baf2a 100644
--- a/src/types/coaching-session.ts
+++ b/src/types/coaching-session.ts
@@ -69,26 +69,6 @@ export function filterAndSortCoachingSessions(
return filteredSessions;
}
-// export function sortCoachingSessionArray(
-// sessions: CoachingSession[],
-// order: SortOrder
-// ): CoachingSession[] {
-// if (order == SortOrder.Ascending) {
-// sessions.sort(
-// (a, b) =>
-// new Date(a.date.toString()).getTime() -
-// new Date(b.date.toString()).getTime()
-// );
-// } else if (order == SortOrder.Descending) {
-// sessions.sort(
-// (a, b) =>
-// new Date(b.date.toString()).getTime() -
-// new Date(a.date.toString()).getTime()
-// );
-// }
-// return sessions;
-// }
-
export function getCoachingSessionById(
id: string,
sessions: CoachingSession[]