design: the window can now resize to l=380px

This commit is contained in:
2026-04-22 13:03:25 +02:00
parent 7de1fa2850
commit 9d181f3676
4 changed files with 331 additions and 219 deletions

View File

@ -4,19 +4,17 @@ export default function HomeView() {
const { guides, openGuide, profiles, activeProfileId } = useStore();
const activeProfile = profiles.find(p => p.id === activeProfileId);
const totalQuests = guides.reduce((s, g) => s + g.total_quests, 0);
const totalCompleted = guides.reduce((s, g) => s + g.completed_quests, 0);
const globalPct = totalQuests > 0 ? Math.round((totalCompleted / totalQuests) * 100) : 0;
const completedGuides = guides.filter(g => g.total_quests > 0 && g.completed_quests === g.total_quests);
const inProgressGuides = guides.filter(g => g.completed_quests > 0 && g.completed_quests < g.total_quests);
return (
<div style={{ flex: 1, overflowY: "auto", padding: "20px 24px", minHeight: 0 }}>
{/* Header */}
<div style={{ marginBottom: "24px" }}>
<h1 style={{ fontSize: "18px", fontWeight: 700, color: "#f0c040", marginBottom: "4px" }}>
<div style={{ marginBottom: "20px" }}>
<h1 style={{ fontSize: "20px", fontWeight: 700, color: "#f0c040", marginBottom: "2px" }}>
Tougli Guide Dofus
</h1>
{activeProfile && (
@ -32,7 +30,7 @@ export default function HomeView() {
background: "#161b22", border: "1px solid #2d3748", borderRadius: "10px",
padding: "16px 20px", marginBottom: "24px",
}}>
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: "8px" }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "8px" }}>
<span style={{ fontSize: "13px", color: "#94a3b8" }}>Progression globale</span>
<span style={{ fontSize: "13px", fontWeight: 700, color: "#f0c040" }}>
{totalCompleted} / {totalQuests} quêtes ({globalPct}%)
@ -45,7 +43,7 @@ export default function HomeView() {
borderRadius: "3px", transition: "width 0.4s ease",
}} />
</div>
<div style={{ marginTop: "8px", display: "flex", gap: "16px" }}>
<div style={{ marginTop: "10px", display: "flex", gap: "20px" }}>
<Stat label="Complétés" value={completedGuides.length} color="#4ade80" />
<Stat label="En cours" value={inProgressGuides.length} color="#f0c040" />
<Stat label="Total" value={guides.length} color="#94a3b8" />
@ -53,12 +51,12 @@ export default function HomeView() {
</div>
)}
{/* In progress first */}
{/* En cours */}
{inProgressGuides.length > 0 && (
<Section title="En cours" guides={inProgressGuides} onOpen={openGuide} />
)}
{/* All guides grid */}
{/* Tous les guides */}
<Section title="Tous les guides" guides={guides} onOpen={openGuide} />
</div>
);
@ -66,9 +64,9 @@ export default function HomeView() {
function Stat({ label, value, color }: { label: string; value: number; color: string }) {
return (
<div style={{ display: "flex", flexDirection: "column", gap: "2px" }}>
<div>
<span style={{ fontSize: "16px", fontWeight: 700, color }}>{value}</span>
<span style={{ fontSize: "11px", color: "#4a5568" }}>{label}</span>
<span style={{ fontSize: "11px", color: "#4a5568", marginLeft: "4px" }}>{label}</span>
</div>
);
}
@ -80,13 +78,15 @@ function Section({ title, guides, onOpen }: {
}) {
return (
<div style={{ marginBottom: "24px" }}>
<h2 style={{ fontSize: "12px", fontWeight: 600, color: "#4a5568", textTransform: "uppercase", letterSpacing: "0.1em", marginBottom: "10px" }}>
<h2 style={{
fontSize: "11px", fontWeight: 600, color: "#4a5568",
textTransform: "uppercase", letterSpacing: "0.1em",
marginBottom: "10px", borderBottom: "1px solid #2d3748", paddingBottom: "4px",
}}>
{title}
</h2>
<div style={{
display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", gap: "8px",
}}>
{guides.map(guide => <GuideCard key={guide.gid} guide={guide} onOpen={onOpen} />)}
<div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(175px, 1fr))", gap: "8px" }}>
{guides.map(g => <GuideCard key={g.gid} guide={g} onOpen={onOpen} />)}
</div>
</div>
);
@ -96,52 +96,63 @@ function GuideCard({ guide, onOpen }: {
guide: import("../types").GuideListItem;
onOpen: (gid: string) => void;
}) {
const pct = guide.total_quests > 0
? Math.round((guide.completed_quests / guide.total_quests) * 100)
: 0;
const pct = guide.total_quests > 0 ? Math.round((guide.completed_quests / guide.total_quests) * 100) : 0;
const isDone = pct === 100 && guide.total_quests > 0;
const inProgress = guide.completed_quests > 0 && !isDone;
const accentColor = isDone ? "#4ade80" : inProgress ? "#f0c040" : "#4a9eff";
return (
<button
onClick={() => onOpen(guide.gid)}
style={{
background: isDone ? "rgba(74,222,128,0.05)" : "#161b22",
border: `1px solid ${isDone ? "rgba(74,222,128,0.3)" : "#2d3748"}`,
background: "#161b22", border: `1px solid ${isDone ? "rgba(74,222,128,0.25)" : "#2d3748"}`,
borderRadius: "8px", padding: "12px 14px", cursor: "pointer",
textAlign: "left", transition: "all 0.15s",
textAlign: "left", transition: "all 0.15s", position: "relative", overflow: "hidden",
}}
onMouseEnter={e => {
(e.currentTarget as HTMLElement).style.borderColor = isDone ? "rgba(74,222,128,0.6)" : "#f0c040";
(e.currentTarget as HTMLElement).style.background = isDone ? "rgba(74,222,128,0.08)" : "#1a2233";
(e.currentTarget as HTMLElement).style.borderColor = accentColor;
(e.currentTarget as HTMLElement).style.background = "#1a2233";
}}
onMouseLeave={e => {
(e.currentTarget as HTMLElement).style.borderColor = isDone ? "rgba(74,222,128,0.3)" : "#2d3748";
(e.currentTarget as HTMLElement).style.background = isDone ? "rgba(74,222,128,0.05)" : "#161b22";
(e.currentTarget as HTMLElement).style.borderColor = isDone ? "rgba(74,222,128,0.25)" : "#2d3748";
(e.currentTarget as HTMLElement).style.background = "#161b22";
}}
>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: "8px" }}>
<span style={{
fontSize: "12px", fontWeight: 600, color: isDone ? "#4ade80" : "#e2e8f0",
lineHeight: 1.3,
}}>
{guide.name}
</span>
{isDone && <span style={{ fontSize: "14px" }}></span>}
</div>
<div style={{ height: "3px", background: "#2d3748", borderRadius: "2px", overflow: "hidden", marginBottom: "6px" }}>
<div style={{
height: "100%", width: `${pct}%`,
background: isDone ? "#4ade80" : pct > 60 ? "#f0c040" : "#4a9eff",
borderRadius: "2px",
}} />
</div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<span style={{ fontSize: "10px", color: "#4a5568" }}>
{guide.completed_quests}/{guide.total_quests} quêtes
</span>
<span style={{ fontSize: "10px", fontWeight: 700, color: isDone ? "#4ade80" : "#94a3b8" }}>
{pct}%
</span>
{/* Indicateur latéral */}
<div style={{
position: "absolute", left: 0, top: 0, bottom: 0, width: "3px",
background: accentColor, opacity: isDone ? 1 : inProgress ? 0.8 : 0.3,
borderRadius: "8px 0 0 8px",
}} />
<div style={{ paddingLeft: "4px" }}>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: "8px" }}>
<span style={{
fontSize: "12px", fontWeight: 600, lineHeight: 1.3,
color: isDone ? "#4ade80" : "#e2e8f0",
}}>
{guide.name}
</span>
{isDone && <span style={{ fontSize: "12px", flexShrink: 0 }}></span>}
</div>
<div style={{ height: "3px", background: "#2d3748", borderRadius: "2px", overflow: "hidden", marginBottom: "6px" }}>
<div style={{
height: "100%", width: `${pct}%`,
background: accentColor,
borderRadius: "2px", transition: "width 0.3s ease",
}} />
</div>
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
<span style={{ fontSize: "10px", color: "#4a5568" }}>
{guide.completed_quests}/{guide.total_quests} quêtes
</span>
<span style={{ fontSize: "10px", fontWeight: 700, color: accentColor }}>
{pct}%
</span>
</div>
</div>
</button>
);