Skip to content

Commit fc24f2d

Browse files
committed
frontend/tokens: enhance display of used "use once" tokens.
1 parent d367a4a commit fc24f2d

File tree

4 files changed

+64
-60
lines changed

4 files changed

+64
-60
lines changed

frontend/src/locales/de.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,10 @@ export const de ={
138138
"name": "Name",
139139
"name_placeholder": "Name",
140140
"created": "Erstellt",
141+
"used": "Verwendet",
141142
"last_used": "Zuletzt verwendet",
142-
"never_used": "Nie verwendet",
143+
"never_used": "Nie",
144+
"expired": "Abgelaufen",
143145
"create": "Token erstellen",
144146
"existing_tokens": "Vorhandene Token",
145147
"reusable": "Wiederverwendbar",

frontend/src/locales/en.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,10 @@ export const en = {
141141
"name": "Name",
142142
"name_placeholder": "Name",
143143
"created": "Created",
144+
"used": "Used",
144145
"last_used": "Last used",
145-
"never_used": "Never used",
146+
"never_used": "Never",
147+
"expired": "Expired",
146148
"create": "Create token",
147149
"existing_tokens": "Existing tokens",
148150
"reusable": "Reusable",

frontend/src/pages/tokens.tsx

Lines changed: 58 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -240,63 +240,71 @@ export function Tokens() {
240240
<h5 className="mb-0">{t("tokens.existing_tokens")}</h5>
241241
</Card.Header>
242242
<Card.Body>
243-
{tokens.map((token, index) => (
244-
<div key={index} className={`token-item ${index !== tokens.length - 1 ? 'mb-4' : ''}`}>
245-
<div className="d-flex justify-content-between align-items-start mb-2">
246-
<div>
247-
<h6 className="mb-1 fw-bold">{token.name}</h6>
248-
<small className="text-muted">
249-
{t("tokens.created")}: {token.createdAt.toLocaleDateString()} {token.createdAt.toLocaleTimeString()}
250-
</small>
251-
<br />
252-
<small className="text-muted">
253-
{t("tokens.last_used")}: {token.lastUsedAt ?
254-
`${token.lastUsedAt.toLocaleDateString()} ${token.lastUsedAt.toLocaleTimeString()}` :
255-
t("tokens.never_used")
256-
}
257-
</small>
243+
{tokens.map((token, index) => {
244+
const isExpired = token.use_once && token.lastUsedAt !== null;
245+
const statusVariant = isExpired ? "danger" : (token.use_once ? "success" : "warning");
246+
const statusText = isExpired ? t("tokens.expired") : (token.use_once ? t("tokens.use_once") : t("tokens.reusable"));
247+
248+
return (
249+
<div key={index} className={`token-item ${index !== tokens.length - 1 ? 'mb-4' : ''}`}>
250+
<div className="d-flex justify-content-between align-items-start mb-2">
251+
<div>
252+
<h6 className={`mb-1 fw-bold ${isExpired ? 'text-muted' : ''}`}>{token.name}</h6>
253+
<small className="text-muted">
254+
{t("tokens.created")}: {token.createdAt.toLocaleDateString()} {token.createdAt.toLocaleTimeString()}
255+
</small>
256+
<br />
257+
<small className="text-muted">
258+
{token.use_once ? t("tokens.used") : t("tokens.last_used")}: {token.lastUsedAt ?
259+
`${token.lastUsedAt.toLocaleDateString()} ${token.lastUsedAt.toLocaleTimeString()}` :
260+
t("tokens.never_used")
261+
}
262+
</small>
263+
</div>
264+
<div className="d-flex gap-2">
265+
<Button
266+
variant={statusVariant}
267+
disabled
268+
size="sm"
269+
>
270+
{statusText}
271+
</Button>
272+
</div>
258273
</div>
259-
<div className="d-flex gap-2">
274+
<InputGroup className="mb-2">
275+
<Form.Control
276+
type="text"
277+
readOnly
278+
value={isExpired ? "••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••" : token.token}
279+
className={`${isExpired ? 'text-muted' : ''}`}
280+
style={isExpired ? { fontFamily: 'monospace' } : {}}
281+
/>
282+
</InputGroup>
283+
<div className="d-flex flex-wrap gap-2">
260284
<Button
261-
variant={token.use_once ? "success" : "warning"}
262-
disabled
285+
variant="secondary"
263286
size="sm"
287+
className="d-flex align-items-center gap-2"
288+
onClick={() => handleCopyToken(token.token)}
289+
disabled={isExpired}
264290
>
265-
{token.use_once ? t("tokens.use_once") : t("tokens.reusable")}
291+
<Clipboard size={16} />
292+
{t("tokens.copy")}
293+
</Button>
294+
<Button
295+
variant="danger"
296+
size="sm"
297+
className="d-flex align-items-center gap-2"
298+
onClick={() => handleDeleteToken(token.id)}
299+
>
300+
<Trash2 size={16} />
301+
{t("tokens.delete")}
266302
</Button>
267303
</div>
304+
{index !== tokens.length - 1 && <hr className="mt-3" />}
268305
</div>
269-
<InputGroup className="mb-2">
270-
<Form.Control
271-
type="text"
272-
readOnly
273-
value={token.token}
274-
className="token-txt"
275-
/>
276-
</InputGroup>
277-
<div className="d-flex flex-wrap gap-2">
278-
<Button
279-
variant="secondary"
280-
size="sm"
281-
className="d-flex align-items-center gap-2"
282-
onClick={() => handleCopyToken(token.token)}
283-
>
284-
<Clipboard size={16} />
285-
{t("tokens.copy")}
286-
</Button>
287-
<Button
288-
variant="danger"
289-
size="sm"
290-
className="d-flex align-items-center gap-2"
291-
onClick={() => handleDeleteToken(token.id)}
292-
>
293-
<Trash2 size={16} />
294-
{t("tokens.delete")}
295-
</Button>
296-
</div>
297-
{index !== tokens.length - 1 && <hr className="mt-3" />}
298-
</div>
299-
))}
306+
);
307+
})}
300308
</Card.Body>
301309
</Card>
302310
</Container>

frontend/src/styles/main.scss

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,4 @@ th:hover:has(div) {
130130
border-bottom-right-radius: 0.25rem !important;
131131
}
132132
}
133-
134-
@media (max-width: 767.98px) {
135-
.token-txt {
136-
width: 100%;
137-
border-top-right-radius: 0.25rem !important;
138-
border-bottom-right-radius: 0.25rem !important;
139-
}
140-
}
141133
}

0 commit comments

Comments
 (0)