feat: implement auto-sharing functionality for session creation across motivators, weekly check-ins, and year reviews, enhancing collaboration capabilities
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
31
src/app/api/teams/members/route.ts
Normal file
31
src/app/api/teams/members/route.ts
Normal 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 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
56
src/components/ui/ParticipantInput.tsx
Normal file
56
src/components/ui/ParticipantInput.tsx
Normal 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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
Reference in New Issue
Block a user