Files
ToBePlayed-Frontend/src/components/DashboardWelcomeCard.jsx
T

70 lines
3.4 KiB
React

import {Link} from 'react-router-dom';
import {useTranslation} from 'react-i18next';
import {Hash, LayoutGrid, Link2, RefreshCw} from 'lucide-react';
import {Badge} from '@/components/ui/badge';
import {Button} from '@/components/ui/button';
import {Card} from '@/components/ui/card';
import HeroBanner from './HeroBanner.jsx';
import SteamAvatar from './SteamAvatar.jsx';
import SyncStatusBadge from './SyncStatusBadge.jsx';
import {useCurrentUserContext} from '../context/CurrentUserContext.jsx';
export default function DashboardWelcomeCard({bannerAppid, avatarUrl, sync, forceSync, editing, onCustomize}) {
const {t} = useTranslation();
const {user: userData} = useCurrentUserContext();
const hasSteamId = !!userData?.steamId;
const syncBusy = forceSync.busy || sync.isRunning;
return (
<Card className="relative overflow-hidden p-6 md:p-8 flex flex-col md:flex-row md:items-center md:justify-between gap-6">
{/* A picked game, else the game played most in the last two weeks. */}
<HeroBanner appid={bannerAppid}/>
<div className="relative flex min-w-0 items-center gap-4">
{/* The slot is there before the avatar loads, so the title does not jump. */}
{hasSteamId && (
<span className="flex size-16 shrink-0 items-center justify-center rounded-full bg-muted ring-2 ring-primary/60">
<SteamAvatar url={avatarUrl} className="size-16" iconClassName="size-8 text-muted-foreground"/>
</span>
)}
<div className="min-w-0">
<p className="text-sm font-medium text-muted-foreground">{t('DASHBOARD.WELCOME_BACK')}</p>
<h1 className="mt-1 text-3xl md:text-4xl font-bold tracking-tight truncate">
{t('DASHBOARD.HELLO')} {userData?.displayName ?? userData?.email?.split('@')[0]} 👋
</h1>
{hasSteamId ? (
<Badge variant="outline" className="mt-3 gap-1.5 font-mono text-muted-foreground">
<Hash className="size-3"/>
{userData.steamId}
</Badge>
) : (
<Button asChild variant="link" className="mt-2 h-auto p-0">
<Link to="/settings"><Link2 className="size-4"/>{t('DASHBOARD.NO_STEAM_ID')}</Link>
</Button>
)}
</div>
</div>
<div className="relative flex flex-col items-start md:items-end gap-3 shrink-0">
{hasSteamId && (
<>
<SyncStatusBadge
status={sync.status}
lastSyncedAt={sync.lastSyncedAt}
isRunning={sync.isRunning}
stale={sync.stale}
/>
<Button onClick={forceSync.trigger} disabled={syncBusy}>
<RefreshCw className={syncBusy ? 'animate-spin' : ''}/>
{t('LIBRARY.RESYNC')}
</Button>
</>
)}
<Button variant="ghost" size="sm" disabled={editing} onClick={onCustomize}>
<LayoutGrid/>{t('TILES.CUSTOMIZE')}
</Button>
</div>
</Card>
);
}