feat: implement auto-sharing functionality for session creation across motivators, weekly check-ins, and year reviews, enhancing collaboration capabilities

This commit is contained in:
Julien Froidefond
2026-02-17 15:11:46 +01:00
parent d05157d498
commit 520a1f4838
11 changed files with 133 additions and 24 deletions

View File

@@ -16,6 +16,16 @@ export async function createMotivatorSession(data: { title: string; participant:
try {
const motivatorSession = await motivatorsService.createMotivatorSession(session.user.id, data);
try {
await motivatorsService.shareMotivatorSession(
motivatorSession.id,
session.user.id,
data.participant,
'EDITOR'
);
} catch (shareError) {
console.error('Auto-share failed:', shareError);
}
revalidatePath('/motivators');
return { success: true, data: motivatorSession };
} catch (error) {

View File

@@ -24,6 +24,16 @@ export async function createWeeklyCheckInSession(data: {
session.user.id,
data
);
try {
await weeklyCheckInService.shareWeeklyCheckInSession(
weeklyCheckInSession.id,
session.user.id,
data.participant,
'EDITOR'
);
} catch (shareError) {
console.error('Auto-share failed:', shareError);
}
revalidatePath('/weekly-checkin');
revalidatePath('/sessions');
return { success: true, data: weeklyCheckInSession };

View File

@@ -24,6 +24,16 @@ export async function createYearReviewSession(data: {
session.user.id,
data
);
try {
await yearReviewService.shareYearReviewSession(
yearReviewSession.id,
session.user.id,
data.participant,
'EDITOR'
);
} catch (shareError) {
console.error('Auto-share failed:', shareError);
}
revalidatePath('/year-review');
revalidatePath('/sessions');
return { success: true, data: yearReviewSession };

View File

@@ -1,6 +1,7 @@
import { NextResponse } from 'next/server';
import { auth } from '@/lib/auth';
import { prisma } from '@/services/database';
import { shareSession } from '@/services/sessions';
export async function GET() {
try {
@@ -56,6 +57,12 @@ export async function POST(request: Request) {
},
});
try {
await shareSession(newSession.id, session.user.id, collaborator, 'EDITOR');
} catch (shareError) {
console.error('Auto-share failed:', shareError);
}
return NextResponse.json(newSession, { status: 201 });
} catch (error) {
console.error('Error creating session:', error);

View File

@@ -0,0 +1,31 @@
import { NextResponse } from 'next/server';
import { auth } from '@/lib/auth';
import { getUserTeams } from '@/services/teams';
import { getTeamMembersForShare } from '@/lib/share-utils';
export async function GET() {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
}
const teams = await getUserTeams(session.user.id);
const otherMembers = getTeamMembersForShare(teams, session.user.id);
const currentUser = {
id: session.user.id,
email: session.user.email ?? '',
name: session.user.name ?? null,
};
const members = [currentUser, ...otherMembers];
return NextResponse.json({ members });
} catch (error) {
console.error('Error fetching team members:', error);
return NextResponse.json(
{ error: 'Erreur lors de la récupération des membres' },
{ status: 500 }
);
}
}

View File

@@ -10,6 +10,7 @@ import {
CardContent,
Button,
Input,
ParticipantInput,
} from '@/components/ui';
import { createMotivatorSession } from '@/actions/moving-motivators';
@@ -72,12 +73,7 @@ export default function NewMotivatorSessionPage() {
required
/>
<Input
label="Nom du participant"
name="participant"
placeholder="Ex: Jean Dupont"
required
/>
<ParticipantInput name="participant" required />
<div className="rounded-lg border border-border bg-card-hover p-4">
<h3 className="font-medium text-foreground mb-2">Comment ça marche ?</h3>

View File

@@ -10,6 +10,7 @@ import {
CardContent,
Button,
Input,
ParticipantInput,
} from '@/components/ui';
export default function NewSessionPage() {
@@ -82,12 +83,7 @@ export default function NewSessionPage() {
required
/>
<Input
label="Nom du collaborateur"
name="collaborator"
placeholder="Ex: Jean Dupont"
required
/>
<ParticipantInput name="collaborator" required />
<div className="flex gap-3 pt-4">
<Button

View File

@@ -10,6 +10,7 @@ import {
CardContent,
Button,
Input,
ParticipantInput,
} from '@/components/ui';
import { createWeeklyCheckInSession } from '@/actions/weekly-checkin';
import { getWeekYearLabel } from '@/lib/date-utils';
@@ -93,12 +94,7 @@ export default function NewWeeklyCheckInPage() {
required
/>
<Input
label="Nom du collaborateur"
name="participant"
placeholder="Ex: Jean Dupont"
required
/>
<ParticipantInput name="participant" required />
<div>
<label htmlFor="date" className="block text-sm font-medium text-foreground mb-1">

View File

@@ -10,6 +10,7 @@ import {
CardContent,
Button,
Input,
ParticipantInput,
} from '@/components/ui';
import { createYearReviewSession } from '@/actions/year-review';
@@ -76,12 +77,7 @@ export default function NewYearReviewPage() {
required
/>
<Input
label="Nom du participant"
name="participant"
placeholder="Ex: Jean Dupont"
required
/>
<ParticipantInput name="participant" required />
<div>
<label htmlFor="year" className="block text-sm font-medium text-foreground mb-1">

View File

@@ -0,0 +1,56 @@
'use client';
import { useState, useEffect } from 'react';
import { Select } from '@/components/ui';
interface TeamMemberUser {
id: string;
email: string;
name: string | null;
}
interface ParticipantInputProps {
name: string;
label?: string;
required?: boolean;
}
export function ParticipantInput({
name,
label = "Choisir un membre de l'équipe",
required = true,
}: ParticipantInputProps) {
const [teamMembers, setTeamMembers] = useState<TeamMemberUser[]>([]);
const [value, setValue] = useState('');
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch('/api/teams/members')
.then((res) => res.json())
.then((data) => setTeamMembers(data.members ?? []))
.catch(() => setTeamMembers([]))
.finally(() => setLoading(false));
}, []);
const options =
teamMembers.length > 0
? teamMembers.map((m) => ({
value: m.email,
label: m.name ? `${m.name} (${m.email})` : m.email,
}))
: [{ value: '', label: 'Aucun membre dans vos équipes', disabled: true }];
if (loading) return null;
return (
<Select
name={name}
label={label}
options={options}
placeholder={teamMembers.length > 0 ? '— Sélectionner —' : undefined}
value={value}
onChange={(e) => setValue(e.target.value)}
required={required}
/>
);
}

View File

@@ -10,6 +10,7 @@ export { EditableYearReviewTitle } from './EditableYearReviewTitle';
export { EditableWeeklyCheckInTitle } from './EditableWeeklyCheckInTitle';
export { EditableWeatherTitle } from './EditableWeatherTitle';
export { Input } from './Input';
export { ParticipantInput } from './ParticipantInput';
export { Modal, ModalFooter } from './Modal';
export { RocketIcon } from './RocketIcon';
export { Select } from './Select';