forked from yvv/decision
v3 : neuvième relecture — noms uniques, places justes, quantités
- Noms des liens d'équipe : comparés sans casse, accents ni ponctuation (ld_engine::names), lettres latines seulement (pas de sosie cyrillique, grec ou pleine chasse), une ligne ; index unique (migration additive 0003) contre deux ouvertures simultanées sous le même nom. - Une personne déjà connectée ne prend une place que si le lien lui ajoute un groupe ; « Ce n'est pas moi » la déconnecte sur un navigateur partagé ; un lien collé dans le même onglet est relu. - Coller ou couper un mot de quantité n'est pas une coquille (« sur tout » → « surtout », « par tout » → « partout »). - Libellés sans caractère de contrôle ; la soumission revérifie le titre. Boucle : 68 tests Rust, svelte-check, 9 vitest, e2e 13/13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,9 +20,10 @@
|
||||
let error = $state('');
|
||||
let busy = $state(false);
|
||||
|
||||
onMount(async () => {
|
||||
async function read() {
|
||||
// The token travels in the fragment: it never reaches a server log.
|
||||
token = location.hash.slice(1).trim();
|
||||
const fragment = location.hash.slice(1).trim();
|
||||
if (fragment) token = fragment;
|
||||
history.replaceState(null, '', '/equipe');
|
||||
if (!/^[0-9a-f]{64}$/.test(token)) {
|
||||
phase = 'missing';
|
||||
@@ -34,8 +35,22 @@
|
||||
} catch {
|
||||
phase = 'invalid';
|
||||
}
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
void read();
|
||||
// A whole link pasted into this same tab only changes the fragment.
|
||||
const again = () => void read();
|
||||
window.addEventListener('hashchange', again);
|
||||
return () => window.removeEventListener('hashchange', again);
|
||||
});
|
||||
|
||||
// A shared browser: whoever is signed in is not the person opening the link.
|
||||
async function notMe() {
|
||||
await session.logout();
|
||||
await read();
|
||||
}
|
||||
|
||||
async function join(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
error = '';
|
||||
@@ -62,7 +77,10 @@
|
||||
<form class="card block" onsubmit={join}>
|
||||
{#if link.signedInAs}
|
||||
<p>{t('team.signed', { name: link.signedInAs })}</p>
|
||||
<button class="btn primary" type="submit" disabled={busy}>{t('team.add')}</button>
|
||||
<div class="row">
|
||||
<button class="btn primary" type="submit" disabled={busy}>{t('team.add')}</button>
|
||||
<button class="btn quiet" type="button" onclick={notMe}>{t('team.notme')}</button>
|
||||
</div>
|
||||
{:else}
|
||||
<label class="field">
|
||||
<span>{t('team.name')}</span>
|
||||
@@ -102,6 +120,11 @@
|
||||
.block > .btn {
|
||||
justify-self: start;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.small {
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user