feat: show evolution indicators per person per axis in weather board
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@ import { createOrUpdateWeatherEntry } from '@/actions/weather';
|
|||||||
import { Avatar } from '@/components/ui/Avatar';
|
import { Avatar } from '@/components/ui/Avatar';
|
||||||
import { Textarea } from '@/components/ui/Textarea';
|
import { Textarea } from '@/components/ui/Textarea';
|
||||||
import { Select } from '@/components/ui/Select';
|
import { Select } from '@/components/ui/Select';
|
||||||
import { WEATHER_EMOJIS } from '@/lib/weather-utils';
|
import { WEATHER_EMOJIS, getEmojiEvolution } from '@/lib/weather-utils';
|
||||||
|
|
||||||
interface WeatherEntry {
|
interface WeatherEntry {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -37,6 +37,25 @@ interface WeatherCardProps {
|
|||||||
previousEntry?: PreviousEntry | null;
|
previousEntry?: PreviousEntry | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EvolutionIndicator({
|
||||||
|
current,
|
||||||
|
previous,
|
||||||
|
}: {
|
||||||
|
current: string | null;
|
||||||
|
previous: string | null | undefined;
|
||||||
|
}) {
|
||||||
|
const direction = getEmojiEvolution(current, previous);
|
||||||
|
if (direction === null) return null;
|
||||||
|
|
||||||
|
if (direction === 'up') {
|
||||||
|
return <span className="text-xs text-green-500 font-bold leading-none" title="Amélioration">↑</span>;
|
||||||
|
}
|
||||||
|
if (direction === 'down') {
|
||||||
|
return <span className="text-xs text-red-500 font-bold leading-none" title="Dégradation">↓</span>;
|
||||||
|
}
|
||||||
|
return <span className="text-xs text-muted font-bold leading-none" title="Stable">→</span>;
|
||||||
|
}
|
||||||
|
|
||||||
export function WeatherCard({ sessionId, currentUserId, entry, canEdit, previousEntry }: WeatherCardProps) {
|
export function WeatherCard({ sessionId, currentUserId, entry, canEdit, previousEntry }: WeatherCardProps) {
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
const [notes, setNotes] = useState(entry.notes || '');
|
const [notes, setNotes] = useState(entry.notes || '');
|
||||||
@@ -112,9 +131,6 @@ export function WeatherCard({ sessionId, currentUserId, entry, canEdit, previous
|
|||||||
// For now, we'll use a placeholder - in real app, you'd pass user info as prop
|
// For now, we'll use a placeholder - in real app, you'd pass user info as prop
|
||||||
const user = entry.user;
|
const user = entry.user;
|
||||||
|
|
||||||
// previousEntry is available for future use in Task 6
|
|
||||||
void previousEntry;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr className={`border-b border-border ${isPending ? 'opacity-50' : ''}`}>
|
<tr className={`border-b border-border ${isPending ? 'opacity-50' : ''}`}>
|
||||||
{/* User column */}
|
{/* User column */}
|
||||||
@@ -130,64 +146,88 @@ export function WeatherCard({ sessionId, currentUserId, entry, canEdit, previous
|
|||||||
{/* Performance */}
|
{/* Performance */}
|
||||||
<td className="w-24 px-2 py-3">
|
<td className="w-24 px-2 py-3">
|
||||||
{canEditThis ? (
|
{canEditThis ? (
|
||||||
<Select
|
<div className="flex flex-col items-center gap-1">
|
||||||
value={performanceEmoji || ''}
|
<Select
|
||||||
onChange={(e) => handleEmojiChange('performance', e.target.value || null)}
|
value={performanceEmoji || ''}
|
||||||
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
onChange={(e) => handleEmojiChange('performance', e.target.value || null)}
|
||||||
size="sm"
|
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
||||||
wrapperClassName="!w-fit mx-auto"
|
size="sm"
|
||||||
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
wrapperClassName="!w-fit mx-auto"
|
||||||
/>
|
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
||||||
|
/>
|
||||||
|
<EvolutionIndicator current={performanceEmoji} previous={previousEntry?.performanceEmoji ?? null} />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-2xl text-center">{performanceEmoji || '-'}</div>
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="text-2xl text-center">{performanceEmoji || '-'}</div>
|
||||||
|
<EvolutionIndicator current={performanceEmoji} previous={previousEntry?.performanceEmoji ?? null} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{/* Moral */}
|
{/* Moral */}
|
||||||
<td className="w-24 px-2 py-3">
|
<td className="w-24 px-2 py-3">
|
||||||
{canEditThis ? (
|
{canEditThis ? (
|
||||||
<Select
|
<div className="flex flex-col items-center gap-1">
|
||||||
value={moralEmoji || ''}
|
<Select
|
||||||
onChange={(e) => handleEmojiChange('moral', e.target.value || null)}
|
value={moralEmoji || ''}
|
||||||
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
onChange={(e) => handleEmojiChange('moral', e.target.value || null)}
|
||||||
size="sm"
|
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
||||||
wrapperClassName="!w-fit mx-auto"
|
size="sm"
|
||||||
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
wrapperClassName="!w-fit mx-auto"
|
||||||
/>
|
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
||||||
|
/>
|
||||||
|
<EvolutionIndicator current={moralEmoji} previous={previousEntry?.moralEmoji ?? null} />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-2xl text-center">{moralEmoji || '-'}</div>
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="text-2xl text-center">{moralEmoji || '-'}</div>
|
||||||
|
<EvolutionIndicator current={moralEmoji} previous={previousEntry?.moralEmoji ?? null} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{/* Flux */}
|
{/* Flux */}
|
||||||
<td className="w-24 px-2 py-3">
|
<td className="w-24 px-2 py-3">
|
||||||
{canEditThis ? (
|
{canEditThis ? (
|
||||||
<Select
|
<div className="flex flex-col items-center gap-1">
|
||||||
value={fluxEmoji || ''}
|
<Select
|
||||||
onChange={(e) => handleEmojiChange('flux', e.target.value || null)}
|
value={fluxEmoji || ''}
|
||||||
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
onChange={(e) => handleEmojiChange('flux', e.target.value || null)}
|
||||||
size="sm"
|
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
||||||
wrapperClassName="!w-fit mx-auto"
|
size="sm"
|
||||||
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
wrapperClassName="!w-fit mx-auto"
|
||||||
/>
|
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
||||||
|
/>
|
||||||
|
<EvolutionIndicator current={fluxEmoji} previous={previousEntry?.fluxEmoji ?? null} />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-2xl text-center">{fluxEmoji || '-'}</div>
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="text-2xl text-center">{fluxEmoji || '-'}</div>
|
||||||
|
<EvolutionIndicator current={fluxEmoji} previous={previousEntry?.fluxEmoji ?? null} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{/* Création de valeur */}
|
{/* Création de valeur */}
|
||||||
<td className="w-24 px-2 py-3">
|
<td className="w-24 px-2 py-3">
|
||||||
{canEditThis ? (
|
{canEditThis ? (
|
||||||
<Select
|
<div className="flex flex-col items-center gap-1">
|
||||||
value={valueCreationEmoji || ''}
|
<Select
|
||||||
onChange={(e) => handleEmojiChange('valueCreation', e.target.value || null)}
|
value={valueCreationEmoji || ''}
|
||||||
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
onChange={(e) => handleEmojiChange('valueCreation', e.target.value || null)}
|
||||||
size="sm"
|
options={WEATHER_EMOJIS.map(({ emoji }) => ({ value: emoji, label: emoji }))}
|
||||||
wrapperClassName="!w-fit mx-auto"
|
size="sm"
|
||||||
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
wrapperClassName="!w-fit mx-auto"
|
||||||
/>
|
className="!w-16 min-w-16 text-center text-lg py-2.5"
|
||||||
|
/>
|
||||||
|
<EvolutionIndicator current={valueCreationEmoji} previous={previousEntry?.valueCreationEmoji ?? null} />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="text-2xl text-center">{valueCreationEmoji || '-'}</div>
|
<div className="flex flex-col items-center gap-1">
|
||||||
|
<div className="text-2xl text-center">{valueCreationEmoji || '-'}</div>
|
||||||
|
<EvolutionIndicator current={valueCreationEmoji} previous={previousEntry?.valueCreationEmoji ?? null} />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user