feat: implement Weather Workshop feature with models, UI components, and session management for enhanced team visibility and personal well-being tracking
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m16s
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m16s
This commit is contained in:
146
src/components/weather/WeatherBoard.tsx
Normal file
146
src/components/weather/WeatherBoard.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
'use client';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { WeatherCard } from './WeatherCard';
|
||||
|
||||
interface WeatherEntry {
|
||||
id: string;
|
||||
userId: string;
|
||||
performanceEmoji: string | null;
|
||||
moralEmoji: string | null;
|
||||
fluxEmoji: string | null;
|
||||
valueCreationEmoji: string | null;
|
||||
notes: string | null;
|
||||
user: {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface Share {
|
||||
id: string;
|
||||
userId: string;
|
||||
user: {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface WeatherBoardProps {
|
||||
sessionId: string;
|
||||
currentUserId: string;
|
||||
currentUser: {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
};
|
||||
entries: WeatherEntry[];
|
||||
shares: Share[];
|
||||
owner: {
|
||||
id: string;
|
||||
name: string | null;
|
||||
email: string;
|
||||
};
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
export function WeatherBoard({
|
||||
sessionId,
|
||||
currentUserId,
|
||||
entries,
|
||||
shares,
|
||||
owner,
|
||||
canEdit,
|
||||
}: WeatherBoardProps) {
|
||||
// Get all users who have access: owner + shared users
|
||||
const allUsers = useMemo(() => {
|
||||
const usersMap = new Map<string, { id: string; name: string | null; email: string }>();
|
||||
|
||||
// Add owner
|
||||
usersMap.set(owner.id, owner);
|
||||
|
||||
// Add shared users
|
||||
shares.forEach((share) => {
|
||||
usersMap.set(share.userId, share.user);
|
||||
});
|
||||
|
||||
return Array.from(usersMap.values());
|
||||
}, [owner, shares]);
|
||||
|
||||
// Create entries map for quick lookup
|
||||
const entriesMap = useMemo(() => {
|
||||
const map = new Map<string, WeatherEntry>();
|
||||
entries.forEach((entry) => {
|
||||
map.set(entry.userId, entry);
|
||||
});
|
||||
return map;
|
||||
}, [entries]);
|
||||
|
||||
// Create entries for all users (with placeholder entries for users without entries)
|
||||
const allEntries = useMemo(() => {
|
||||
return allUsers.map((user) => {
|
||||
const existingEntry = entriesMap.get(user.id);
|
||||
if (existingEntry) {
|
||||
return existingEntry;
|
||||
}
|
||||
// Create placeholder entry for user without entry
|
||||
return {
|
||||
id: '',
|
||||
userId: user.id,
|
||||
performanceEmoji: null,
|
||||
moralEmoji: null,
|
||||
fluxEmoji: null,
|
||||
valueCreationEmoji: null,
|
||||
notes: null,
|
||||
user,
|
||||
};
|
||||
});
|
||||
}, [allUsers, entriesMap]);
|
||||
|
||||
// Sort: current user first, then owner, then others
|
||||
const sortedEntries = useMemo(() => {
|
||||
return [...allEntries].sort((a, b) => {
|
||||
if (a.userId === currentUserId) return -1;
|
||||
if (b.userId === currentUserId) return 1;
|
||||
if (a.userId === owner.id) return -1;
|
||||
if (b.userId === owner.id) return 1;
|
||||
return (a.user.name || a.user.email).localeCompare(b.user.name || b.user.email, 'fr');
|
||||
});
|
||||
}, [allEntries, currentUserId, owner.id]);
|
||||
|
||||
return (
|
||||
<div className="overflow-x-auto rounded-lg border border-border bg-card">
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr className="border-b border-border bg-card-column">
|
||||
<th className="px-4 py-3 text-left text-sm font-medium text-foreground">Membre</th>
|
||||
<th className="px-4 py-3 text-center text-sm font-medium text-foreground">
|
||||
Performance
|
||||
</th>
|
||||
<th className="px-4 py-3 text-center text-sm font-medium text-foreground">Moral</th>
|
||||
<th className="px-4 py-3 text-center text-sm font-medium text-foreground">Flux</th>
|
||||
<th className="px-4 py-3 text-center text-sm font-medium text-foreground">
|
||||
Création de valeur
|
||||
</th>
|
||||
<th className="px-4 py-3 text-left text-sm font-medium text-foreground min-w-[300px]">
|
||||
Notes
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sortedEntries.map((entry) => (
|
||||
<WeatherCard
|
||||
key={entry.userId}
|
||||
sessionId={sessionId}
|
||||
currentUserId={currentUserId}
|
||||
entry={entry}
|
||||
canEdit={canEdit}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user