Skip to content

Commit 79e6417

Browse files
committed
Set dynamic coaching session titles
1 parent 29f47cd commit 79e6417

File tree

11 files changed

+375
-53
lines changed

11 files changed

+375
-53
lines changed

src/app/coaching-sessions/[id]/page.tsx

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ import { ActionsList } from "@/components/ui/coaching-sessions/actions-list";
6060
import { Action } from "@/types/action";
6161
import { createAction, deleteAction, updateAction } from "@/lib/api/actions";
6262
import { DateTime } from "ts-luxon";
63+
import { CoachingSessionTitle } from "@/components/ui/coaching-sessions/coaching-session-title";
64+
import { SessionTitle, SessionTitleStyle } from "@/types/session-title";
6365

6466
// export const metadata: Metadata = {
6567
// title: "Coaching Session",
@@ -72,26 +74,28 @@ export default function CoachingSessionsPage() {
7274
const [note, setNote] = useState<string>("");
7375
const [syncStatus, setSyncStatus] = useState<string>("");
7476
const { userId } = useAuthStore((state) => state);
75-
const { coachingSessionId } = useAppStateStore((state) => state);
77+
const { coachingSession, coachingRelationship } = useAppStateStore(
78+
(state) => state
79+
);
7680

7781
useEffect(() => {
7882
async function fetchNote() {
79-
if (!coachingSessionId) {
83+
if (!coachingSession.id) {
8084
console.error(
81-
"Failed to fetch Note since coachingSessionId is not set."
85+
"Failed to fetch Note since coachingSession.id is not set."
8286
);
8387
return;
8488
}
8589

86-
await fetchNotesByCoachingSessionId(coachingSessionId)
90+
await fetchNotesByCoachingSessionId(coachingSession.id)
8791
.then((notes) => {
8892
const note = notes[0];
8993
if (notes.length > 0) {
9094
console.trace("note: " + noteToString(note));
9195
setNoteId(note.id);
9296
setNote(note.body);
9397
} else {
94-
console.trace("No Notes associated with this coachingSessionId");
98+
console.trace("No Notes associated with this coachingSession.id");
9599
}
96100
})
97101
.catch((err) => {
@@ -101,11 +105,11 @@ export default function CoachingSessionsPage() {
101105
});
102106
}
103107
fetchNote();
104-
}, [coachingSessionId, noteId]);
108+
}, [coachingSession.id, noteId]);
105109

106110
const handleAgreementAdded = (body: string): Promise<Agreement> => {
107111
// Calls the backend endpoint that creates and stores a full Agreement entity
108-
return createAgreement(coachingSessionId, userId, body)
112+
return createAgreement(coachingSession.id, userId, body)
109113
.then((agreement) => {
110114
return agreement;
111115
})
@@ -116,7 +120,7 @@ export default function CoachingSessionsPage() {
116120
};
117121

118122
const handleAgreementEdited = (id: Id, body: string): Promise<Agreement> => {
119-
return updateAgreement(id, coachingSessionId, userId, body)
123+
return updateAgreement(id, coachingSession.id, userId, body)
120124
.then((agreement) => {
121125
return agreement;
122126
})
@@ -143,7 +147,7 @@ export default function CoachingSessionsPage() {
143147
dueBy: DateTime
144148
): Promise<Action> => {
145149
// Calls the backend endpoint that creates and stores a full Action entity
146-
return createAction(coachingSessionId, body, status, dueBy)
150+
return createAction(coachingSession.id, body, status, dueBy)
147151
.then((action) => {
148152
return action;
149153
})
@@ -159,7 +163,7 @@ export default function CoachingSessionsPage() {
159163
status: ActionStatus,
160164
dueBy: DateTime
161165
): Promise<Action> => {
162-
return updateAction(id, coachingSessionId, body, status, dueBy)
166+
return updateAction(id, coachingSession.id, body, status, dueBy)
163167
.then((action) => {
164168
return action;
165169
})
@@ -183,8 +187,8 @@ export default function CoachingSessionsPage() {
183187
const handleInputChange = (value: string) => {
184188
setNote(value);
185189

186-
if (noteId && coachingSessionId && userId) {
187-
updateNote(noteId, coachingSessionId, userId, value)
190+
if (noteId && coachingSession.id && userId) {
191+
updateNote(noteId, coachingSession.id, userId, value)
188192
.then((note) => {
189193
console.trace("Updated Note: " + noteToString(note));
190194
setSyncStatus("All changes saved");
@@ -193,8 +197,8 @@ export default function CoachingSessionsPage() {
193197
setSyncStatus("Failed to save changes");
194198
console.error("Failed to update Note: " + err);
195199
});
196-
} else if (!noteId && coachingSessionId && userId) {
197-
createNote(coachingSessionId, userId, value)
200+
} else if (!noteId && coachingSession.id && userId) {
201+
createNote(coachingSession.id, userId, value)
198202
.then((note) => {
199203
console.trace("Newly created Note: " + noteToString(note));
200204
setNoteId(note.id);
@@ -206,7 +210,7 @@ export default function CoachingSessionsPage() {
206210
});
207211
} else {
208212
console.error(
209-
"Could not update or create a Note since coachingSessionId or userId are not set."
213+
"Could not update or create a Note since coachingSession.id or userId are not set."
210214
);
211215
}
212216
};
@@ -215,11 +219,21 @@ export default function CoachingSessionsPage() {
215219
setSyncStatus("");
216220
};
217221

222+
const handleTitleRender = (sessionTitle: string) => {
223+
document.title = sessionTitle;
224+
};
225+
218226
return (
219227
<>
220-
<div className="hidden h-full flex-col md:flex">
228+
<div className="h-full flex-col md:flex">
221229
<div className="flex flex-col items-start justify-between space-y-2 py-4 px-4 sm:flex-row sm:items-center sm:space-y-0 md:h-16">
222-
<h4 className="w-16 md:w-32 lg:w-48 font-semibold">Session Title</h4>
230+
<CoachingSessionTitle
231+
coachingSession={coachingSession}
232+
coachingRelationship={coachingRelationship}
233+
locale={siteConfig.locale}
234+
style={SessionTitleStyle.CoachFirstCoacheeFirstDate}
235+
onRender={handleTitleRender}
236+
></CoachingSessionTitle>
223237
<div className="ml-auto flex w-full space-x-2 sm:justify-end">
224238
<PresetSelector current={current} future={future} past={past} />
225239
<PresetActions />
@@ -289,7 +303,7 @@ export default function CoachingSessionsPage() {
289303
<TabsContent value="agreements">
290304
<div className="w-full">
291305
<AgreementsList
292-
coachingSessionId={coachingSessionId}
306+
coachingSessionId={coachingSession.id}
293307
userId={userId}
294308
locale={siteConfig.locale}
295309
onAgreementAdded={handleAgreementAdded}
@@ -301,7 +315,7 @@ export default function CoachingSessionsPage() {
301315
<TabsContent value="actions">
302316
<div className="w-full">
303317
<ActionsList
304-
coachingSessionId={coachingSessionId}
318+
coachingSessionId={coachingSession.id}
305319
userId={userId}
306320
locale={siteConfig.locale}
307321
onActionAdded={handleActionAdded}

src/components/ui/coaching-sessions/actions-list.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,12 @@ const ActionsList: React.FC<{
201201

202202
useEffect(() => {
203203
async function loadActions() {
204-
if (!coachingSessionId) return;
204+
if (!coachingSessionId) {
205+
console.error(
206+
"Failed to fetch Actions since coachingSession.id is not set."
207+
);
208+
return;
209+
}
205210

206211
await fetchActionsByCoachingSessionId(coachingSessionId)
207212
.then((actions) => {

src/components/ui/coaching-sessions/agreements-list.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@ import {
1919
} from "@/components/ui/dropdown-menu";
2020
import { MoreHorizontal, ArrowUpDown, Save } from "lucide-react";
2121
import { Id } from "@/types/general";
22-
import {
23-
createAgreement,
24-
deleteAgreement as deleteAgreementApi,
25-
updateAgreement as updateAgreementApi,
26-
fetchAgreementsByCoachingSessionId,
27-
} from "@/lib/api/agreements";
22+
import { fetchAgreementsByCoachingSessionId } from "@/lib/api/agreements";
2823
import { Agreement, agreementToString } from "@/types/agreement";
2924
import { DateTime } from "ts-luxon";
3025
import { siteConfig } from "@/site.config";
@@ -158,7 +153,12 @@ const AgreementsList: React.FC<{
158153

159154
useEffect(() => {
160155
async function loadAgreements() {
161-
if (!coachingSessionId) return;
156+
if (!coachingSessionId) {
157+
console.error(
158+
"Failed to fetch Agreements since coachingSession.id is not set."
159+
);
160+
return;
161+
}
162162

163163
await fetchAgreementsByCoachingSessionId(coachingSessionId)
164164
.then((agreements) => {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"use client";
2+
3+
import { useEffect, useState } from "react";
4+
import {
5+
generateSessionTitle,
6+
SessionTitle,
7+
SessionTitleStyle,
8+
} from "@/types/session-title";
9+
import { CoachingRelationshipWithUserNames } from "@/types/coaching_relationship_with_user_names";
10+
import { CoachingSession } from "@/types/coaching-session";
11+
12+
const CoachingSessionTitle: React.FC<{
13+
coachingSession: CoachingSession;
14+
coachingRelationship: CoachingRelationshipWithUserNames;
15+
locale: string | "us";
16+
style: SessionTitleStyle;
17+
onRender: (sessionTitle: string) => void;
18+
}> = ({ coachingSession, coachingRelationship, locale, style, onRender }) => {
19+
const [sessionTitle, setSessionTitle] = useState<SessionTitle>();
20+
21+
useEffect(() => {
22+
async function getSessionTitle() {
23+
const sessionTitle = generateSessionTitle(
24+
coachingSession,
25+
coachingRelationship,
26+
style,
27+
locale
28+
);
29+
setSessionTitle(sessionTitle);
30+
console.debug("sessionTitle: " + JSON.stringify(sessionTitle));
31+
onRender(sessionTitle.title);
32+
}
33+
34+
getSessionTitle();
35+
}, [coachingSession, coachingRelationship]);
36+
37+
return (
38+
<h4 className="font-semibold break-words w-full px-2 md:px-4 lg:px-6 md:text-clip">
39+
{sessionTitle?.title}
40+
</h4>
41+
);
42+
};
43+
44+
export { CoachingSessionTitle };

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

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ import { fetchCoachingRelationshipsWithUserNames } from "@/lib/api/coaching-rela
2323
import { fetchCoachingSessions } from "@/lib/api/coaching-sessions";
2424
import { fetchOrganizationsByUserId } from "@/lib/api/organizations";
2525
import { useAppStateStore } from "@/lib/providers/app-state-store-provider";
26-
import { CoachingSession } from "@/types/coaching-session";
27-
import { CoachingRelationshipWithUserNames } from "@/types/coaching_relationship_with_user_names";
26+
import {
27+
CoachingSession,
28+
coachingSessionToString,
29+
getCoachingSessionById,
30+
} from "@/types/coaching-session";
31+
import {
32+
CoachingRelationshipWithUserNames,
33+
coachingRelationshipWithUserNamesToString,
34+
getCoachingRelationshipById,
35+
} from "@/types/coaching_relationship_with_user_names";
2836
import { Id } from "@/types/general";
2937
import { Organization } from "@/types/organization";
3038
import Link from "next/link";
@@ -46,9 +54,15 @@ export function SelectCoachingSession({
4654
const { relationshipId, setRelationshipId } = useAppStateStore(
4755
(state) => state
4856
);
57+
const { coachingRelationship, setCoachingRelationship } = useAppStateStore(
58+
(state) => state
59+
);
4960
const { coachingSessionId, setCoachingSessionId } = useAppStateStore(
5061
(state) => state
5162
);
63+
const { coachingSession, setCoachingSession } = useAppStateStore(
64+
(state) => state
65+
);
5266

5367
const [organizations, setOrganizations] = useState<Organization[]>([]);
5468
const [coachingRelationships, setCoachingRelationships] = useState<
@@ -115,6 +129,31 @@ export function SelectCoachingSession({
115129
loadCoachingSessions();
116130
}, [relationshipId]);
117131

132+
const handleSetCoachingRelationship = (coachingRelationshipId: string) => {
133+
setRelationshipId(coachingRelationshipId);
134+
const coachingRelationship = getCoachingRelationshipById(
135+
coachingRelationshipId,
136+
coachingRelationships
137+
);
138+
console.debug(
139+
"coachingRelationship: " +
140+
coachingRelationshipWithUserNamesToString(coachingRelationship)
141+
);
142+
setCoachingRelationship(coachingRelationship);
143+
};
144+
145+
const handleSetCoachingSession = (coachingSessionId: string) => {
146+
setCoachingSessionId(coachingSessionId);
147+
const coachingSession = getCoachingSessionById(
148+
coachingSessionId,
149+
coachingSessions
150+
);
151+
console.debug(
152+
"coachingSession: " + coachingSessionToString(coachingSession)
153+
);
154+
setCoachingSession(coachingSession);
155+
};
156+
118157
return (
119158
<Card>
120159
<CardHeader>
@@ -154,7 +193,7 @@ export function SelectCoachingSession({
154193
defaultValue="caleb"
155194
disabled={!organizationId}
156195
value={relationshipId}
157-
onValueChange={setRelationshipId}
196+
onValueChange={handleSetCoachingRelationship}
158197
>
159198
<SelectTrigger id="relationship">
160199
<SelectValue placeholder="Select coaching relationship" />
@@ -181,7 +220,8 @@ export function SelectCoachingSession({
181220
defaultValue="today"
182221
disabled={!relationshipId}
183222
value={coachingSessionId}
184-
onValueChange={setCoachingSessionId}
223+
// TODO: set CoachingSession in the app state!!
224+
onValueChange={handleSetCoachingSession}
185225
>
186226
<SelectTrigger id="session">
187227
<SelectValue placeholder="Select coaching session" />

src/lib/api/coaching-relationships.ts

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,57 @@
33
import {
44
CoachingRelationshipWithUserNames,
55
coachingRelationshipsWithUserNamesToString,
6+
defaultCoachingRelationshipWithUserNames,
67
defaultCoachingRelationshipsWithUserNames,
8+
isCoachingRelationshipWithUserNames,
79
isCoachingRelationshipWithUserNamesArray
810
} from "@/types/coaching_relationship_with_user_names";
911
import { Id } from "@/types/general";
1012
import { AxiosError, AxiosResponse } from "axios";
1113

14+
export const fetchCoachingRelationshipWithUserNames = async (
15+
organization_id: Id,
16+
relationship_id: Id
17+
): Promise<CoachingRelationshipWithUserNames> => {
18+
const axios = require("axios");
19+
20+
var relationship: CoachingRelationshipWithUserNames = defaultCoachingRelationshipWithUserNames();
21+
var err: string = "";
22+
23+
const data = await axios
24+
.get(`http://localhost:4000/organizations/${organization_id}/coaching_relationships/${relationship_id}`, {
25+
withCredentials: true,
26+
setTimeout: 5000, // 5 seconds before timing out trying to log in with the backend
27+
headers: {
28+
"X-Version": "0.0.1",
29+
},
30+
})
31+
.then(function (response: AxiosResponse) {
32+
// handle success
33+
if (isCoachingRelationshipWithUserNames(response.data.data)) {
34+
relationship = response.data.data;
35+
}
36+
})
37+
.catch(function (error: AxiosError) {
38+
// handle error
39+
console.error(error.response?.status);
40+
if (error.response?.status == 401) {
41+
err = "Retrieval of CoachingRelationshipWithUserNames failed: unauthorized.";
42+
} else if (error.response?.status == 500) {
43+
err = "Retrieval of CoachingRelationshipWithUserNames failed, system error: " + error.response.data;
44+
} else {
45+
err = `Retrieval of CoachingRelationshipWithUserNames(` + relationship_id + `) failed: ` + error.response?.data;
46+
}
47+
});
48+
49+
if (err) {
50+
console.error(err);
51+
throw err;
52+
}
53+
54+
return relationship;
55+
};
56+
1257
export const fetchCoachingRelationshipsWithUserNames = async (
1358
organizationId: Id
1459
): Promise<[CoachingRelationshipWithUserNames[], string]> => {
@@ -52,4 +97,4 @@ export const fetchCoachingRelationshipsWithUserNames = async (
5297
});
5398

5499
return [relationships, err];
55-
};
100+
};

0 commit comments

Comments
 (0)