All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 3m16s
147 lines
3.8 KiB
TypeScript
147 lines
3.8 KiB
TypeScript
'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>
|
|
);
|
|
}
|