218 lines
4.1 KiB
Vue
218 lines
4.1 KiB
Vue
<template>
|
|
<div class="lock-page">
|
|
<div class="lock-inner">
|
|
|
|
<div class="lock-header">
|
|
<h1>Co-développement</h1>
|
|
<p class="lock-subtitle">Entraide entre pairs</p>
|
|
<p class="lock-intro">Cet espace est un cercle. Pour entrer, il y a un mot.</p>
|
|
</div>
|
|
|
|
<form class="lock-form" @submit.prevent="submit" novalidate>
|
|
|
|
<div class="field-group">
|
|
<input
|
|
id="password"
|
|
v-model="password"
|
|
type="password"
|
|
placeholder="Mot de passe"
|
|
autocomplete="current-password"
|
|
required
|
|
:disabled="loading"
|
|
class="lock-input"
|
|
/>
|
|
</div>
|
|
|
|
<div v-if="error" class="lock-error" role="alert">
|
|
{{ error }}
|
|
</div>
|
|
|
|
<button type="submit" class="lock-btn" :disabled="loading || !password">
|
|
{{ loading ? 'Vérification...' : 'Entrer' }}
|
|
</button>
|
|
|
|
</form>
|
|
|
|
<div class="lock-footer">
|
|
<NuxtLink to="/codev/demo" class="demo-link">Voir l'exemple →</NuxtLink>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const password = ref('')
|
|
const error = ref('')
|
|
const loading = ref(false)
|
|
|
|
useHead({ title: 'Co-développement — Entraide entre pairs' })
|
|
|
|
async function submit() {
|
|
error.value = ''
|
|
loading.value = true
|
|
try {
|
|
await $fetch('/api/codev/auth', {
|
|
method: 'POST',
|
|
body: { password: password.value },
|
|
})
|
|
await navigateTo('/codev/fiche')
|
|
} catch (e: any) {
|
|
error.value = e?.statusMessage || 'Mauvais mot de passe'
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
/* ── Layout ── */
|
|
|
|
.lock-page {
|
|
min-height: 100vh;
|
|
background: var(--nav-bg, #fafafa);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 1.5rem 1rem;
|
|
}
|
|
|
|
.lock-inner {
|
|
width: 100%;
|
|
max-width: 400px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2rem;
|
|
}
|
|
|
|
/* ── En-tête ── */
|
|
|
|
.lock-header {
|
|
text-align: center;
|
|
}
|
|
|
|
.lock-header h1 {
|
|
font-size: 1.75rem;
|
|
font-weight: 700;
|
|
color: var(--nav-text, #1a1a2e);
|
|
margin: 0 0 0.375rem;
|
|
}
|
|
|
|
.lock-subtitle {
|
|
font-size: 1rem;
|
|
color: var(--nav-text-muted, #6b7280);
|
|
margin: 0 0 1rem;
|
|
}
|
|
|
|
.lock-intro {
|
|
font-size: 0.9rem;
|
|
color: var(--nav-text-muted, #6b7280);
|
|
line-height: 1.5;
|
|
margin: 0;
|
|
font-style: italic;
|
|
}
|
|
|
|
/* ── Formulaire ── */
|
|
|
|
.lock-form {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.875rem;
|
|
}
|
|
|
|
.field-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.lock-input {
|
|
width: 100%;
|
|
padding: 0.875rem 1rem;
|
|
border: 1px solid var(--border-color, #d0d4dc);
|
|
border-radius: 8px;
|
|
font-size: 1rem;
|
|
color: var(--nav-text, #1a1a2e);
|
|
background: var(--nav-surface, #ffffff);
|
|
font-family: inherit;
|
|
text-align: center;
|
|
letter-spacing: 0.1em;
|
|
transition: border-color 0.15s, box-shadow 0.15s;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.lock-input:focus {
|
|
outline: none;
|
|
border-color: var(--nav-primary-solid, #1B4436);
|
|
box-shadow: 0 0 0 2px rgba(27, 68, 54, 0.15);
|
|
}
|
|
|
|
.lock-input:disabled {
|
|
opacity: 0.6;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* ── Erreur ── */
|
|
|
|
.lock-error {
|
|
padding: 0.625rem 0.875rem;
|
|
background: #fdf0ee;
|
|
border: 1px solid #e74c3c;
|
|
border-radius: 8px;
|
|
font-size: 0.875rem;
|
|
color: #c0392b;
|
|
text-align: center;
|
|
}
|
|
|
|
/* ── Bouton ── */
|
|
|
|
.lock-btn {
|
|
width: 100%;
|
|
padding: 0.875rem 1rem;
|
|
background: var(--nav-primary-solid, #1B4436);
|
|
color: #ffffff;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
font-family: inherit;
|
|
transition: opacity 0.15s;
|
|
}
|
|
|
|
.lock-btn:hover:not(:disabled) {
|
|
opacity: 0.88;
|
|
}
|
|
|
|
.lock-btn:disabled {
|
|
opacity: 0.45;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
/* ── Pied de page ── */
|
|
|
|
.lock-footer {
|
|
text-align: center;
|
|
}
|
|
|
|
.demo-link {
|
|
font-size: 0.875rem;
|
|
color: var(--nav-text-muted, #6b7280);
|
|
text-decoration: none;
|
|
transition: color 0.15s;
|
|
}
|
|
|
|
.demo-link:hover {
|
|
color: var(--nav-primary-solid, #1B4436);
|
|
}
|
|
|
|
/* ── Responsive ── */
|
|
|
|
@media (max-width: 480px) {
|
|
.lock-page {
|
|
padding: 1.25rem 1rem 2.5rem;
|
|
align-items: flex-start;
|
|
padding-top: 3rem;
|
|
}
|
|
}
|
|
</style>
|