Files
nav-carte/pages/proposer.vue
Jules Neny c860dabdc0 feat(proposer): interface 5 onglets + soumission Références vers NocoDB
- Page /proposer avec 5 onglets (Écosystème/Réseau/Jobs/Outils/Références RAG)
- 5 form components + form-styles.css partagé
- Submit multi-type avec submission_type vers NocoDB
- Server route references.post.ts réécrite pour NocoDB (table ressources_references)
- redirect 301 /contribuer → /proposer
- Suppression references-pending.json
2026-06-23 12:13:33 +02:00

195 lines
4.8 KiB
Vue

<template>
<div class="proposer-page">
<div class="proposer-inner">
<NuxtLink to="/" class="back-link"> Retour à la carte</NuxtLink>
<div class="proposer-header">
<h1>Proposer une ressource</h1>
<p class="proposer-subtitle">
Tu connais quelque chose d'utile qui n'est pas encore référencé sur AEP ?
Choisis la catégorie ci-dessous et soumets-le on valide sous 7 jours.
</p>
</div>
<div v-if="success" class="success-block" role="status" aria-live="polite">
<div class="success-icon"></div>
<h2>Merci !</h2>
<p>Ta proposition est en attente de modération.</p>
<p class="success-detail">Jules valide manuellement chaque entrée avant publication.</p>
<button type="button" class="btn-secondary" @click="reset">Proposer autre chose</button>
</div>
<template v-else>
<div class="tabs-bar">
<button
v-for="tab in TABS"
:key="tab.id"
type="button"
class="tab-btn"
:class="{ 'tab-btn--active': activeTab === tab.id }"
@click="activeTab = tab.id"
>{{ tab.label }}</button>
</div>
<div class="tab-content">
<FormEcosysteme v-if="activeTab === 'ecosysteme'" @success="onSuccess" />
<FormReseau v-else-if="activeTab === 'reseau'" @success="onSuccess" />
<FormJobs v-else-if="activeTab === 'jobs'" @success="onSuccess" />
<FormOutils v-else-if="activeTab === 'outils'" @success="onSuccess" />
<FormReferences v-else-if="activeTab === 'references'" @success="onSuccess" />
</div>
</template>
</div>
</div>
</template>
<script setup lang="ts">
const TABS = [
{ id: 'ecosysteme', label: 'Écosystème / Entraide' },
{ id: 'reseau', label: 'Réseau AEP' },
{ id: 'jobs', label: 'Jobs' },
{ id: 'outils', label: 'Outils' },
{ id: 'references', label: 'Références RAG' },
] as const
const activeTab = ref<string>('ecosysteme')
const success = ref(false)
function onSuccess() {
success.value = true
}
function reset() {
success.value = false
activeTab.value = 'ecosysteme'
}
useHead({ title: 'Proposer une ressource — AEP' })
</script>
<style scoped>
.proposer-page {
min-height: 100vh;
background: var(--nav-bg);
padding: 1.5rem 1rem 4rem;
}
.proposer-inner {
max-width: 680px;
margin: 0 auto;
}
.back-link {
display: inline-flex;
align-items: center;
gap: 0.25rem;
font-size: 0.875rem;
color: var(--nav-primary-solid);
opacity: 0.7;
text-decoration: none;
margin-bottom: 1.5rem;
transition: opacity 0.15s;
}
.back-link:hover { opacity: 1; }
.proposer-header { margin-bottom: 1.5rem; }
.proposer-header h1 {
font-size: 1.5rem;
font-weight: 700;
color: var(--nav-text);
margin: 0 0 0.5rem;
}
.proposer-subtitle {
font-size: 0.9rem;
color: var(--nav-text-muted);
line-height: 1.5;
margin: 0;
}
.tabs-bar {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
margin-bottom: 1.5rem;
border-bottom: 1px solid var(--nav-bg-alt);
padding-bottom: 0;
}
.tab-btn {
padding: 0.5rem 0.9rem;
font-size: 0.8rem;
font-weight: 500;
color: var(--nav-text-muted);
background: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
font-family: inherit;
transition: color 0.15s, border-color 0.15s;
white-space: nowrap;
}
.tab-btn:hover { color: var(--nav-text); }
.tab-btn--active {
color: var(--nav-text);
border-bottom-color: var(--nav-primary-solid);
font-weight: 600;
}
.tab-content {
min-height: 300px;
}
.success-block {
background: var(--nav-surface);
border: 1px solid rgba(26, 34, 56, 0.15);
border-radius: 12px;
padding: 2rem 1.5rem;
text-align: center;
}
.success-icon {
width: 48px; height: 48px;
background: rgba(26, 34, 56, 0.1);
color: var(--nav-text);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
font-weight: 700;
margin: 0 auto 1rem;
}
.success-block h2 {
font-size: 1.25rem;
font-weight: 700;
color: var(--nav-text);
margin: 0 0 0.5rem;
}
.success-block p {
font-size: 0.9rem;
color: var(--nav-text-muted);
margin: 0 0 0.5rem;
line-height: 1.5;
}
.success-detail { font-size: 0.85rem !important; }
.btn-secondary {
padding: 0.75rem 1.25rem;
background: transparent;
color: var(--nav-text-muted);
border: 1px solid rgba(26, 34, 56, 0.2);
border-radius: 8px;
font-size: 0.9rem;
cursor: pointer;
font-family: inherit;
text-decoration: none;
display: inline-flex;
align-items: center;
margin-top: 0.5rem;
transition: border-color 0.15s, color 0.15s;
}
.btn-secondary:hover {
border-color: var(--nav-primary-solid);
color: var(--nav-text);
}
@media (max-width: 480px) {
.proposer-page { padding: 1rem 0.75rem 3rem; }
.tabs-bar { overflow-x: auto; flex-wrap: nowrap; }
}
</style>