feat: add Weekly Check-in feature with models, UI components, and session management for enhanced team collaboration
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6m24s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 6m24s
This commit is contained in:
@@ -15,10 +15,18 @@ import {
|
||||
import { deleteSwotSession, updateSwotSession } from '@/actions/session';
|
||||
import { deleteMotivatorSession, updateMotivatorSession } from '@/actions/moving-motivators';
|
||||
import { deleteYearReviewSession, updateYearReviewSession } from '@/actions/year-review';
|
||||
import { deleteWeeklyCheckInSession, updateWeeklyCheckInSession } from '@/actions/weekly-checkin';
|
||||
|
||||
type WorkshopType = 'all' | 'swot' | 'motivators' | 'year-review' | 'byPerson';
|
||||
type WorkshopType = 'all' | 'swot' | 'motivators' | 'year-review' | 'weekly-checkin' | 'byPerson';
|
||||
|
||||
const VALID_TABS: WorkshopType[] = ['all', 'swot', 'motivators', 'year-review', 'byPerson'];
|
||||
const VALID_TABS: WorkshopType[] = [
|
||||
'all',
|
||||
'swot',
|
||||
'motivators',
|
||||
'year-review',
|
||||
'weekly-checkin',
|
||||
'byPerson',
|
||||
];
|
||||
|
||||
interface ShareUser {
|
||||
id: string;
|
||||
@@ -84,12 +92,28 @@ interface YearReviewSession {
|
||||
workshopType: 'year-review';
|
||||
}
|
||||
|
||||
type AnySession = SwotSession | MotivatorSession | YearReviewSession;
|
||||
interface WeeklyCheckInSession {
|
||||
id: string;
|
||||
title: string;
|
||||
participant: string;
|
||||
resolvedParticipant: ResolvedCollaborator;
|
||||
date: Date;
|
||||
updatedAt: Date;
|
||||
isOwner: boolean;
|
||||
role: 'OWNER' | 'VIEWER' | 'EDITOR';
|
||||
user: { id: string; name: string | null; email: string };
|
||||
shares: Share[];
|
||||
_count: { items: number };
|
||||
workshopType: 'weekly-checkin';
|
||||
}
|
||||
|
||||
type AnySession = SwotSession | MotivatorSession | YearReviewSession | WeeklyCheckInSession;
|
||||
|
||||
interface WorkshopTabsProps {
|
||||
swotSessions: SwotSession[];
|
||||
motivatorSessions: MotivatorSession[];
|
||||
yearReviewSessions: YearReviewSession[];
|
||||
weeklyCheckInSessions: WeeklyCheckInSession[];
|
||||
}
|
||||
|
||||
// Helper to get resolved collaborator from any session
|
||||
@@ -98,6 +122,8 @@ function getResolvedCollaborator(session: AnySession): ResolvedCollaborator {
|
||||
return (session as SwotSession).resolvedCollaborator;
|
||||
} else if (session.workshopType === 'year-review') {
|
||||
return (session as YearReviewSession).resolvedParticipant;
|
||||
} else if (session.workshopType === 'weekly-checkin') {
|
||||
return (session as WeeklyCheckInSession).resolvedParticipant;
|
||||
} else {
|
||||
return (session as MotivatorSession).resolvedParticipant;
|
||||
}
|
||||
@@ -141,6 +167,7 @@ export function WorkshopTabs({
|
||||
swotSessions,
|
||||
motivatorSessions,
|
||||
yearReviewSessions,
|
||||
weeklyCheckInSessions,
|
||||
}: WorkshopTabsProps) {
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
@@ -165,6 +192,7 @@ export function WorkshopTabs({
|
||||
...swotSessions,
|
||||
...motivatorSessions,
|
||||
...yearReviewSessions,
|
||||
...weeklyCheckInSessions,
|
||||
].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
||||
|
||||
// Filter based on active tab (for non-byPerson tabs)
|
||||
@@ -175,7 +203,9 @@ export function WorkshopTabs({
|
||||
? swotSessions
|
||||
: activeTab === 'motivators'
|
||||
? motivatorSessions
|
||||
: yearReviewSessions;
|
||||
: activeTab === 'year-review'
|
||||
? yearReviewSessions
|
||||
: weeklyCheckInSessions;
|
||||
|
||||
// Separate by ownership
|
||||
const ownedSessions = filteredSessions.filter((s) => s.isOwner);
|
||||
@@ -226,6 +256,13 @@ export function WorkshopTabs({
|
||||
label="Year Review"
|
||||
count={yearReviewSessions.length}
|
||||
/>
|
||||
<TabButton
|
||||
active={activeTab === 'weekly-checkin'}
|
||||
onClick={() => setActiveTab('weekly-checkin')}
|
||||
icon="📝"
|
||||
label="Weekly Check-in"
|
||||
count={weeklyCheckInSessions.length}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Sessions */}
|
||||
@@ -343,18 +380,29 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
|
||||
const isSwot = session.workshopType === 'swot';
|
||||
const isYearReview = session.workshopType === 'year-review';
|
||||
const isWeeklyCheckIn = session.workshopType === 'weekly-checkin';
|
||||
const href = isSwot
|
||||
? `/sessions/${session.id}`
|
||||
: isYearReview
|
||||
? `/year-review/${session.id}`
|
||||
: `/motivators/${session.id}`;
|
||||
const icon = isSwot ? '📊' : isYearReview ? '📅' : '🎯';
|
||||
: isWeeklyCheckIn
|
||||
? `/weekly-checkin/${session.id}`
|
||||
: `/motivators/${session.id}`;
|
||||
const icon = isSwot ? '📊' : isYearReview ? '📅' : isWeeklyCheckIn ? '📝' : '🎯';
|
||||
const participant = isSwot
|
||||
? (session as SwotSession).collaborator
|
||||
: isYearReview
|
||||
? (session as YearReviewSession).participant
|
||||
: (session as MotivatorSession).participant;
|
||||
const accentColor = isSwot ? '#06b6d4' : isYearReview ? '#f59e0b' : '#8b5cf6';
|
||||
: isWeeklyCheckIn
|
||||
? (session as WeeklyCheckInSession).participant
|
||||
: (session as MotivatorSession).participant;
|
||||
const accentColor = isSwot
|
||||
? '#06b6d4'
|
||||
: isYearReview
|
||||
? '#f59e0b'
|
||||
: isWeeklyCheckIn
|
||||
? '#10b981'
|
||||
: '#8b5cf6';
|
||||
|
||||
const handleDelete = () => {
|
||||
startTransition(async () => {
|
||||
@@ -362,7 +410,9 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
? await deleteSwotSession(session.id)
|
||||
: isYearReview
|
||||
? await deleteYearReviewSession(session.id)
|
||||
: await deleteMotivatorSession(session.id);
|
||||
: isWeeklyCheckIn
|
||||
? await deleteWeeklyCheckInSession(session.id)
|
||||
: await deleteMotivatorSession(session.id);
|
||||
|
||||
if (result.success) {
|
||||
setShowDeleteModal(false);
|
||||
@@ -381,10 +431,15 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
title: editTitle,
|
||||
participant: editParticipant,
|
||||
})
|
||||
: await updateMotivatorSession(session.id, {
|
||||
title: editTitle,
|
||||
participant: editParticipant,
|
||||
});
|
||||
: isWeeklyCheckIn
|
||||
? await updateWeeklyCheckInSession(session.id, {
|
||||
title: editTitle,
|
||||
participant: editParticipant,
|
||||
})
|
||||
: await updateMotivatorSession(session.id, {
|
||||
title: editTitle,
|
||||
participant: editParticipant,
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
setShowEditModal(false);
|
||||
@@ -401,6 +456,8 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
setShowEditModal(true);
|
||||
};
|
||||
|
||||
const editParticipantLabel = isSwot ? 'Collaborateur' : 'Participant';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="relative group">
|
||||
@@ -456,6 +513,17 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
<span>·</span>
|
||||
<span>Année {(session as YearReviewSession).year}</span>
|
||||
</>
|
||||
) : isWeeklyCheckIn ? (
|
||||
<>
|
||||
<span>{(session as WeeklyCheckInSession)._count.items} items</span>
|
||||
<span>·</span>
|
||||
<span>
|
||||
{new Date((session as WeeklyCheckInSession).date).toLocaleDateString('fr-FR', {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
})}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span>{(session as MotivatorSession)._count.cards}/10</span>
|
||||
)}
|
||||
@@ -570,7 +638,7 @@ function SessionCard({ session }: { session: AnySession }) {
|
||||
htmlFor="edit-participant"
|
||||
className="block text-sm font-medium text-foreground mb-1"
|
||||
>
|
||||
{isSwot ? 'Collaborateur' : 'Participant'}
|
||||
{editParticipantLabel}
|
||||
</label>
|
||||
<Input
|
||||
id="edit-participant"
|
||||
|
||||
Reference in New Issue
Block a user