Skip to content

Commit 4d89b9c

Browse files
committed
style(account): Tailwind classes per WellbeingSection e SecurityAuditSection
1 parent 7371235 commit 4d89b9c

2 files changed

Lines changed: 114 additions & 77 deletions

File tree

frontend/src/components/SecurityAuditSection.tsx

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -49,52 +49,54 @@ export default function SecurityAuditSection() {
4949
const hasNext = data ? skip + data.items.length < total : false;
5050

5151
return (
52-
<section className="security-audit-section">
53-
<h2>{t('account.securityAudit.title')}</h2>
54-
<p className="muted">{t('account.securityAudit.hint')}</p>
52+
<section className="space-y-3">
53+
<h2 className="text-base font-semibold text-accanto-900">{t('account.securityAudit.title')}</h2>
54+
<p className="text-sm text-accanto-500">{t('account.securityAudit.hint')}</p>
5555

56-
{error && <p className="error">{error}</p>}
56+
{error && <p className="text-sm text-red-700">{error}</p>}
5757

5858
{data && data.items.length === 0 && (
59-
<p className="muted">{t('account.securityAudit.empty')}</p>
59+
<p className="text-sm text-accanto-500">{t('account.securityAudit.empty')}</p>
6060
)}
6161

6262
{data && data.items.length > 0 && (
63-
<table className="audit-table">
64-
<thead>
65-
<tr>
66-
<th>{t('account.securityAudit.colWhen')}</th>
67-
<th>{t('account.securityAudit.colEvent')}</th>
68-
<th>{t('account.securityAudit.colDetails')}</th>
69-
<th>{t('account.securityAudit.colWhere')}</th>
70-
</tr>
71-
</thead>
72-
<tbody>
73-
{data.items.map((e) => (
74-
<tr key={e.id}>
75-
<td>{fmt(e.timestamp)}</td>
76-
<td>{eventLabel(e.eventType)}</td>
77-
<td>{e.summary ?? ''}</td>
78-
<td>
79-
{e.ipAddress ?? ''}
80-
{e.userAgent ? (
81-
<>
82-
<br />
83-
<small className="muted">{e.userAgent}</small>
84-
</>
85-
) : null}
86-
</td>
87-
</tr>
88-
))}
89-
</tbody>
90-
</table>
63+
<ul className="space-y-2">
64+
{data.items.map((e) => (
65+
<li key={e.id} className="card">
66+
<div className="flex items-baseline justify-between gap-2">
67+
<span className="text-sm font-medium text-accanto-900">{eventLabel(e.eventType)}</span>
68+
<span className="text-xs text-accanto-500 shrink-0">{fmt(e.timestamp)}</span>
69+
</div>
70+
{e.summary && (
71+
<p className="text-sm text-accanto-700 mt-1">{e.summary}</p>
72+
)}
73+
{(e.ipAddress || e.userAgent) && (
74+
<p className="text-xs text-accanto-500 mt-1 break-words">
75+
{e.ipAddress}
76+
{e.ipAddress && e.userAgent ? ' · ' : ''}
77+
{e.userAgent}
78+
</p>
79+
)}
80+
</li>
81+
))}
82+
</ul>
9183
)}
9284

93-
<div className="pager">
94-
<button type="button" disabled={!hasPrev || busy} onClick={() => load(Math.max(0, skip - PAGE_SIZE))}>
85+
<div className="flex gap-2">
86+
<button
87+
type="button"
88+
disabled={!hasPrev || busy}
89+
onClick={() => load(Math.max(0, skip - PAGE_SIZE))}
90+
className="px-3 py-1.5 rounded-lg border border-accanto-200 text-sm text-accanto-700 disabled:opacity-50"
91+
>
9592
{t('common.previous', { defaultValue: '← Precedente' })}
9693
</button>
97-
<button type="button" disabled={!hasNext || busy} onClick={() => load(skip + PAGE_SIZE)}>
94+
<button
95+
type="button"
96+
disabled={!hasNext || busy}
97+
onClick={() => load(skip + PAGE_SIZE)}
98+
className="px-3 py-1.5 rounded-lg border border-accanto-200 text-sm text-accanto-700 disabled:opacity-50"
99+
>
98100
{t('common.next', { defaultValue: 'Successivo →' })}
99101
</button>
100102
</div>

frontend/src/components/WellbeingSection.tsx

Lines changed: 76 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ export default function WellbeingSection() {
8686
};
8787

8888
return (
89-
<section className="wellbeing-section">
90-
<h2>{t('account.wellbeing.title')}</h2>
91-
<p className="muted">{t('account.wellbeing.hint')}</p>
89+
<section className="space-y-3">
90+
<h2 className="text-base font-semibold text-accanto-900">{t('account.wellbeing.title')}</h2>
91+
<p className="text-sm text-accanto-500">{t('account.wellbeing.hint')}</p>
9292

93-
{error && <p className="error">{error}</p>}
94-
{success && <p className="success">{success}</p>}
93+
{error && <p className="text-sm text-red-700">{error}</p>}
94+
{success && <p className="text-sm text-green-700">{success}</p>}
9595

96-
<form onSubmit={handleSubmit} className="wellbeing-form">
96+
<form onSubmit={handleSubmit} className="space-y-4 card">
9797
<ScaleField
9898
label={t('account.wellbeing.mood')}
9999
value={mood}
@@ -115,24 +115,29 @@ export default function WellbeingSection() {
115115
lowLabel={t('account.wellbeing.stressLow')}
116116
highLabel={t('account.wellbeing.stressHigh')}
117117
/>
118-
<label className="field">
119-
<span>{t('account.wellbeing.note')}</span>
118+
<div>
119+
<label className="block text-sm text-accanto-700 mb-1">{t('account.wellbeing.note')}</label>
120120
<textarea
121121
value={note}
122122
onChange={(e) => setNote(e.target.value)}
123123
maxLength={500}
124124
rows={2}
125125
placeholder={t('account.wellbeing.notePlaceholder')}
126+
className="w-full border border-accanto-200 rounded-lg px-3 py-2 text-sm"
126127
/>
127-
</label>
128-
<button type="submit" disabled={busy}>
128+
</div>
129+
<button
130+
type="submit"
131+
disabled={busy}
132+
className="w-full sm:w-auto px-4 py-2 rounded-lg bg-accanto-700 text-white text-sm font-medium disabled:opacity-60"
133+
>
129134
{t('account.wellbeing.save')}
130135
</button>
131136
</form>
132137

133138
<Trend items={items} t={t} />
134139

135-
<p className="muted" style={{ marginTop: '1rem' }}>
140+
<p className="text-sm text-accanto-500">
136141
<Link to="/self-care" className="text-accanto-700 underline">
137142
{t('account.wellbeing.selfCareLink')}
138143
</Link>
@@ -143,19 +148,25 @@ export default function WellbeingSection() {
143148
</p>
144149

145150
{items.length > 0 && (
146-
<details className="wellbeing-history">
147-
<summary>{t('account.wellbeing.history', { count: items.length })}</summary>
148-
<ul>
151+
<details className="card">
152+
<summary className="cursor-pointer text-sm font-medium text-accanto-700">
153+
{t('account.wellbeing.history', { count: items.length })}
154+
</summary>
155+
<ul className="mt-3 space-y-3">
149156
{items.map((c) => (
150-
<li key={c.id}>
151-
<div>
152-
<strong>{fmtDate(c.createdAt)}</strong>
153-
<span className="muted">
154-
{' '}· {t('account.wellbeing.mood')} {c.mood}/5 · {t('account.wellbeing.energy')} {c.energy}/5 · {t('account.wellbeing.stress')} {c.stress}/5
155-
</span>
157+
<li key={c.id} className="border-t border-accanto-100 pt-3 first:border-t-0 first:pt-0">
158+
<div className="text-sm">
159+
<strong className="text-accanto-900">{fmtDate(c.createdAt)}</strong>
160+
<div className="text-xs text-accanto-500 mt-0.5">
161+
{t('account.wellbeing.mood')} {c.mood}/5 · {t('account.wellbeing.energy')} {c.energy}/5 · {t('account.wellbeing.stress')} {c.stress}/5
162+
</div>
156163
</div>
157-
{c.note && <p>{c.note}</p>}
158-
<button type="button" className="link-button" onClick={() => handleDelete(c.id)}>
164+
{c.note && <p className="text-sm text-accanto-700 mt-1">{c.note}</p>}
165+
<button
166+
type="button"
167+
className="text-xs text-red-700 underline mt-1"
168+
onClick={() => handleDelete(c.id)}
169+
>
159170
{t('common.delete', { defaultValue: 'Elimina' })}
160171
</button>
161172
</li>
@@ -181,24 +192,29 @@ function ScaleField({
181192
highLabel: string;
182193
}) {
183194
return (
184-
<fieldset className="scale-field">
185-
<legend>{label}</legend>
186-
<div className="scale-buttons">
195+
<fieldset className="border-0 p-0 m-0">
196+
<legend className="text-sm font-medium text-accanto-700 mb-2">{label}</legend>
197+
<div className="flex gap-2">
187198
{SCALE.map((n) => (
188199
<button
189200
key={n}
190201
type="button"
191-
className={n === value ? 'selected' : ''}
202+
className={
203+
'flex-1 h-10 rounded-lg border text-sm font-medium transition-colors ' +
204+
(n === value
205+
? 'bg-accanto-700 text-white border-accanto-700'
206+
: 'bg-white text-accanto-700 border-accanto-200 hover:border-accanto-400')
207+
}
192208
onClick={() => onChange(n)}
193209
aria-pressed={n === value}
194210
>
195211
{n}
196212
</button>
197213
))}
198214
</div>
199-
<div className="scale-labels">
200-
<small className="muted">{lowLabel}</small>
201-
<small className="muted">{highLabel}</small>
215+
<div className="flex justify-between mt-1">
216+
<small className="text-xs text-accanto-500">{lowLabel}</small>
217+
<small className="text-xs text-accanto-500">{highLabel}</small>
202218
</div>
203219
</fieldset>
204220
);
@@ -215,7 +231,7 @@ function Trend({
215231
const sorted = useMemo(() => [...items].sort((a, b) => a.createdAt.localeCompare(b.createdAt)), [items]);
216232

217233
if (sorted.length < 2) {
218-
return <p className="muted">{t('account.wellbeing.trendEmpty')}</p>;
234+
return <p className="text-sm text-accanto-500">{t('account.wellbeing.trendEmpty')}</p>;
219235
}
220236

221237
const width = 320;
@@ -226,19 +242,38 @@ function Trend({
226242
const path = (key: 'mood' | 'energy' | 'stress') =>
227243
sorted.map((c, i) => `${i === 0 ? 'M' : 'L'} ${xs[i].toFixed(1)} ${yFor(c[key]).toFixed(1)}`).join(' ');
228244

245+
const colors = {
246+
mood: '#0ea5e9',
247+
energy: '#16a34a',
248+
stress: '#dc2626'
249+
} as const;
250+
229251
return (
230-
<div className="trend-wrap">
231-
<h3>{t('account.wellbeing.trend', { days: TREND_DAYS })}</h3>
232-
<svg viewBox={`0 0 ${width} ${height}`} className="trend-svg" role="img" aria-label={t('account.wellbeing.trend', { days: TREND_DAYS })}>
233-
<line x1={padding} y1={yFor(3)} x2={width - padding} y2={yFor(3)} className="trend-axis" />
234-
<path d={path('mood')} className="trend-line trend-mood" />
235-
<path d={path('energy')} className="trend-line trend-energy" />
236-
<path d={path('stress')} className="trend-line trend-stress" />
252+
<div className="card">
253+
<h3 className="text-sm font-medium text-accanto-700 mb-2">{t('account.wellbeing.trend', { days: TREND_DAYS })}</h3>
254+
<svg
255+
viewBox={`0 0 ${width} ${height}`}
256+
className="w-full h-32"
257+
role="img"
258+
aria-label={t('account.wellbeing.trend', { days: TREND_DAYS })}
259+
>
260+
<line
261+
x1={padding}
262+
y1={yFor(3)}
263+
x2={width - padding}
264+
y2={yFor(3)}
265+
stroke="#e5e7eb"
266+
strokeWidth={1}
267+
strokeDasharray="3 3"
268+
/>
269+
<path d={path('mood')} fill="none" stroke={colors.mood} strokeWidth={2} />
270+
<path d={path('energy')} fill="none" stroke={colors.energy} strokeWidth={2} />
271+
<path d={path('stress')} fill="none" stroke={colors.stress} strokeWidth={2} />
237272
</svg>
238-
<div className="trend-legend">
239-
<span className="trend-key trend-mood">{t('account.wellbeing.mood')}</span>
240-
<span className="trend-key trend-energy">{t('account.wellbeing.energy')}</span>
241-
<span className="trend-key trend-stress">{t('account.wellbeing.stress')}</span>
273+
<div className="flex flex-wrap gap-3 mt-2 text-xs">
274+
<span style={{ color: colors.mood }}>{t('account.wellbeing.mood')}</span>
275+
<span style={{ color: colors.energy }}>{t('account.wellbeing.energy')}</span>
276+
<span style={{ color: colors.stress }}>{t('account.wellbeing.stress')}</span>
242277
</div>
243278
</div>
244279
);

0 commit comments

Comments
 (0)