feat: add GIF Mood Board workshop
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 4m5s

- New workshop where each team member shares up to 5 GIFs with notes to express their weekly mood
- Per-user week rating (1-5 stars) visible next to each member's section
- Masonry-style grid with adjustable column count (3/4/5) toggle
- Handwriting font (Caveat) for GIF notes
- Full real-time collaboration via SSE
- Clean migration (add_gif_mood_workshop) safe for production deploy
- DB backup via cp before each migration in docker-entrypoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-03 10:04:56 +01:00
parent 7c68fb81e3
commit 766f3d5a59
21 changed files with 2032 additions and 15 deletions

View File

@@ -20,6 +20,10 @@ import {
getWeatherSessionsByUserId,
getTeamCollaboratorSessionsForAdmin as getTeamWeatherSessions,
} from '@/services/weather';
import {
getGifMoodSessionsByUserId,
getTeamCollaboratorSessionsForAdmin as getTeamGifMoodSessions,
} from '@/services/gif-mood';
import { Card } from '@/components/ui';
import { withWorkshopType } from '@/lib/workshops';
import { WorkshopTabs } from './WorkshopTabs';
@@ -58,22 +62,26 @@ export default async function SessionsPage() {
yearReviewSessions,
weeklyCheckInSessions,
weatherSessions,
gifMoodSessions,
teamSwotSessions,
teamMotivatorSessions,
teamYearReviewSessions,
teamWeeklyCheckInSessions,
teamWeatherSessions,
teamGifMoodSessions,
] = await Promise.all([
getSessionsByUserId(session.user.id),
getMotivatorSessionsByUserId(session.user.id),
getYearReviewSessionsByUserId(session.user.id),
getWeeklyCheckInSessionsByUserId(session.user.id),
getWeatherSessionsByUserId(session.user.id),
getGifMoodSessionsByUserId(session.user.id),
getTeamSwotSessions(session.user.id),
getTeamMotivatorSessions(session.user.id),
getTeamYearReviewSessions(session.user.id),
getTeamWeeklyCheckInSessions(session.user.id),
getTeamWeatherSessions(session.user.id),
getTeamGifMoodSessions(session.user.id),
]);
// Add workshopType to each session for unified display
@@ -82,12 +90,14 @@ export default async function SessionsPage() {
const allYearReviewSessions = withWorkshopType(yearReviewSessions, 'year-review');
const allWeeklyCheckInSessions = withWorkshopType(weeklyCheckInSessions, 'weekly-checkin');
const allWeatherSessions = withWorkshopType(weatherSessions, 'weather');
const allGifMoodSessions = withWorkshopType(gifMoodSessions, 'gif-mood');
const teamSwotWithType = withWorkshopType(teamSwotSessions, 'swot');
const teamMotivatorWithType = withWorkshopType(teamMotivatorSessions, 'motivators');
const teamYearReviewWithType = withWorkshopType(teamYearReviewSessions, 'year-review');
const teamWeeklyCheckInWithType = withWorkshopType(teamWeeklyCheckInSessions, 'weekly-checkin');
const teamWeatherWithType = withWorkshopType(teamWeatherSessions, 'weather');
const teamGifMoodWithType = withWorkshopType(teamGifMoodSessions, 'gif-mood');
// Combine and sort by updatedAt
const allSessions = [
@@ -96,6 +106,7 @@ export default async function SessionsPage() {
...allYearReviewSessions,
...allWeeklyCheckInSessions,
...allWeatherSessions,
...allGifMoodSessions,
].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
const hasNoSessions = allSessions.length === 0;
@@ -135,12 +146,14 @@ export default async function SessionsPage() {
yearReviewSessions={allYearReviewSessions}
weeklyCheckInSessions={allWeeklyCheckInSessions}
weatherSessions={allWeatherSessions}
gifMoodSessions={allGifMoodSessions}
teamCollabSessions={[
...teamSwotWithType,
...teamMotivatorWithType,
...teamYearReviewWithType,
...teamWeeklyCheckInWithType,
...teamWeatherWithType,
...teamGifMoodWithType,
]}
/>
</Suspense>