- Port all React components to Vue 3 (GwTabs, GwMN, GwCRA, GwCRS, GwMap, GwRelations, GwPerimeterList) - Port hooks to Vue composables (useCesiumProfiles, useSavedPerimeters) - Copy pure TS services and utils (duniter/, ss58, gratewizard utils) - Add Leaflet + Geoman + MarkerCluster dependencies - Serve grateWizard as popup via /gratewizard?popup (layout: false) and info page on /gratewizard (with Librodrome layout) - Remove public/gratewizard-app/ static Next.js export - Refine UI: compact tabs, buttons, inputs, cards, perimeter list - Use Ğ1 breve everywhere, French locale for all dates and amounts - Rename roles: vendeur→offre / acheteur→reçoit le produit ou service - Rename prix→évaluation in all visible text - Add calculated result column in CRA and CRS relation tables - DU/Ğ1 selector uses toggle switch (same as role toggle) - Auto-scroll to monetary data card on polygon selection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
79 lines
2.5 KiB
Vue
79 lines
2.5 KiB
Vue
<template>
|
|
<section class="section-padding">
|
|
<div class="container-content">
|
|
<UiScrollReveal>
|
|
<div class="gw-card">
|
|
<div class="flex flex-col items-center text-center gap-4 md:flex-row md:text-left md:gap-8">
|
|
<!-- Icon -->
|
|
<div class="gw-icon-wrapper">
|
|
<div class="i-lucide-sparkles h-8 w-8 text-amber-400" />
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="flex-1">
|
|
<span class="inline-block mb-2 rounded-full bg-amber-400/15 px-3 py-0.5 font-mono text-xs tracking-widest text-amber-400 uppercase">
|
|
{{ content?.grateWizardTeaser.kicker }}
|
|
</span>
|
|
<h3 class="heading-h3 font-display font-bold text-white">
|
|
{{ content?.grateWizardTeaser.title }}
|
|
</h3>
|
|
<p class="mt-2 text-sm text-white/60 md:text-base leading-relaxed">
|
|
{{ content?.grateWizardTeaser.description }}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- CTAs -->
|
|
<div class="shrink-0 flex flex-col gap-2">
|
|
<UiBaseButton :href="url" target="_blank" @click="launch">
|
|
<div class="i-lucide-external-link mr-2 h-4 w-4" />
|
|
{{ content?.grateWizardTeaser.cta.launch }}
|
|
</UiBaseButton>
|
|
<UiBaseButton variant="ghost" :to="content?.grateWizardTeaser.cta.more.to">
|
|
{{ content?.grateWizardTeaser.cta.more.label }}
|
|
<div class="i-lucide-arrow-right ml-2 h-4 w-4" />
|
|
</UiBaseButton>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</UiScrollReveal>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
const { url, launch } = useGrateWizard()
|
|
const { data: content } = await usePageContent('home')
|
|
</script>
|
|
|
|
<style scoped>
|
|
.gw-card {
|
|
border: 1px solid hsl(40 80% 50% / 0.2);
|
|
border-radius: 1rem;
|
|
padding: 1.5rem 2rem;
|
|
background: linear-gradient(135deg, hsl(40 80% 50% / 0.05), hsl(40 80% 50% / 0.02));
|
|
box-shadow: 0 0 40px hsl(40 80% 50% / 0.05);
|
|
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
|
}
|
|
|
|
.gw-card:hover {
|
|
border-color: hsl(40 80% 50% / 0.35);
|
|
box-shadow: 0 0 60px hsl(40 80% 50% / 0.1);
|
|
}
|
|
|
|
.heading-h3 {
|
|
font-size: clamp(1.25rem, 3vw, 1.625rem);
|
|
}
|
|
|
|
.gw-icon-wrapper {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 3.5rem;
|
|
height: 3.5rem;
|
|
border-radius: 0.75rem;
|
|
background: hsl(40 80% 50% / 0.1);
|
|
border: 1px solid hsl(40 80% 50% / 0.15);
|
|
flex-shrink: 0;
|
|
}
|
|
</style>
|