This commit is contained in:
2026-03-08 10:04:14 +01:00
parent 7967f63fea
commit 14636bd58f
74 changed files with 14180 additions and 4453 deletions

View File

@@ -1,86 +1,85 @@
- [ ] photo possibilité d'ajouter des photos, upload ( prevoir mecanisme : transformer en webp et redimensionner)
- [x] photo : upload + conversion WebP + thumbnail automatique
- couleur predominante : plantes: vert; jardin : marron; arrosage : bleu; outils: jaune
- ajout icones representatives
- [ ] ajout icones representatives dimensionnables
jardin :
- [ ] ajouter les caracteristiques pour un jardin: photo, geolocalisation, type de terre, ph, ensoleillement, exposition, dimension,surface, ...
-
- [ ] dans l'edition du jardin definir si carré potager avec dimension x;y en cm
- [x] ajouter les caracteristiques pour un jardin: photo, geolocalisation, type de terre, ph, ensoleillement, exposition, dimension, surface, ...
- [x] dans l'edition du jardin definir si carré potager avec dimension x;y en cm
plante :
- [ ] header : varietés => remplacer par plante ( pareil dans tous le programme)
- [ ] pour une plante, ajouter des caracteristiques : photo, nom, varités, famille, resistance au froid , maladie commune et astuces , methode de semis et de plantation, ... (brainstorming)
- [ ] plante du potager, fleur, arbre ou arbustre
- [ ] brainstorming pour ajouter une liste de plantes courante du jardin: carotte, tomate, ail, oignon, haricot, petis pois, poireaux, pomme de terre, salade, fraise, framboise, persil, echalote,courgette, choux fleur, choux boule,
- [ ] association des plantes et plantes ne devant pas etre planté a proximite
- [x] header : varietés => remplacé par plante (partout dans le programme)
- [x] pour une plante, ajouter des caracteristiques : photo, nom, variétés, famille, résistance au froid, maladie commune et astuces, méthode de semis et de plantation, ...
- [x] plante du potager, fleur, arbre ou arbuste
- [x] liste de plantes courantes seedée : carotte, tomate, ail, oignon, haricot, petits pois, poireaux, pomme de terre, salade, fraise, framboise, persil, échalote, courgette, chou-fleur, chou boule, ...
- [x] association des plantes (favorables / défavorables) : tags noms communs, validation croisée, édition depuis popup plante
taches:
- [ ] brainstorming pour preremplir la liste des taches courantes au jardin
- [ ] un tache peut etre unique ou avoir une frequence
- [ ] une tache peut utiliser un outils et s'applique a une platantion ( plantation: plantes dans une zone d'un jardin)
- [x] liste des tâches courantes au jardin pré-remplie (seed)
- [x] une tâche peut être unique ou avoir une fréquence (frequence_jours + date_prochaine)
- [x] une tâche peut utiliser un outil et s'applique à une plantation
outils:
- [ ] brainstorming pour ajouter des outils de jardinage
- [ ] liste dans le header
- [ ] créer une 1ere liste d'outils commun du jardin (grelinete, pelle, beche, pioche, sarcloir,....)
- [x] outils de jardinage : CRUD complet, catégories
- [x] liste dans le header (OutilsView)
- [x] re liste d'outils communs seedée (grelinette, pelle, bêche, pioche, sarcloir, ...)
planning:
- [ ] brainstorming
- [x] PlanningView : calendrier 4 semaines, tâches et plantations par jour
calendrier:
- [ ] renommer le header lunaire en calendrier ( lunaire, dictons, meteo, taches, )
- [ ] brainstorming
- [ ] calendrier lunaire avec icones et texte
- [ ] calendrier ajouter dictons courant ( brainstorming region france, auvergne, haute-loire, yssingeaux)
- analyse le dossier calendrier_lunaire
- [x] renommer le header lunaire en calendrier (Météo + Lunaire + Dictons + navigation)
- [x] calendrier lunaire avec icônes et texte (phases + types jours : racine/feuille/fleur/fruit)
- [x] dictons courants (région France, Auvergne, Haute-Loire, Yssingeaux)
- [x] dossier calendrier_lunaire analysé et intégré
meteo:
- [ ] brainstorming
- [ ] calendrier bi-hebdo ? avec prevision meteo
- recupere les infos sur ma station meteo locale ( donnéée de la veille une fois par jours et donnée actuelle 1 fois par heure)( brainstorming a partir des script d'essai)
- recupere les infos sur https://open-meteo.com/ une fois par heure pour les prevision ( brainstorming a partir des script d'essai)
- presentation meteo sous forme de tableau journalier synthetique ( passé, present, futur ( avec des colonnes pour station meteo locale et site open-meteo separé)) ( brainstorming
- analyse le dossier prevision meteo et station_meteo
astuces :
- [ ] possibilité d'ajouter des astuces pour les plantes, le jardin, les taches
- [ ] brainstorming
- [x] station météo locale (WeeWX) : données veille 1×/jour + actuelles 1×/heure
- [x] open-meteo.com : prévisions 1×/heure
- [x] tableau journalier synthétique (passé/présent/futur, colonne station + open-meteo)
- [x] dossiers prevision_meteo et station_meteo analysés et intégrés
astuces :
- [x] astuces pour les plantes, le jardin, les tâches : CRUD + filtres catégorie/mois/tag
- [ ] "Astuce du jour" dans le dashboard
capteur:
- [ ] recuperation de capteur possible: ensoleillement, temperature ambiante, temperature du sol, humidite de l'air, humidite du sol, ph du sol,
- [ ] configuration via serveur mqtt ( topic et payload)
- [ ] brainstorming
- capteur exterieur et capteur serre
- [ ] récupération de capteurs : ensoleillement, température ambiante/sol, humidité air/sol, pH sol
- [ ] configuration via serveur MQTT (topic et payload)
- [ ] capteur extérieur et capteur serre
reglages :
- [ ] application en mode desktop et pour smartphone ( responsive ?)
- [ ] section pour chaque type: interface, jardin, plante, taches, calendrier, planning
- [ ] backup et restaure (toutes les données: bdd, photo, pdf, txt)
- [ ] ajout de detection de plante a partir de photos ( possibilite d'ajouter un service de detection de type de plantes a partir d'une photo)
- reglage url station meteo local et site distant
reglages :
- [x] application responsive desktop et smartphone
- [x] backup ZIP (DB + uploads) téléchargeable
- [ ] restauration depuis ZIP (upload + restore)
- [ ] sections réglages par type : interface, jardin, plante, tâches, calendrier, planning
- [x] détection de plante depuis photo (Pl@ntNet API + YOLO local)
- [x] réglage URL station météo locale et site distant
recolte:
- [ ] ajouter possibiliter de saisir des quantites recoltés et a quelles dates ( brainstorming)
- [ ] ajouter la possibiliter de suivre des maladies (mildioux ), des traitement, des ravageurs: limaces, taupe, chenille, ...
recolte:
- [x] saisie des quantités récoltées avec dates (unités : kg/g/unités/litres/bottes)
- [x] suivi maladies (mildiou), traitements, ravageurs (limaces, taupe, chenille) via Observations
frontend :
- [ ] icones pour objet dimensionnable ds setting : jardin, plantes, tache, calendrier, meteo, outils
- [ ] icones pour plantes dimensionnable ds setting : tomate, pomme de terre, salade, carotte, ...
- [ ] mode editions pour pouvoir modifier les different element, plantes, jardin, taches, calendrier, ...
- [ ] ajouter des images depuis iphones ( appareil photo)
- [ ] ajouter des pdf ou des annotation, des url dvalable pour tous types d'objet: jardin, plantes,outils,
- verifier que l'application s'affiche correctement sur smartphone
- utilise le dossier icons pour le calendrier lunaire et la meteo ( icone svg adapter taille d'affichage dans setting)
frontend :
- [ ] icônes pour objets dimensionnables dans setting : jardin, plantes, tâche, calendrier, météo, outils
- [ ] icônes pour plantes dimensionnables dans setting : tomate, pomme de terre, salade, carotte, ...
- [x] mode édition pour les différents éléments (plantes, jardin, tâches, calendrier) via modales
- [ ] ajouter des images depuis iPhone (appareil photo natif)
- [x] PDF, annotations, URL pour tous types d'objets : jardin, plantes, outils (Attachments)
- [ ] vérifier affichage correct sur smartphone (à tester)
- [ ] utiliser le dossier icons pour le calendrier lunaire et la météo (icônes SVG adaptatifs dans settings)
bibliotehque photo:
- ajoute une bibliotheque ( plante, legume, fleur, arbres et arbrisseau, adventices) avec un stockage de mes capture et le rsultat d'une identification des plante grace au web ( via api ou via ia : brainstorming) api key: 2b1088cHCJ4c7Cn2Vqq67xfve sur https://my.plantnet.org/dashboard ( https://my.plantnet.org/doc/api/openapi)
- brainstorming local ai detection style yolo ( fichier consigne_yolo.md)
bibliotheque photo:
- [x] bibliothèque (plante, légume, fleur, arbres et arbrisseaux, adventices) + galerie lightbox
- [x] identification via Pl@ntNet API (api key configurée)
- [x] détection locale style YOLO (consigne_yolo.md intégrée)
backend :
- [ ] methode simple pour mettre a jours la base de donnée ; brainstorming
backend :
- [x] migration automatique BDD (migrate.py : ALTER TABLE ADD COLUMN sans perte de données)
- [x] mise à jour BDD via API REST
- [ ] ajouter des étoiles 1 à 5 (satisfaction plante)
- [ ] mise a jours bdd via api puis je peut ajouter des script dans mon openclaw]
- [ ] ajouter des etoiles 1 à 5 si j'ai été satisfait de la plante
divers :
- [ ] page 404 catch-all (route Vue manquante)
- [ ] export/import JSON complet
- [ ] observations dans PlantationsView (backend prêt, UI manquante)
- [ ] tests backend : couverture ~60% → objectif 80%

View File

@@ -13,6 +13,14 @@ EXPECTED_COLUMNS: dict[str, list[tuple[str, str, str | None]]] = {
("maladies_courantes", "TEXT", None),
("astuces_culture", "TEXT", None),
("url_reference", "TEXT", None),
("associations_favorables", "TEXT", None), # JSON list[str]
("associations_defavorables", "TEXT", None), # JSON list[str]
("boutique_nom", "TEXT", None),
("boutique_url", "TEXT", None),
("prix_achat", "REAL", None),
("date_achat", "TEXT", None),
("poids", "TEXT", None),
("dluo", "TEXT", None),
],
"garden": [
("latitude", "REAL", None),

View File

@@ -1,5 +1,7 @@
from datetime import datetime, timezone
from typing import Optional
from typing import List, Optional
from sqlalchemy import Column
from sqlalchemy import JSON as SA_JSON
from sqlmodel import Field, SQLModel
@@ -31,6 +33,21 @@ class Plant(SQLModel, table=True):
astuces_culture: Optional[str] = None
url_reference: Optional[str] = None
notes: Optional[str] = None
associations_favorables: Optional[List[str]] = Field(
default=None,
sa_column=Column("associations_favorables", SA_JSON, nullable=True),
)
associations_defavorables: Optional[List[str]] = Field(
default=None,
sa_column=Column("associations_defavorables", SA_JSON, nullable=True),
)
# Boutique / approvisionnement (par variété)
boutique_nom: Optional[str] = None # ex: "Gamm Vert", "Lidl", "Amazon"
boutique_url: Optional[str] = None # URL fiche produit
prix_achat: Optional[float] = None
date_achat: Optional[str] = None # ISO date
poids: Optional[str] = None # ex: "5g", "100g", "50 graines"
dluo: Optional[str] = None # date limite utilisation optimale
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
docs/arbustre/IMG_4808.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

BIN
docs/arbustre/IMG_4809.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

BIN
docs/arbustre/IMG_4810.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

BIN
docs/arbustre/IMG_4811.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
docs/arbustre/IMG_4813.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/arbustre/IMG_4814.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
docs/arbustre/IMG_4815.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
docs/arbustre/IMG_4816.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

View File

@@ -0,0 +1,219 @@
{
"source_dossier": "docs/arbustre",
"regle_groupement": "2 images consecutives = 1 plante",
"plantes": [
{
"id": 1,
"plante": "Vitis vinifera 'Marechal Foch'",
"nom_latin": "Vitis vinifera",
"images": ["IMG_4808.jpg", "IMG_4809.jpg"],
"texte_extrait": {
"avant": "Vitis vinifera 'Marechal Foch' (code 191599).",
"arriere": "Pictogrammes de culture et informations plant passport/recyclage."
},
"caracteristiques_plantation": {
"type": "Plant en pot (arbuste fruitier)",
"periode_plantation": null,
"periode_recolte": null,
"exposition": "Soleil / mi-ombre (selon pictogrammes)",
"arrosage": "Regulier (pictogramme arrosoir)",
"espacement": null,
"remarques": "Pictogramme maison (culture proche d'un support/mur, interpretation)."
},
"icones_significatives": [
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
},
{
"icone": "demi-soleil",
"signification": "Exposition",
"valeur": "Mi-ombre"
},
{
"icone": "arrosoir",
"signification": "Arrosage",
"valeur": "Regulier"
},
{
"icone": "maison",
"signification": "Emplacement",
"valeur": "Zone abritee/proche habitation (a confirmer)"
},
{
"icone": "couverts barres",
"signification": "Usage alimentaire",
"valeur": "Interpretation incertaine"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vitis\nvinifera 'Marechal Foch'\n191599",
"arriere": "Pictogrammes visibles: soleil, demi-soleil, maison, arrosoir, couverts barres.\nRaccolta differenziata - Etichetta: Carta - Verifica le disposizioni del tuo Comune.\nPlant Passport (bloc lisible partiellement): A Vitis vinifera; B CZ-...; C 02574/...; D 25.\nGGN: 4063061211323."
}
}
},
{
"id": 2,
"plante": "Ribes nigrum 'Titania'",
"nom_latin": "Ribes nigrum",
"images": ["IMG_4810.jpg", "IMG_4811.jpg"],
"texte_extrait": {
"avant": "Ribes nigrum 'Titania' (code 58329).",
"arriere": "Pictogrammes: soleil, arrosage, 150 cm, recolte VI-VII."
},
"caracteristiques_plantation": {
"type": "Plant en pot (arbuste fruitier)",
"periode_plantation": null,
"periode_recolte": "VI-VII",
"exposition": "Soleil",
"arrosage": "Regulier",
"espacement": "150 cm",
"taille_entretien": "Pictogrammes de taille/suppression du bois (interpretation)"
},
"icones_significatives": [
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
},
{
"icone": "arrosoir",
"signification": "Arrosage",
"valeur": "Regulier"
},
{
"icone": "fleche verticale 150 cm",
"signification": "Espacement/distance",
"valeur": "150 cm"
},
{
"icone": "main + VI-VII",
"signification": "Periode de recolte",
"valeur": "Juin-Juillet"
},
{
"icone": "branche/fruits + fleches",
"signification": "Taille/renouvellement",
"valeur": "Interpretation"
},
{
"icone": "flocon barre + fleches",
"signification": "Gestion hivernale",
"valeur": "Interpretation"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Ribes nigrum\n'Titania'\n58329",
"arriere": "Ribes nigrum\nPictogrammes: soleil; arrosoir; 150 cm; main + VI-VII; deux pictogrammes de taille/entretien.\nPlant Passport: A Ribes nigrum; B NL-...; C 4421PP; D NL.\nCode-barres: 4014157115032."
}
}
},
{
"id": 3,
"plante": "Rubus idaeus 'Schoenemann'",
"nom_latin": "Rubus idaeus",
"images": ["IMG_4813.jpg", "IMG_4814.jpg"],
"texte_extrait": {
"avant": "Rubus idaeus 'Schoenemann' (code 58329).",
"arriere": "Pictogrammes: soleil, arrosage, 150 cm, recolte VII-XI."
},
"caracteristiques_plantation": {
"type": "Plant en pot (arbuste fruitier)",
"periode_plantation": null,
"periode_recolte": "VII-XI",
"exposition": "Soleil",
"arrosage": "Regulier",
"espacement": "150 cm",
"taille_entretien": "Pictogrammes de taille/suppression du bois (interpretation)"
},
"icones_significatives": [
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
},
{
"icone": "arrosoir",
"signification": "Arrosage",
"valeur": "Regulier"
},
{
"icone": "fleche verticale 150 cm",
"signification": "Espacement/distance",
"valeur": "150 cm"
},
{
"icone": "main + VII-XI",
"signification": "Periode de recolte",
"valeur": "Juillet-Novembre"
},
{
"icone": "branche/fruits + fleches",
"signification": "Taille/renouvellement",
"valeur": "Interpretation"
},
{
"icone": "flocon barre + fleches",
"signification": "Gestion hivernale",
"valeur": "Interpretation"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Rubus idaeus\n'Schoenemann'\n58329",
"arriere": "Rubus idaeus\nPictogrammes: soleil; arrosoir; 150 cm; main + VII-XI; deux pictogrammes de taille/entretien.\nPlant Passport: A Rubus idaeus; B NL-...; C 4421PP; D NL.\nCode-barres: 4014157115087."
}
}
},
{
"id": 4,
"plante": "Framboisier remontant 'Paris'",
"nom_latin": "Rubus idaeus",
"images": ["IMG_4815.jpg", "IMG_4816.jpg"],
"texte_extrait": {
"avant": "F.A.N Fruits Au Naturel - Framboisier remontant 'Paris'. Recolte: juin-juillet puis septembre-octobre.",
"arriere": "Conseils complets de plantation/entretien + recette 'Palets a la confiture de framboises'."
},
"caracteristiques_plantation": {
"type": "Plant en pot 1,6 litre",
"periode_plantation": "Fevrier a juin et aout a novembre",
"periode_recolte": "Juin-juillet puis septembre-octobre",
"exposition": "Soleil a mi-ombre",
"arrosage": "Arroser a la plantation puis regulier",
"espacement": "0,50 m a 0,70 m entre chaque plant",
"sol": "Tout type de sol sauf humide",
"fertilisation": "Engrais organique a l'automne"
},
"icones_significatives": [
{
"icone": "suite etapes 1-5",
"signification": "Methode de plantation",
"valeur": "Ameublir, trou, retirer le pot, planter/tasser, arroser"
},
{
"icone": "recolte en 2 periodes",
"signification": "Calendrier de production",
"valeur": "Juin-juillet puis septembre-octobre"
},
{
"icone": "mes reperes usage/gout",
"signification": "Usages culinaires et profil gustatif",
"valeur": "Patisserie, confiture, fruits frais, smoothies"
}
],
"detail": {
"texte_integral_visible": {
"avant": "F.A.N Fruits Au Naturel\nFramboisier remontant\n'Paris'\nRecolte: juin-juillet puis septembre-octobre\nmes reperes: glaces/sorbets, patisserie/confiture, fruits frais/smoothies\nproduction locale\nPot 1,6 litre",
"arriere": "1 Travaillez le sol pour l'ameublir.\n2 Faites un trou a la taille de la motte.\n3 Retirez le pot.\n4 Plantez et tassez la terre autour de la motte.\n5 Arrosez.\ninfos et conseils: www.vivaplante.fr\n\nFRAMBOISIER REMONTANT 'Paris' (Rubus idaeus)\n\nFramboisier remontant 'Paris'\nSol: tout type de sol sauf humide.\nPlantation: planter toute la motte sous terre. Arroser.\nFertilisation: apporter un engrais organique a l'automne.\nTaille:\n- non remontant (de saison): chaque hiver, enlever les tiges dessechees. Palisser les cannes conservees pour l'annee suivante.\n- remontant: l'hiver, enlever les tiges dessechees et celles trop freles. Ne laisser que 4 ou 5 belles cannes qui produiront en juin. La deuxieme production des septembre aura lieu sur les pousses de l'annee.\n\nPalets a la confiture de framboises\n250 g de farine - 125 g de beurre - 150 g de sucre en poudre - confiture de framboise - 1 oeuf - vanille en poudre\nBattez ensemble le beurre, l'oeuf et 125 g de sucre.\nAjoutez la farine lorsque la preparation mousse, une cuiller a cafe de vanille et une pincee de sel.\nPetrissez la pate et placez-la au refrigerateur pendant 20 minutes.\nFaites des noix de pate que vous roulez dans le reste de sucre. Aplatissez un peu ces noix avant de les poser sur la plaque du four a 210 C pendant 5 minutes.\nFormez un creux au centre de chaque palet a l'aide d'une cuiller a cafe.\nVersez-y la confiture de framboise et placez-les de nouveau au four ou laissez-les dorer.\n\nPlantation: fevrier a juin et aout a nov.\nRecolte: juin-juillet puis septembre-octobre.\nExposition: soleil-mi-ombre.\nEspacement des plants: 0,50 m a 0,70 m entre chaque plant.\n\nPasseport Phytosanitaire / Plant Passport: A Rubus idaeus; B FR-RH00491; C 765883; D FR."
}
}
}
],
"notes": [
"Extraction manuelle depuis photos.",
"Certaines lignes de passeport ou pictogrammes sont partiellement lisibles et marquees comme interpretation quand necessaire."
]
}

1563
docs/association.json Normal file

File diff suppressed because it is too large Load Diff

BIN
docs/graine/IMG_4780.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

BIN
docs/graine/IMG_4781.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
docs/graine/IMG_4782.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
docs/graine/IMG_4783.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
docs/graine/IMG_4784.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 MiB

BIN
docs/graine/IMG_4785.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
docs/graine/IMG_4786.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

BIN
docs/graine/IMG_4787.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

BIN
docs/graine/IMG_4788.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

BIN
docs/graine/IMG_4789.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
docs/graine/IMG_4790.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

BIN
docs/graine/IMG_4791.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

BIN
docs/graine/IMG_4792.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

BIN
docs/graine/IMG_4793.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

BIN
docs/graine/IMG_4794.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

BIN
docs/graine/IMG_4795.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

BIN
docs/graine/IMG_4796.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

BIN
docs/graine/IMG_4797.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
docs/graine/IMG_4798.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

BIN
docs/graine/IMG_4799.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

BIN
docs/graine/IMG_4800.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

BIN
docs/graine/IMG_4801.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
docs/graine/IMG_4802.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 MiB

BIN
docs/graine/IMG_4803.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
docs/graine/IMG_4804.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

BIN
docs/graine/IMG_4805.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

BIN
docs/graine/IMG_4806.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
docs/graine/IMG_4807.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

View File

@@ -0,0 +1,783 @@
{
"source_dossier": "docs/graine",
"regle_groupement": "2 images consecutives = 1 plante",
"plantes": [
{
"id": 1,
"plante": "Oignon Stockarda",
"nom_latin": "Allium cepa",
"images": [
"IMG_4780.jpg",
"IMG_4781.jpg"
],
"texte_extrait": {
"avant": "Oignon comestible epice a conserver ou a consommer frais.",
"arriere": "Semis de debut mars a avril, en pleine terre. Germination 15 a 20 jours."
},
"caracteristiques_plantation": {
"semis": "Exterieur",
"periode_semis": "III-IV",
"temperature": "8-10 C",
"profondeur": "1 cm",
"espacement": "5 x 25 cm",
"exposition": "Ensoleille",
"periode_recolte": "VII-IX"
},
"icones_significatives": [
{
"icone": "thermometre",
"signification": "Temperature de semis",
"valeur": "8-10 C"
},
{
"icone": "graines/ligne",
"signification": "Semis exterieur",
"valeur": "III-IV"
},
{
"icone": "profondeur",
"signification": "Profondeur de semis",
"valeur": "1 cm"
},
{
"icone": "espacement",
"signification": "Distance de plantation",
"valeur": "5 x 25 cm"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Ensoleille"
},
{
"icone": "panier",
"signification": "Periode de recolte",
"valeur": "VII-IX"
}
],
"detail": {
"texte_integral_visible": {
"avant": "OIGNON COMESTIBLE EPICE A CONSERVER OU A CONSOMMER FRAIS\nOIGNON STOCKARDA\nALLIUM CEPA\n2 GP\nPour la culture de printemps et d'automne\nConvient pour la culture en pleine terre\n8880830",
"arriere": "Oignon Stockarda\nUtilisation: Variete mi-precoce, tres polyvalente, utilisable comme oignon de conservation et comme ciboule. Oignons ronds legerement aplatis, de couleur jaune, a la peau ferme, au poids de sortie eleve et a la duree de conservation tres longue. Crus, les oignons conviennent pour assaisonner les salades, cuits ils accompagnent de nombreux plats.\nCulture et soin: Germination 15 a 20 jours. Le semis se fait de debut mars a avril, en pleine terre. Semer a 1 cm de profondeur, tasser, recouvrir de terre et maintenir humide.\nConseil: Les oignons preferent un sol ameubli et riche en substances nutritives. Veiller a une humidite reguliere pendant toute la croissance.\nPictogrammes: 8-10 C; 1 cm; Semis en exterieur III-IV; Distance 5 x 25 cm; Exposition Ensoleille; Recolte VII-IX.\nLe contenu suffit pour environ 7 metres. 1 g."
}
}
},
{
"id": 2,
"plante": "Laitue Attraction (ruban de graines)",
"nom_latin": "Lactuca sativa",
"images": [
"IMG_4782.jpg",
"IMG_4783.jpg"
],
"texte_extrait": {
"avant": "Laitue pommee tendre. Ruban de graines.",
"arriere": "Germination 7 a 12 jours. Semis en exterieur en ruban."
},
"caracteristiques_plantation": {
"semis": "Exterieur (ruban)",
"periode_semis": "III-VI",
"temperature": "10-20 C",
"profondeur": "0,5 cm",
"espacement": "15 cm",
"exposition": "Ensoleille / semi-ombrage",
"periode_recolte": "VI-IX"
},
"icones_significatives": [
{
"icone": "ruban",
"signification": "Type de semis",
"valeur": "Ruban de graines"
},
{
"icone": "thermometre",
"signification": "Temperature",
"valeur": "10-20 C"
},
{
"icone": "graines/ligne",
"signification": "Semis exterieur",
"valeur": "III-VI"
},
{
"icone": "espacement",
"signification": "Distance",
"valeur": "15 cm"
},
{
"icone": "soleil-nuage",
"signification": "Exposition",
"valeur": "Ensoleille/Semi-ombrage"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "VI-IX"
}
],
"detail": {
"texte_integral_visible": {
"avant": "LAITUE POMMEE TENDRE\nRUBAN DE GRAINES LAITUE ATTRAKTION\nLACTUCA SATIVA\n4 PG\nPour la culture de printemps\nRuban de graines\n8882915",
"arriere": "Ruban de graines Laitue Attraktion\nUtilisation: La variete eprouvee Attraction est une laitue pommee mi-precoce avec des tetes fermes vert clair dont le coeur est d'une qualite exceptionnelle, tendre et avec peu de feuilles exterieures.\nCulture et soin: Germination 7 a 12 jours. Preferer un sol de jardin riche en humus, meuble et profond, a un endroit ensoleille a semi-ombrage. Placer le ruban de graines dans un sillon d'env. 0,5 cm de profondeur, humidifier, recouvrir d'une fine couche de terre, tasser et arroser a nouveau abondamment.\nConseil: Le sol doit etre desherbe et ameubli. Les graines sont placees dans le ruban a la distance optimale de plantation.\nPictogrammes: 10-20 C; 0,5 cm; Semis en exterieur III-VI; Distance 15 cm; Exposition Ensoleille/Semi-ombrage; Recolte VI-IX.\nLe contenu suffit pour environ 5 metres."
}
}
},
{
"id": 3,
"plante": "Persil frise Moskrul 2",
"nom_latin": "Petroselinum crispum",
"images": [
"IMG_4784.jpg",
"IMG_4785.jpg"
],
"texte_extrait": {
"avant": "Feuilles finement frisees, aromatiques. Plante resistante a l'hiver.",
"arriere": "Germination 15 a 35 jours. Semis de mars a aout."
},
"caracteristiques_plantation": {
"semis": "Exterieur",
"periode_semis": "III-VIII",
"temperature": "15-20 C",
"profondeur": "1 cm",
"espacement": "8 x 25 cm",
"exposition": "Ensoleille (possible mi-ombre selon texte)",
"periode_recolte": "V-IX"
},
"icones_significatives": [
{
"icone": "flocon",
"signification": "Resistance",
"valeur": "Resistant a l'hiver"
},
{
"icone": "feuille",
"signification": "Usage",
"valeur": "Herbe aromatique"
},
{
"icone": "thermometre",
"signification": "Temperature",
"valeur": "15-20 C"
},
{
"icone": "graines/ligne",
"signification": "Semis exterieur",
"valeur": "III-VIII"
},
{
"icone": "espacement",
"signification": "Distance",
"valeur": "8 x 25 cm"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "V-IX"
}
],
"detail": {
"texte_integral_visible": {
"avant": "FEUILLES FINEMENT FRISEES, AROMATIQUES\nPERSIL, FRISE MOSKRUL 2\nPETROSELINUM CRISPUM\n1 GP\nplante resistante a l'hiver\nherbe aromatique\n8881010",
"arriere": "Persil, frise Moskrul 2\nUtilisation: Bisannuelle. Les feuilles finement frisees et d'un vert intense possedent un arome subtil et epice. Le persil est particulierement apprecie en cuisine pour assaisonner les soupes, les sauces et les salades.\nCulture et soin: Germination 15 a 35 jours. Le semis se fait des que le sol est a l'abri du gel. Semer a 1 cm de profondeur, recouvrir d'une fine couche de terre, tasser les graines et maintenir une humidite constante.\nConseil: Le persil aime les endroits humides, semi-ombrages, riches en humus et nutritifs.\nPictogrammes: 15-20 C; 1 cm; Semis en exterieur III-VIII; Distance 8 x 25 cm; Exposition Ensoleille; Recolte V-IX.\nLe contenu suffit pour environ 1,2-1,8 metres. 3,5 g."
}
}
},
{
"id": 4,
"plante": "Courgette de Nice a fruit rond",
"nom_latin": "Cucurbita pepo",
"images": [
"IMG_4786.jpg",
"IMG_4787.jpg"
],
"texte_extrait": {
"avant": "Fruits spheriques a la chair tendre.",
"arriere": "Semis en pre-culture en pot. Germination 6 a 10 jours."
},
"caracteristiques_plantation": {
"semis": "Pre-culture en pot",
"periode_semis": "III-V",
"temperature": "15-20 C",
"profondeur": "2-3 cm",
"espacement": "60 x 60 cm",
"exposition": "Ensoleille",
"periode_recolte": "VII-VIII"
},
"icones_significatives": [
{
"icone": "pot",
"signification": "Mode de semis",
"valeur": "Pre-culture en pot"
},
{
"icone": "thermometre",
"signification": "Temperature",
"valeur": "15-20 C"
},
{
"icone": "profondeur",
"signification": "Profondeur",
"valeur": "2-3 cm"
},
{
"icone": "espacement",
"signification": "Distance",
"valeur": "60 x 60 cm"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Ensoleille"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "VII-VIII"
}
],
"detail": {
"texte_integral_visible": {
"avant": "FRUITS SPHERIQUES A LA CHAIR TENDRE\nCOURGETTE DE NICE A FRUIT ROND\nCUCURBITA PEPO L.\n3 GP\nPour la culture de printemps et d'ete\nConvient pour la culture en pleine terre\n8880360",
"arriere": "Courgette De Nice a fruit rond\nUtilisation: Les varietes De Nice a fruit rond sont des courgettes rondes. La chair est de couleur creme et les jeunes fruits sont utilises comme legumes, farcis, sautes ou a l'etouffee.\nCulture et soin: Germination 6 a 10 jours. A partir de la mi-mai, les jeunes plants vigoureux peuvent etre repiques en respectant un espacement d'environ 60 x 60 cm.\nConseil: Pour la consommation, les jeunes fruits sont recoltes lorsqu'ils atteignent environ 10 cm de diametre.\nPictogrammes: 15-20 C; 2-3 cm; Semis pre-culture en pot III-V; Distance 60 x 60 cm; Exposition Ensoleille; Recolte VII-VIII.\nLe contenu suffit pour environ 7-8 plantes. 3 g."
}
}
},
{
"id": 5,
"plante": "Pois a ecosser Merveille de Kelvedon",
"nom_latin": "Pisum sativum",
"images": [
"IMG_4788.jpg",
"IMG_4789.jpg"
],
"texte_extrait": {
"avant": "Variete a haut rendement.",
"arriere": "Germination 8 a 14 jours."
},
"caracteristiques_plantation": {
"semis": "Exterieur",
"periode_semis": "II-V",
"temperature": "10-15 C",
"profondeur": "3-5 cm (lecture icone, a confirmer)",
"espacement": "5 x 40 cm",
"exposition": "Ensoleille",
"periode_recolte": "VI-VIII"
},
"icones_significatives": [
{
"icone": "thermometre",
"signification": "Temperature",
"valeur": "10-15 C"
},
{
"icone": "graines/ligne",
"signification": "Semis exterieur",
"valeur": "II-V"
},
{
"icone": "espacement",
"signification": "Distance",
"valeur": "5 x 40 cm"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Ensoleille"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "VI-VIII"
}
],
"detail": {
"texte_integral_visible": {
"avant": "VARIETE A HAUT RENDEMENT\nPOIS A ECOSSER MERVEILLE DE KELVEDON\nPISUM SATIVUM\n3 GP\nPour la culture de printemps et d'ete\nConvient pour la culture en exterieur",
"arriere": "Pois a ecosser Merveille de Kelvedon\nUtilisation: La variete Kelvedon Wonder est une variete precoce et productive de moelleux, au gout intense.\nCulture et soin: Germination 8 a 14 jours. Les pois sont des graines qui germent dans l'obscurite. Recouvrir completement les graines de terre et les maintenir constamment humides.\nConseil: Eviter l'eau stagnante et les bases temperates. Proteger le semis de pois contre les oiseaux voraces.\nPictogrammes: 10-15 C; profondeur env. 3-5 cm; Semis en exterieur II-V; Distance 5 x 40 cm; Exposition Ensoleille; Recolte VI-VIII.\nLe contenu suffit pour environ 50 plantes. 25 g."
}
}
},
{
"id": 6,
"plante": "Tomates Moneymaker",
"nom_latin": "Solanum lycopersicum",
"images": [
"IMG_4790.jpg",
"IMG_4791.jpg"
],
"texte_extrait": {
"avant": "Tomate a tuteurer, fruits aromatiques.",
"arriere": "Semis en pre-culture en pot. Germination 12 a 18 jours."
},
"caracteristiques_plantation": {
"semis": "Pre-culture en pot",
"periode_semis": "III-IV",
"temperature": "20-25 C",
"profondeur": "1 cm",
"espacement": "60 x 60 cm",
"exposition": "Ensoleille",
"periode_recolte": "VII-X"
},
"icones_significatives": [
{
"icone": "pot",
"signification": "Mode de semis",
"valeur": "Pre-culture en pot"
},
{
"icone": "thermometre",
"signification": "Temperature",
"valeur": "20-25 C"
},
{
"icone": "profondeur",
"signification": "Profondeur",
"valeur": "1 cm"
},
{
"icone": "espacement",
"signification": "Distance",
"valeur": "60 x 60 cm"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Ensoleille"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "VII-X"
}
],
"detail": {
"texte_integral_visible": {
"avant": "TOMATE A TUTEURER AUX FRUITS AROMATIQUES ET RESISTANTS A L'ECLATEMENT\nTOMATES MONEYMAKER\nSOLANUM LYCOPERSICUM\n1 GP\nPour la culture de printemps et d'ete\nConvient pour la culture en pleine terre\n8880340",
"arriere": "Tomates Moneymaker\nUtilisation: Une variete tres productive. Les fruits de 60 a 80 g sont tres aromatiques.\nCulture et soin: Germination 12 a 18 jours. A partir de la mi-mai, les jeunes plants vigoureux peuvent etre repiques en respectant un espacement d'environ 60 x 60 cm. Les tomates ont besoin d'un tuteur et d'un sol meuble et fertilise.\nConseil: Pour l'arrosage direct, recourir a la technique du pot en terre enfoui dans le sol et rempli d'eau. Enlever les gourmands et les feuilles proches du sol.\nPictogrammes: 20-25 C; 1 cm; Semis pre-culture en pot III-IV; Distance 60 x 60 cm; Exposition Ensoleille; Recolte VII-X.\nLe contenu suffit pour environ 45 plantes. 0,3 g."
}
}
},
{
"id": 7,
"plante": "Poireau Bleu de Solaise",
"nom_latin": "Allium porrum",
"images": [
"IMG_4792.jpg",
"IMG_4793.jpg"
],
"texte_extrait": {
"avant": "Resistant au froid. Semis: avril a mai. Recolte: decembre a mars.",
"arriere": "Exposition soleil, T C de germination 10 C, levee 15 a 20 jours."
},
"caracteristiques_plantation": {
"semis": "Pleine terre / terrine-godet",
"periode_semis": "IV-V",
"temperature": "10 C (germination)",
"profondeur": "1 cm",
"espacement": "10 cm entre plants",
"exposition": "Soleil",
"periode_recolte": "XII-III",
"duree_apres_semis": "~8 mois"
},
"icones_significatives": [
{
"icone": "flocon",
"signification": "Resistance",
"valeur": "Resistant au froid"
},
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Avril-Mai"
},
{
"icone": "panier",
"signification": "Periode recolte",
"valeur": "Decembre-Mars"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
}
],
"detail": {
"texte_integral_visible": {
"avant": "inVivo Nous on seme\nPOIREAU BLEU DE SOLAISE\nCODE PRIX 3\nCOLLECTION LEGUME FEUILLE\nRESISTANT AU FROID\nFORMAT IDEAL POUR GRAND POTAGER\nSEMIS: AVRIL A MAI\nRECOLTE: DECEMBRE A MARS\n5 x 5 m",
"arriere": "COLLECTION LEGUME FEUILLE\nConseils d'utilisation\nPeriode de semis: avril-mai\nPeriode de recolte: decembre-mars\nExposition: soleil\nT C de germination: 10 C\nTemps de levee: 15 a 20 jours\nArrosage: +++\nRecolte: des 8 mois apres les semis\nPour semer en terre: preparer l'espace, choisir la methode de semis, recouvrir, tasser, arroser, maintenir le sol humide puis eclaircir.\nTableaux methodes/indications: profondeur de semis ~1 cm, stade de repiquage ~7 cm de hauteur, espacement entre plants ~10 cm.\nPoids net: 10 g."
}
}
},
{
"id": 8,
"plante": "Echalion Zebrune",
"nom_latin": "Allium cepa",
"images": [
"IMG_4794.jpg",
"IMG_4795.jpg"
],
"texte_extrait": {
"avant": "Calendrier semis/recolte par mois.",
"arriere": "Semis de fevrier a avril en lignes espacees de 20-25 cm. Recolte d'aout a octobre."
},
"caracteristiques_plantation": {
"semis": "Pleine terre",
"periode_semis": "II-IV",
"temperature": "Sol min 10 C",
"profondeur": null,
"espacement": "20-25 cm entre lignes, eclaircissage a 8 cm",
"exposition": "Tous types de sol, prefere sols sableux",
"periode_recolte": "VIII-X",
"levee": "13-15 jours"
},
"icones_significatives": [
{
"icone": "calendrier mois",
"signification": "Periodes semis/recolte",
"valeur": "Semis II-IV, recolte VIII-X"
},
{
"icone": "thermometre",
"signification": "Temperature sol",
"valeur": "10 C min"
},
{
"icone": "etape 1",
"signification": "Semis",
"valeur": "Lignes 20-25 cm"
},
{
"icone": "etape 2",
"signification": "Eclaircissage",
"valeur": "8 cm"
},
{
"icone": "etape 3",
"signification": "Recolte",
"valeur": "Aout-Octobre"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vilmorin depuis 1743\nCODE 2\nEchalion Zebrune\nCalendrier semis/recolte par mois (pastilles sur fevrier-avril et aout-octobre).",
"arriere": "Allium cepa\nEchalion Zebrune\nLevee en 13/15 jours\nTemperature du sol 10 C mini\nCette variete est proche du type echalote cuisse de poulet, avec sa forme allongee et sa couleur cuivree.\nPlantes compagnes: l'echalion aime la proximite de la poiree.\nConseil culture: pousse partout mais apprecie les sols sableux, craint l'humidite.\n1. Semis: semez de fevrier a avril, en pleine terre, en lignes espacees de 20-25 cm.\n2. Eclaircissage: quand vos echalions ont 3-4 feuilles, arracher les plus petits; conserver les plus vigoureux, afin de ne laisser qu'un echalion tous les 8 cm.\n3. Recolte: recoltez d'aout a octobre. Arrachez par temps sec, laissez secher sur le sol quelques jours puis stockez au sec."
}
}
},
{
"id": 9,
"plante": "Courge Musquee Sucrine du Berry",
"nom_latin": "Cucurbita moschata",
"images": [
"IMG_4796.jpg",
"IMG_4797.jpg"
],
"texte_extrait": {
"avant": "Adaptee aux recettes salees et sucrees. Jusqu'a 10 pieds.",
"arriere": "Semis de mars a mai, 4-5 graines par trou, trous distants de 1 m x 1,50 m."
},
"caracteristiques_plantation": {
"semis": "Pleine terre",
"periode_semis": "III-V",
"temperature": "Sol min 15 C",
"profondeur": "Trou peu profond",
"espacement": "1 m x 1,5 m",
"exposition": "Ensoleillee",
"periode_recolte": "IX-XII",
"levee": "6-8 jours"
},
"icones_significatives": [
{
"icone": "calendrier mois",
"signification": "Periodes",
"valeur": "Semis III-V, recolte IX-XII"
},
{
"icone": "thermometre",
"signification": "Temperature sol",
"valeur": "15 C min"
},
{
"icone": "capsule 'jusqu'a'",
"signification": "Rendement",
"valeur": "Jusqu'a 10 pieds"
},
{
"icone": "etape semis",
"signification": "Nombre de graines",
"valeur": "4-5 graines/trou"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vilmorin depuis 1743\nCODE 3\nLes Legumes d'autrefois\nCourge Musquee Sucrine du Berry\nAdaptee aux recettes salees et sucrees\nCalendrier semis/recolte par mois\nJusqu'a 10 pieds",
"arriere": "Cucurbita moschata\nCourge Musquee Sucrine du Berry\nLevee en 6/8 jours\nTemperature du sol 15 C mini\nLa courge Sucrine du Berry est une variete coureuse produisant 5 a 8 fruits par pied, de 12 a 15 cm de diametre dans la partie renflee, de 1 a 3 kg en moyenne.\nConseil cuisine: delicieuse en soupes, tartes, puree ou a l'aperitif en croustilles.\nPlantes compagnes: aime la proximite du radis.\nConseil culture: pour avoir de grosses courges, recouvrir la tige de terre pour permettre la creation de nouvelles racines; aime l'exposition ensoleillee.\n1. Semis: semez 4-5 graines de mars a mai, dans des petits trous peu profonds, distants de 1 m x 1,50 m.\n2. Eclaircissage: garder le plus vigoureux quand 3-4 feuilles.\n3. Recolte: recoltez de septembre a decembre."
}
}
},
{
"id": 10,
"plante": "Laitue Pommee Grosse Blonde Paresseuse",
"nom_latin": null,
"images": [
"IMG_4798.jpg",
"IMG_4799.jpg"
],
"texte_extrait": {
"avant": "Resistante a la chaleur. Je seme avril a juillet. Je recolte 3 mois apres le semis.",
"arriere": "Temperature minimum du sol 10 C. Levee en 8-10 jours."
},
"caracteristiques_plantation": {
"semis": "Sous abri puis pleine terre / semis direct",
"periode_semis": "IV-VII",
"temperature": "Sol min 10 C",
"profondeur": "~3 cm (semis en terrine selon notice)",
"espacement": null,
"exposition": null,
"periode_recolte": "Fin VI-X",
"duree_apres_semis": "~3 mois"
},
"icones_significatives": [
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Avril-Juillet"
},
{
"icone": "panier",
"signification": "Recolte",
"valeur": "3 mois apres semis"
},
{
"icone": "tableau mensuel",
"signification": "Calendrier",
"valeur": "Semis IV-VII, recolte fin VI-X"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vilmorin depuis 1743\nCODE 1\nLaitue Pommee Grosse Blonde Paresseuse\nResistante a la chaleur - Tardive\nJe seme: AVRIL A JUILLET\n5 x 5 m\nJe recolte: 3 MOIS apres les semis",
"arriere": "Variete recommandee pour des recoltes d'ete-automne, resistante a la chaleur et lente a la montee a graines.\nJe seme: d'avril a juillet, tous les 15 jours pour des recoltes echelonnees.\nJe recolte: de fin juin a octobre, 3 mois apres le semis.\nJe deguste: feuilles crues, en salade ou braisees.\nNos secrets pour reussir votre recolte:\n- Temperature minimum du sol 10 C\n- Levee en 8-10 jours\n- Semer en terrine (1 graine tous les 3 cm, recouvrir de terreau, arroser, placer sous abri)\n- Ou semer en pleine terre en avril-mai quand le sol se rechauffe\n- Repiquer au stade 5-6 feuilles\nCalendrier en pictogrammes: semis IV-VII, recolte fin VI-X."
}
}
},
{
"id": 11,
"plante": "Chou Pomme de Brunswick",
"nom_latin": null,
"images": [
"IMG_4800.jpg",
"IMG_4801.jpg"
],
"texte_extrait": {
"avant": "Je seme avril-juillet. Je recolte 3-4 mois apres semis.",
"arriere": "Temperature minimum du sol 15 C. Levee en 6-8 jours."
},
"caracteristiques_plantation": {
"semis": "Terrine/godet puis pleine terre",
"periode_semis": "IV-VII",
"temperature": "Sol min 15 C",
"profondeur": null,
"espacement": "60 x 50 cm apres repiquage",
"exposition": null,
"periode_recolte": "VII-XI",
"duree_apres_semis": "3-4 mois"
},
"icones_significatives": [
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Avril-Juillet"
},
{
"icone": "panier",
"signification": "Periode recolte",
"valeur": "Juillet-Novembre"
},
{
"icone": "tableau mensuel",
"signification": "Calendrier",
"valeur": "Semis IV-VII, recolte VII-XI"
},
{
"icone": "thermometre",
"signification": "Temperature sol",
"valeur": "15 C min"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vilmorin depuis 1743\nCODE 0\nChou Pomme de Brunswick\nPomme tres volumineuse\nPour des recoltes d'ete-automne\nJe seme: AVRIL - JUILLET\nJusqu'a 90 pieds\nJe recolte: 3-4 MOIS apres semis",
"arriere": "Variete tardive aux feuilles vertes produisant une pomme volumineuse (jusqu'a 3,5 kg), compacte et tres serree.\nJe seme: d'avril a juillet, dans une terre fraiche, humide et riche d'engrais naturels.\nJe recolte: de juillet a novembre, 3-4 mois apres le semis.\nJe deguste: pommes crues, rapees en salade, ou cuites en potee.\nNos secrets pour reussir votre recolte:\n- Temperature minimum du sol 15 C\n- Levee en 6-8 jours\n- Semis en terrine (2-3 graines) puis repiquage\n- Semis direct possible en avril-mai (1 graine tous les 30 cm)\n- Repiquer en pleine terre a 60 x 50 cm au stade 5-6 feuilles\nCalendrier en pictogrammes: semis IV-VII, recolte VII-XI."
}
}
},
{
"id": 12,
"plante": "Chou-fleur Nautilus HF1",
"nom_latin": null,
"images": [
"IMG_4802.jpg",
"IMG_4803.jpg"
],
"texte_extrait": {
"avant": "Semis: mars a juillet. Recolte: juillet a novembre.",
"arriere": "Exposition soleil. T C de germination 15 C. Levee 5 jours."
},
"caracteristiques_plantation": {
"semis": "Sous abri / godet / pleine terre",
"periode_semis": "III-VII",
"temperature": "15 C (germination)",
"profondeur": "< 1 cm",
"espacement": "70 cm entre plants",
"exposition": "Soleil",
"periode_recolte": "VII-XI",
"duree_apres_semis": "~4 mois"
},
"icones_significatives": [
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Mars-Juillet"
},
{
"icone": "panier",
"signification": "Periode recolte",
"valeur": "Juillet-Novembre"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
},
{
"icone": "thermometre",
"signification": "Temperature germination",
"valeur": "15 C"
},
{
"icone": "profondeur",
"signification": "Profondeur semis",
"valeur": "< 1 cm"
}
],
"detail": {
"texte_integral_visible": {
"avant": "inVivo Nous on seme\nCHOU-FLEUR NAUTILUS HF1\nCODE PRIX 4\nCOLLECTION LEGUME FEUILLE\nRECOLTE GENEREUSE\nSEMIS: MARS A JUILLET\nRECOLTE: JUILLET A NOVEMBRE\nJusqu'a 60 pieds",
"arriere": "COLLECTION LEGUME FEUILLE\nLe Chou-Fleur Nautilus HF1 est une variete hybride precoce, productive et de qualite gustative.\nConseils d'utilisation:\nPeriode de semis: mars a juillet\nPeriode de recolte: juillet a novembre\nExposition: soleil\nT C de germination: 15 C\nTemps de levee: 5 jours\nArrosage: ++\nRecolte: 4 mois apres les semis\nPour semer en terre: preparer l'espace, recouvrir, tasser, arroser et maintenir le sol humide.\nIndications sur semis: profondeur < 1 cm; stade de repiquage 4-5 feuilles; espacement entre plants 70 cm.\nPoids net: 0,3 g."
}
}
},
{
"id": 13,
"plante": "Tomate Cornue Cornabel HF1",
"nom_latin": "Solanum lycopersicum",
"images": [
"IMG_4804.jpg",
"IMG_4805.jpg"
],
"texte_extrait": {
"avant": "Je seme fevrier-mai. Je recolte 5 mois apres le semis.",
"arriere": "Temperature minimum du sol 18-20 C. Levee en 6-8 jours."
},
"caracteristiques_plantation": {
"semis": "Godet/terrine puis pleine terre",
"periode_semis": "II-V",
"temperature": "18-20 C (20 C recommande au semis en godet)",
"profondeur": null,
"espacement": "50 x 80 cm",
"exposition": null,
"periode_recolte": "VII-X",
"duree_apres_semis": "~5 mois"
},
"icones_significatives": [
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Fin fevrier-mai"
},
{
"icone": "panier",
"signification": "Periode recolte",
"valeur": "Juillet-Octobre"
},
{
"icone": "thermometre",
"signification": "Temperature sol",
"valeur": "18-20 C"
},
{
"icone": "tableau mensuel",
"signification": "Calendrier",
"valeur": "Semis II-V, recolte VII-X"
}
],
"detail": {
"texte_integral_visible": {
"avant": "Vilmorin depuis 1743\nCODE 3\nGRAINES D'EXCEPTION\nTomate Cornue Cornabel HF1\nJe seme: FEVRIER - MAI\nJusqu'a 25 pieds\nJe recolte: 5 MOIS apres le semis\nRESISTE AUX MALADIES",
"arriere": "Variete hybride de type cornue, tres resistante aux maladies (verticilliose, fusariose, va).\nAmelioration de la tomate Cornue des Andes, fruits longs (15 cm), charnus, lourds (jusqu'a 200 g), chair fondante, peu acide et sans pepins.\nJe seme: de fin fevrier a mai, dans un sol riche en amendements.\nJe recolte: de juillet a octobre, 5 mois apres le semis.\nJe deguste: fruits crus coupes en lamelles pour salades estivales.\nNos secrets pour reussir votre recolte:\n- Temperature minimum du sol 18-20 C\n- Levee en 6-8 jours\n- Semis en godet (2 graines) ou pleine terre en avril-mai si sol rechauffe\n- Repiquer en mai-juin a 50 x 80 cm\nCalendrier en pictogrammes: semis II-V, recolte VII-X."
}
}
},
{
"id": 14,
"plante": "Pois mangetout Carouby de Maussane",
"nom_latin": "Pisum sativum",
"images": [
"IMG_4806.jpg",
"IMG_4807.jpg"
],
"texte_extrait": {
"avant": "Semis: fevrier a novembre. Recolte: mai a juillet.",
"arriere": "Exposition soleil. T C de germination 20 C. Levee 6-8 jours."
},
"caracteristiques_plantation": {
"semis": "Pleine terre / ligne / poquet",
"periode_semis": "II-XI (selon sachet)",
"temperature": "20 C (germination)",
"profondeur": "3 cm",
"espacement": "40 cm entre plants",
"exposition": "Soleil",
"periode_recolte": "V-VII (ou 3 mois apres semis de printemps)",
"duree_apres_semis": "3 mois (printemps), 6-7 mois (automne)"
},
"icones_significatives": [
{
"icone": "main semis",
"signification": "Periode semis",
"valeur": "Fevrier-Novembre"
},
{
"icone": "panier",
"signification": "Periode recolte",
"valeur": "Mai-Juillet"
},
{
"icone": "soleil",
"signification": "Exposition",
"valeur": "Soleil"
},
{
"icone": "thermometre",
"signification": "Temperature germination",
"valeur": "20 C"
},
{
"icone": "goutte",
"signification": "Arrosage",
"valeur": "Soutenu (+)"
}
],
"detail": {
"texte_integral_visible": {
"avant": "inVivo Nous on seme\nPOIS MANGETOUT CAROUBY DE MAUSSANE\nPied demi-nain - H. 90 cm\nCODE PRIX 2\nCOLLECTION POIS\nFACILE A CULTIVER\nSEMIS: FEVRIER A NOVEMBRE\nRECOLTE: MAI A JUILLET\n4 x 5 m",
"arriere": "COLLECTION POIS\nLe Pois Carouby de Maussane (Pisum sativum L) est une variete demi-naine, tardive, a production importante et assez groupee.\nConseils d'utilisation:\nPeriode de semis: fevrier a novembre\nPeriode de recolte: mai a juillet\nExposition: soleil\nT C de germination: 20 C\nTemps de levee: 6 a 8 jours\nArrosage: +++\nRecolte: 3 mois apres les semis de printemps, 6 a 7 mois apres semis d'automne\nIndications sur semis: espacement 40 cm (10 graines) en ligne; 60 cm en poquet; profondeur 3 cm; espacement entre plants 40 cm.\nEntretien: biner en surface, butter, tuteurer, veiller a l'arrosage regulier.\nRecolte: recolter juste au debut de formation des grains.\nPoids net: 200 g."
}
}
}
],
"notes": [
"Extraction faite manuellement depuis photos (sans OCR automatique).",
"Quelques valeurs tres fines (ex: profondeur/espacements sur certains sachets) peuvent necessiter une verification visuelle complementaire."
]
}

View File

@@ -0,0 +1,140 @@
# Intrants & Fabrications — Design
> **Pour Claude :** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Gérer les achats d'intrants (terreau, engrais, traitements) et les fabrications maison (compost, décoctions, purins) dans une vue unique avec deux onglets, liés aux jardins/plantations/tâches existants.
**Architecture:** Option B — deux tables distinctes (`achat_intrant` + `fabrication`), une vue `IntratsView.vue` avec onglets, deux routers FastAPI. Les ingrédients d'une fabrication sont stockés en JSON.
**Tech Stack:** FastAPI + SQLModel + SQLite (backend), Vue 3 + Pinia + Tailwind Gruvbox (frontend)
---
## Modèle de données
### Table `achat_intrant`
| Champ | Type | Notes |
|---|---|---|
| id | INTEGER PK | |
| categorie | TEXT | `terreau` \| `engrais` \| `traitement` \| `autre` |
| nom | TEXT | Nom du produit |
| marque | TEXT | Fabricant / marque |
| boutique_nom | TEXT | Gamm Vert, Lidl, Amazon… |
| boutique_url | TEXT | URL fiche produit |
| prix | REAL | En € |
| poids | TEXT | Ex: "20L", "1kg", "500ml" |
| date_achat | TEXT | ISO date |
| dluo | TEXT | ISO date limite d'utilisation |
| notes | TEXT | Observations libres |
| jardin_id | INTEGER FK → garden | Optionnel |
| plantation_id | INTEGER FK → planting | Optionnel |
| tache_id | INTEGER FK → task | Optionnel |
| created_at | TEXT | ISO datetime |
### Table `fabrication`
| Champ | Type | Notes |
|---|---|---|
| id | INTEGER PK | |
| type | TEXT | `compost` \| `decoction` \| `purin` \| `autre` |
| nom | TEXT | Ex: "Purin d'ortie mai 2026" |
| ingredients | TEXT | JSON : `[{"nom": "ortie", "quantite": "1kg"}, ...]` |
| date_debut | TEXT | ISO date |
| date_fin_prevue | TEXT | ISO date |
| statut | TEXT | `en_cours` \| `pret` \| `utilise` \| `echec` |
| quantite_produite | TEXT | Ex: "8L", "50kg" |
| notes | TEXT | Recette libre, observations |
| jardin_id | INTEGER FK → garden | Optionnel |
| plantation_id | INTEGER FK → planting | Optionnel |
| tache_id | INTEGER FK → task | Optionnel |
| created_at | TEXT | ISO datetime |
---
## API REST
```
GET /api/achats → liste des achats (filtre: categorie, jardin_id)
POST /api/achats → créer un achat
GET /api/achats/{id} → détail
PUT /api/achats/{id} → modifier
DEL /api/achats/{id} → supprimer
GET /api/fabrications → liste (filtre: type, statut, jardin_id)
POST /api/fabrications → créer
GET /api/fabrications/{id} → détail
PUT /api/fabrications/{id} → modifier
DEL /api/fabrications/{id} → supprimer
PATCH /api/fabrications/{id}/statut → changer statut rapidement
```
---
## Frontend
### Nouveau fichier : `frontend/src/views/IntratsView.vue`
**Nouvel item sidebar :** 🧪 Intrants (entre Outils et Réglages)
**Structure :**
```
┌─────────────────────────────────────────────────────┐
│ 🧪 Intrants [🛒 Achats] [🌿 Fabrications] │
│ │
│ Onglet Achats : │
│ • Filtres : Catégorie (terreau/engrais/traitement) │
│ • Grille de cartes : nom, marque, prix, poids, │
│ enseigne, DLUO (rouge si expirée) │
│ • Bouton "+ Ajouter un achat" │
│ • Popup détail + formulaire ajout/édition │
│ │
│ Onglet Fabrications : │
│ • Filtres : Type + Statut │
│ • Cartes : nom, type, statut (badge coloré), │
│ date fin prévue, ingrédients résumés │
│ • Boutons rapides : ✓ Prêt / ✗ Échec │
│ • Popup détail avec liste ingrédients éditable │
└─────────────────────────────────────────────────────┘
```
**Couleurs statut fabrication :**
- `en_cours` → orange
- `pret` → vert
- `utilise` → gris text-muted
- `echec` → rouge
### Nouveaux fichiers API : `frontend/src/api/achats.ts` + `frontend/src/api/fabrications.ts`
### Nouveaux stores Pinia : `frontend/src/stores/achats.ts` + `frontend/src/stores/fabrications.ts`
### Mise à jour `App.vue` : ajouter route `/intrants` dans la sidebar
---
## Migration BDD
Ajouter dans `backend/app/migrate.py` :
- Section `"achat_intrant"` avec toutes ses colonnes
- Section `"fabrication"` avec toutes ses colonnes
Les tables seront créées au démarrage via SQLModel metadata si absentes, puis migrées par `run_migrations()`.
---
## Fichiers à créer / modifier
| Fichier | Action |
|---|---|
| `backend/app/models/intrant.py` | Créer : AchatIntrant + Fabrication SQLModel |
| `backend/app/routers/achats.py` | Créer : CRUD AchatIntrant |
| `backend/app/routers/fabrications.py` | Créer : CRUD Fabrication + PATCH statut |
| `backend/app/main.py` | Modifier : import + include routers |
| `backend/app/migrate.py` | Modifier : ajouter sections achat_intrant + fabrication |
| `frontend/src/api/achats.ts` | Créer |
| `frontend/src/api/fabrications.ts` | Créer |
| `frontend/src/stores/achats.ts` | Créer |
| `frontend/src/stores/fabrications.ts` | Créer |
| `frontend/src/views/IntratsView.vue` | Créer |
| `frontend/src/router/index.ts` | Modifier : route /intrants |
| `frontend/src/App.vue` | Modifier : sidebar item 🧪 Intrants |

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
# Plant Associations Implementation Plan
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
**Goal:** Ajouter des associations favorables/défavorables (plantes amies/ennemies) à chaque plante, éditables depuis la popup d'édition.
**Architecture:** Deux colonnes JSON (`associations_favorables`, `associations_defavorables`) dans le modèle `Plant` (List[str] de noms communs). Migration via migrate.py. UI tag-based avec autocomplete et validation croisée dans PlantesView.vue.
**Tech Stack:** FastAPI + SQLModel + SQLAlchemy JSON column (backend) · Vue 3 + TypeScript (frontend)
---
### Task 1: Backend — modèle Plant
**Files:**
- Modify: `backend/app/models/plant.py`
**Step 1: Ajouter les imports nécessaires**
```python
from typing import List, Optional
from sqlalchemy import Column
from sqlalchemy import JSON as SA_JSON
```
**Step 2: Ajouter les 2 champs dans la classe `Plant`**
Après le champ `notes`, avant `created_at` :
```python
associations_favorables: Optional[List[str]] = Field(
default=None,
sa_column=Column("associations_favorables", SA_JSON, nullable=True),
)
associations_defavorables: Optional[List[str]] = Field(
default=None,
sa_column=Column("associations_defavorables", SA_JSON, nullable=True),
)
```
---
### Task 2: Backend — migration
**Files:**
- Modify: `backend/app/migrate.py`
**Step 1: Ajouter les 2 colonnes dans `EXPECTED_COLUMNS["plant"]`**
```python
"plant": [
("categorie", "TEXT", None),
("hauteur_cm", "INTEGER", None),
("maladies_courantes", "TEXT", None),
("astuces_culture", "TEXT", None),
("url_reference", "TEXT", None),
("associations_favorables", "TEXT", None), # JSON list[str]
("associations_defavorables", "TEXT", None), # JSON list[str]
],
```
---
### Task 3: Frontend — interface TypeScript
**Files:**
- Modify: `frontend/src/api/plants.ts`
**Step 1: Ajouter les 2 champs à l'interface `Plant`**
```typescript
associations_favorables?: string[]
associations_defavorables?: string[]
```
---
### Task 4: Frontend — PlantesView.vue (formulaire + détail)
**Files:**
- Modify: `frontend/src/views/PlantesView.vue`
**Step 1: Étendre `form` reactive**
Dans `const form = reactive({...})` ajouter :
```typescript
associations_favorables: [] as string[],
associations_defavorables: [] as string[],
```
**Step 2: Ajouter ref pour l'autocomplete**
```typescript
const assocInput = reactive({ fav: '', def: '' })
```
**Step 3: Computed — noms de plantes disponibles pour l'autocomplete**
```typescript
const allPlantNames = computed(() =>
plantsStore.plants
.map(p => p.nom_commun)
.filter(n => n && n !== form.nom_commun)
.sort()
)
function filteredAssocSuggestions(type: 'fav' | 'def') {
const query = assocInput[type].toLowerCase()
const excluded = type === 'fav'
? new Set([...form.associations_favorables, ...form.associations_defavorables])
: new Set([...form.associations_defavorables, ...form.associations_favorables])
return allPlantNames.value
.filter(n => !excluded.has(n) && n.toLowerCase().includes(query))
.slice(0, 8)
}
function addAssoc(type: 'fav' | 'def', name: string) {
const list = type === 'fav' ? form.associations_favorables : form.associations_defavorables
const other = type === 'fav' ? form.associations_defavorables : form.associations_favorables
if (!name.trim() || list.includes(name) || other.includes(name)) return
list.push(name)
assocInput[type] = ''
}
function removeAssoc(type: 'fav' | 'def', name: string) {
const list = type === 'fav' ? form.associations_favorables : form.associations_defavorables
const idx = list.indexOf(name)
if (idx !== -1) list.splice(idx, 1)
}
```
**Step 4: `startEdit` — peupler les nouvelles listes**
```typescript
associations_favorables: [...(p.associations_favorables ?? [])],
associations_defavorables: [...(p.associations_defavorables ?? [])],
```
**Step 5: `submitPlant` — inclure les listes dans le payload**
Le spread `{ ...form }` les inclut automatiquement — rien à changer.
**Step 6: Ajouter le bloc UI dans le formulaire (pleine largeur, après les 2 colonnes existantes)**
```html
<!-- Associations — pleine largeur -->
<div class="md:col-span-2 grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Favorables -->
<div>
<label class="text-[10px] font-black text-green uppercase tracking-widest block mb-2">
🤝 Associations favorables
</label>
<div class="flex flex-wrap gap-1.5 mb-2 min-h-[28px]">
<span v-for="n in form.associations_favorables" :key="n"
class="flex items-center gap-1 bg-green/10 border border-green/40 text-green text-[11px] px-2 py-0.5 rounded-full">
{{ n }}
<button type="button" @click="removeAssoc('fav', n)" class="hover:text-red leading-none"></button>
</span>
</div>
<div class="relative">
<input v-model="assocInput.fav"
placeholder="Nom commun d'une plante..."
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-green outline-none"
@keydown.enter.prevent="addAssoc('fav', assocInput.fav)" />
<ul v-if="assocInput.fav && filteredAssocSuggestions('fav').length"
class="absolute z-10 mt-1 w-full bg-bg-hard border border-bg-soft rounded-xl shadow-lg overflow-hidden max-h-40 overflow-y-auto">
<li v-for="s in filteredAssocSuggestions('fav')" :key="s"
@click="addAssoc('fav', s)"
class="px-3 py-2 text-sm text-text hover:bg-green/10 hover:text-green cursor-pointer">
{{ s }}
</li>
</ul>
</div>
</div>
<!-- Défavorables -->
<div>
<label class="text-[10px] font-black text-red uppercase tracking-widest block mb-2">
⚡ Associations défavorables
</label>
<div class="flex flex-wrap gap-1.5 mb-2 min-h-[28px]">
<span v-for="n in form.associations_defavorables" :key="n"
class="flex items-center gap-1 bg-red/10 border border-red/40 text-red text-[11px] px-2 py-0.5 rounded-full">
{{ n }}
<button type="button" @click="removeAssoc('def', n)" class="hover:text-red leading-none"></button>
</span>
</div>
<div class="relative">
<input v-model="assocInput.def"
placeholder="Nom commun d'une plante..."
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-red outline-none"
@keydown.enter.prevent="addAssoc('def', assocInput.def)" />
<ul v-if="assocInput.def && filteredAssocSuggestions('def').length"
class="absolute z-10 mt-1 w-full bg-bg-hard border border-bg-soft rounded-xl shadow-lg overflow-hidden max-h-40 overflow-y-auto">
<li v-for="s in filteredAssocSuggestions('def')" :key="s"
@click="addAssoc('def', s)"
class="px-3 py-2 text-sm text-text hover:bg-red/10 hover:text-red cursor-pointer">
{{ s }}
</li>
</ul>
</div>
</div>
</div>
```
**Step 7: Ajouter le bloc lecture dans la modale détail (après la section Notes)**
```html
<!-- Associations -->
<div v-if="detailPlant.associations_favorables?.length || detailPlant.associations_defavorables?.length" class="space-y-3">
<h3 class="text-[10px] font-black text-text-muted uppercase tracking-widest">Associations</h3>
<div class="grid grid-cols-2 gap-4">
<div v-if="detailPlant.associations_favorables?.length">
<div class="text-[10px] font-black text-green uppercase mb-1.5">🤝 Favorables</div>
<div class="flex flex-wrap gap-1.5">
<span v-for="n in detailPlant.associations_favorables" :key="n"
class="bg-green/10 border border-green/40 text-green text-[11px] px-2 py-0.5 rounded-full">
{{ n }}
</span>
</div>
</div>
<div v-if="detailPlant.associations_defavorables?.length">
<div class="text-[10px] font-black text-red uppercase mb-1.5">⚡ À éviter</div>
<div class="flex flex-wrap gap-1.5">
<span v-for="n in detailPlant.associations_defavorables" :key="n"
class="bg-red/10 border border-red/40 text-red text-[11px] px-2 py-0.5 rounded-full">
{{ n }}
</span>
</div>
</div>
</div>
</div>
```

BIN
docs/terreau/IMG_4817.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

BIN
docs/terreau/IMG_4818.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

View File

@@ -0,0 +1,123 @@
{
"source_dossier": "docs/terreau",
"regle_groupement": "2 images consecutives = 1 produit",
"produits": [
{
"id": 1,
"produit": "Fertiligene Terreau Universel",
"images": [
"IMG_4817.jpg",
"IMG_4818.jpg"
],
"marque": "Fertiligene",
"categorie": "Terreau universel",
"volume": "60 L",
"masse_nette": "13,2 kg",
"origine": "Fabrique en France",
"usage": [
"Toutes plantes interieur et exterieur",
"Pots, bacs, pleine terre",
"Rempotage",
"Plantation",
"Creation de parterres"
],
"promesses_produit": [
"Avec engrais et fumier",
"Accroit les recoltes et l'enracinement",
"Favorise la floraison et l'enracinement",
"Pour des plantes vigoureuses"
],
"composition": {
"support_de_culture": "NF U 44-551",
"type_engrais": "Terreau avec engrais NF U 42-001 (engrais mineral NPK)",
"matieres_premieres": [
"Tourbe de sphaigne",
"Matieres vegetales en melange",
"Compost vert",
"Fumier composte",
"Terre vegetale"
],
"indicateurs": {
"matiere_seche": "35% en masse de produit brut",
"matiere_organique": "50% en masse de produit sec",
"ph": "6,8",
"conductivite": "65 mS/m",
"capacite_retention_eau": "60% en volume"
},
"npk": {
"azote_n": "240 g/m3",
"anhydride_phosphorique_p2o5": "120 g/m3",
"oxyde_de_potassium_k2o": "40 g/m3"
}
},
"explication_composants": [
{
"code": "T",
"element": "Tourbe",
"role": "Retient l'eau, fixe et restitue les elements fertilisants necessaires a la croissance des plantes"
},
{
"code": "F",
"element": "Fumier",
"role": "Enrichit et ameliore la structure du sol, favorise la reprise des vegetaux"
},
{
"code": "C",
"element": "Compost vert",
"role": "Participe a la fertilisation du sol car concentre en elements nutritifs"
},
{
"code": "MV",
"element": "Matieres vegetales",
"role": "Facilitent l'aeration du sol et donc l'enracinement"
}
],
"mode_emploi": {
"precautions": [
"Le port de gants de jardinage est recommande lors de l'utilisation",
"Ne pas ingerer"
],
"periode": {
"libelle": "Periode ideale indiquee sur calendrier mensuel",
"contrainte": "Ne jamais planter en periode de gel"
},
"rempotage": [
"Choisir un contenant de dimensions superieures",
"Disposer un lit de graviers ou de billes d'argile de 2 cm puis recouvrir d'une couche de terreau universel d'environ 1/3 de la hauteur du pot",
"Placer la plante au centre, completer avec le terreau, tasser legerement et arroser copieusement"
],
"plantation_pleine_terre": [
"Creuser un trou adapte aux dimensions de la plante",
"Assurer un bon drainage avec un lit de gros graviers ou billes d'argile et ajouter une couche de terreau universel (5 a 6 cm environ), bien melanger a la terre",
"Placer la plante en etalant les racines, completer avec un melange 50% terreau universel / 50% terre de jardin, tasser et arroser copieusement"
]
},
"conseils_entretien": {
"fertilisation": "Commencer 6 semaines apres plantation avec un engrais universel (Performance Organics) ou fertiliser 1 fois/an avec un engrais enrobe (Osmocote Max), selon recommandations produit",
"arrosage_pots": "1 a 2 fois par semaine selon les besoins (eviter les soucoupes pleines d'eau)",
"arrosage_pleine_terre": "1 fois par semaine selon les besoins pendant l'annee de plantation",
"surfacage": "Si la plante est trop importante pour rempotage: retirer 2-3 cm de surface et remplacer par du terreau universel, tasser puis arroser"
},
"equivalences_volume_sac": [
"6 pots (rond diametre 25 cm ou carre 21x21x21 cm)",
"4 gros pots (rond diametre 30 cm ou carre 25x25x25 cm)",
"2 grandes jardiniere (100x19x16 cm)",
"1 trou en pleine terre d'environ 40x40x40 cm"
],
"tri_recyclage": {
"consigne": "Le tri est plus facile",
"element": "SAC"
},
"detail": {
"texte_integral_visible": {
"avant": "Fertiligene - TERREAU UNIVERSEL - Toutes plantes interieur et exterieur - Pots, bacs, pleine terre - Avec engrais et fumier - Accroit les recoltes et l'enracinement - Favorise la floraison et l'enracinement - Fabrique en France - 60 L",
"arriere": "Fertiligene Terreau Universel. Ce terreau universel est adapte a tous types de plantes d'interieur ou de jardin. Il est parfaitement adapte pour le rempotage, la plantation, la creation de parterres. Il est enrichi en engrais et en fumier pour une nutrition continue. Il s'utilise pur ou en melange a la terre du jardin. L'engrais apporte a la plante la plupart des elements nutritifs necessaires pour pousser et fleurir abondamment.\nMode d'emploi: port de gants recommande, ne pas ingerer. Periode ideale indiquee par calendrier, ne jamais planter en periode de gel.\nRempotage en 3 etapes: nouveau contenant, drainage + couche de terreau, mise en place + arrosage.\nPlantation en pleine terre en 3 etapes: trou adapte, drainage + 5 a 6 cm de terreau melange a la terre, plantation + melange 50/50 terreau/terre du jardin + arrosage.\nFerticonseil: fertiliser 6 semaines apres plantation (Performance Organics) ou 1 fois/an avec Osmocote Max; arrosage pots 1-2 fois/semaine; pleine terre 1 fois/semaine; surfacage sur 2-3 cm.\nCombien de plantations avec ce sac: 6 pots diametre 25 cm (ou carres 21x21x21), 4 gros pots diametre 30 cm (ou 25x25x25), 2 grandes jardiniere 100x19x16, 1 trou pleine terre 40x40x40.\nSupport de culture NF U 44-551. Terreau avec engrais NF U 42-001. Matiere seche 35%, matiere organique 50%, pH 6,8, conductivite 65 mS/m, capacite de retention en eau 60% vol, NPK: N 240 g/m3, P2O5 120 g/m3, K2O 40 g/m3.\nMasse nette 13,2 kg. Volume 60 L."
}
}
}
],
"notes": [
"Extraction manuelle a partir des images IMG_4817.jpg et IMG_4818.jpg.",
"Le calendrier mensuel exact est visible mais partiellement peu lisible sur la photo; la contrainte 'hors gel' est certaine."
]
}

View File

@@ -3,6 +3,7 @@ import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { RouterLink, RouterView } from 'vue-router';
import AppHeader from '@/components/AppHeader.vue';
import AppDrawer from '@/components/AppDrawer.vue';
import ToastNotification from '@/components/ToastNotification.vue';
import { meteoApi } from '@/api/meteo';
import { settingsApi } from '@/api/settings';
import { applyUiSizesToRoot } from '@/utils/uiSizeDefaults';
@@ -158,44 +159,48 @@ if (__VLS_ctx.debugMode) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
(__VLS_ctx.debugDiskLabel);
}
/** @type {[typeof ToastNotification, ]} */ ;
// @ts-ignore
const __VLS_0 = __VLS_asFunctionalComponent(ToastNotification, new ToastNotification({}));
const __VLS_1 = __VLS_0({}, ...__VLS_functionalComponentArgsRest(__VLS_0));
/** @type {[typeof AppHeader, ]} */ ;
// @ts-ignore
const __VLS_0 = __VLS_asFunctionalComponent(AppHeader, new AppHeader({
const __VLS_3 = __VLS_asFunctionalComponent(AppHeader, new AppHeader({
...{ 'onToggleDrawer': {} },
...{ class: "lg:hidden" },
}));
const __VLS_1 = __VLS_0({
const __VLS_4 = __VLS_3({
...{ 'onToggleDrawer': {} },
...{ class: "lg:hidden" },
}, ...__VLS_functionalComponentArgsRest(__VLS_0));
let __VLS_3;
let __VLS_4;
let __VLS_5;
const __VLS_6 = {
}, ...__VLS_functionalComponentArgsRest(__VLS_3));
let __VLS_6;
let __VLS_7;
let __VLS_8;
const __VLS_9 = {
onToggleDrawer: (...[$event]) => {
__VLS_ctx.drawerOpen = !__VLS_ctx.drawerOpen;
}
};
var __VLS_2;
var __VLS_5;
/** @type {[typeof AppDrawer, ]} */ ;
// @ts-ignore
const __VLS_7 = __VLS_asFunctionalComponent(AppDrawer, new AppDrawer({
const __VLS_10 = __VLS_asFunctionalComponent(AppDrawer, new AppDrawer({
...{ 'onClose': {} },
open: (__VLS_ctx.drawerOpen),
}));
const __VLS_8 = __VLS_7({
const __VLS_11 = __VLS_10({
...{ 'onClose': {} },
open: (__VLS_ctx.drawerOpen),
}, ...__VLS_functionalComponentArgsRest(__VLS_7));
let __VLS_10;
let __VLS_11;
let __VLS_12;
const __VLS_13 = {
}, ...__VLS_functionalComponentArgsRest(__VLS_10));
let __VLS_13;
let __VLS_14;
let __VLS_15;
const __VLS_16 = {
onClose: (...[$event]) => {
__VLS_ctx.drawerOpen = false;
}
};
var __VLS_9;
var __VLS_12;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "lg:flex" },
});
@@ -205,40 +210,40 @@ __VLS_asFunctionalElement(__VLS_intrinsicElements.aside, __VLS_intrinsicElements
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "px-5 pt-6 pb-4 border-b border-bg-soft" },
});
const __VLS_14 = {}.RouterLink;
const __VLS_17 = {}.RouterLink;
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.RouterLink, ]} */ ;
// @ts-ignore
const __VLS_15 = __VLS_asFunctionalComponent(__VLS_14, new __VLS_14({
const __VLS_18 = __VLS_asFunctionalComponent(__VLS_17, new __VLS_17({
to: "/",
...{ class: "text-green font-bold text-xl tracking-wide flex items-center gap-2" },
}));
const __VLS_16 = __VLS_15({
const __VLS_19 = __VLS_18({
to: "/",
...{ class: "text-green font-bold text-xl tracking-wide flex items-center gap-2" },
}, ...__VLS_functionalComponentArgsRest(__VLS_15));
__VLS_17.slots.default;
}, ...__VLS_functionalComponentArgsRest(__VLS_18));
__VLS_20.slots.default;
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
var __VLS_17;
var __VLS_20;
__VLS_asFunctionalElement(__VLS_intrinsicElements.nav, __VLS_intrinsicElements.nav)({
...{ class: "flex-1 py-4 px-3 flex flex-col gap-0.5 overflow-y-auto" },
});
for (const [l] of __VLS_getVForSourceType((__VLS_ctx.links))) {
const __VLS_18 = {}.RouterLink;
const __VLS_21 = {}.RouterLink;
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.RouterLink, ]} */ ;
// @ts-ignore
const __VLS_19 = __VLS_asFunctionalComponent(__VLS_18, new __VLS_18({
const __VLS_22 = __VLS_asFunctionalComponent(__VLS_21, new __VLS_21({
key: (l.to),
to: (l.to),
...{ class: "flex items-center gap-3 text-text-muted hover:text-text py-2 px-3 rounded-lg text-sm transition-colors group" },
activeClass: "bg-bg-soft text-green font-medium",
}));
const __VLS_20 = __VLS_19({
const __VLS_23 = __VLS_22({
key: (l.to),
to: (l.to),
...{ class: "flex items-center gap-3 text-text-muted hover:text-text py-2 px-3 rounded-lg text-sm transition-colors group" },
activeClass: "bg-bg-soft text-green font-medium",
}, ...__VLS_functionalComponentArgsRest(__VLS_19));
__VLS_21.slots.default;
}, ...__VLS_functionalComponentArgsRest(__VLS_22));
__VLS_24.slots.default;
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ style: (`font-size: var(--ui-menu-icon-size, 18px); line-height: 1`) },
});
@@ -247,20 +252,42 @@ for (const [l] of __VLS_getVForSourceType((__VLS_ctx.links))) {
...{ style: (`font-size: var(--ui-menu-font-size, 13px)`) },
});
(l.label);
var __VLS_21;
var __VLS_24;
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "px-4 py-4 border-t border-bg-soft text-text-muted text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.main, __VLS_intrinsicElements.main)({
...{ class: "pt-14 lg:pt-0 lg:pl-60 min-h-screen w-full bg-bg" },
...{ style: {} },
});
const __VLS_22 = {}.RouterView;
/** @type {[typeof __VLS_components.RouterView, ]} */ ;
const __VLS_25 = {}.RouterView;
/** @type {[typeof __VLS_components.RouterView, typeof __VLS_components.routerView, typeof __VLS_components.RouterView, typeof __VLS_components.routerView, ]} */ ;
// @ts-ignore
const __VLS_23 = __VLS_asFunctionalComponent(__VLS_22, new __VLS_22({}));
const __VLS_24 = __VLS_23({}, ...__VLS_functionalComponentArgsRest(__VLS_23));
const __VLS_26 = __VLS_asFunctionalComponent(__VLS_25, new __VLS_25({}));
const __VLS_27 = __VLS_26({}, ...__VLS_functionalComponentArgsRest(__VLS_26));
{
const { default: __VLS_thisSlot } = __VLS_28.slots;
const [{ Component }] = __VLS_getSlotParams(__VLS_thisSlot);
const __VLS_29 = {}.transition;
/** @type {[typeof __VLS_components.Transition, typeof __VLS_components.transition, typeof __VLS_components.Transition, typeof __VLS_components.transition, ]} */ ;
// @ts-ignore
const __VLS_30 = __VLS_asFunctionalComponent(__VLS_29, new __VLS_29({
name: "fade",
mode: "out-in",
}));
const __VLS_31 = __VLS_30({
name: "fade",
mode: "out-in",
}, ...__VLS_functionalComponentArgsRest(__VLS_30));
__VLS_32.slots.default;
const __VLS_33 = ((Component));
// @ts-ignore
const __VLS_34 = __VLS_asFunctionalComponent(__VLS_33, new __VLS_33({}));
const __VLS_35 = __VLS_34({}, ...__VLS_functionalComponentArgsRest(__VLS_34));
var __VLS_32;
__VLS_28.slots['' /* empty slot name completion */];
}
var __VLS_28;
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['top-2']} */ ;
/** @type {__VLS_StyleScopedClasses['right-2']} */ ;
@@ -341,6 +368,7 @@ const __VLS_self = (await import('vue')).defineComponent({
RouterView: RouterView,
AppHeader: AppHeader,
AppDrawer: AppDrawer,
ToastNotification: ToastNotification,
drawerOpen: drawerOpen,
debugMode: debugMode,
debugCpuLabel: debugCpuLabel,

View File

@@ -1,4 +1,32 @@
import axios from 'axios';
export default axios.create({
import { useToast } from '@/composables/useToast';
const client = axios.create({
baseURL: import.meta.env.VITE_API_URL ?? '',
});
client.interceptors.response.use(response => response, (error) => {
const { error: showError } = useToast();
if (error.response) {
const status = error.response.status;
const detail = error.response.data?.detail ?? error.response.data?.message;
if (status === 422) {
const msg = Array.isArray(detail)
? detail.map(d => d.msg ?? d).join(', ')
: (detail ?? 'Vérifiez les champs du formulaire');
showError(`Données invalides : ${msg}`);
}
else if (status === 404) {
showError('Ressource introuvable');
}
else if (status >= 500) {
showError(`Erreur serveur (${status}) — réessayez dans un instant`);
}
else if (status !== 401 && status !== 403) {
showError(String(detail ?? `Erreur ${status}`));
}
}
else if (error.request) {
showError('Serveur inaccessible — vérifiez votre connexion réseau');
}
return Promise.reject(error);
});
export default client;

View File

@@ -11,6 +11,8 @@ export const gardensApi = {
},
delete: (id) => client.delete(`/api/gardens/${id}`),
cells: (id) => client.get(`/api/gardens/${id}/cells`).then(r => r.data),
createCell: (id, cell) => client.post(`/api/gardens/${id}/cells`, cell).then(r => r.data),
updateCell: (id, cellId, cell) => client.put(`/api/gardens/${id}/cells/${cellId}`, cell).then(r => r.data),
measurements: (id) => client.get(`/api/gardens/${id}/measurements`).then(r => r.data),
addMeasurement: (id, m) => client.post(`/api/gardens/${id}/measurements`, m).then(r => r.data),
};

View File

@@ -0,0 +1,10 @@
import client from './client';
export const identifyApi = {
identify: (file) => {
const formData = new FormData();
formData.append('file', file);
return client.post('/api/identify', formData, {
headers: { 'Content-Type': 'multipart/form-data' }
}).then(r => r.data);
}
};

View File

@@ -22,6 +22,14 @@ export interface Plant {
astuces_culture?: string
url_reference?: string
notes?: string
associations_favorables?: string[]
associations_defavorables?: string[]
boutique_nom?: string
boutique_url?: string
prix_achat?: number
date_achat?: string
poids?: string
dluo?: string
}
export const plantsApi = {

View File

@@ -0,0 +1,224 @@
/// <reference types="../../node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts" />
const __VLS_props = defineProps();
const __VLS_emit = defineEmits(['close']);
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
// CSS variable injection
// CSS variable injection end
if (__VLS_ctx.open) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.open))
return;
__VLS_ctx.$emit('close');
} },
...{ class: "fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/80 backdrop-blur-sm" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "card-jardin w-full max-w-md overflow-hidden animate-fade-in border-green/30" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-4 border-b border-bg-hard pb-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h3, __VLS_intrinsicElements.h3)({
...{ class: "text-green font-bold flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.open))
return;
__VLS_ctx.$emit('close');
} },
...{ class: "text-text-muted hover:text-red transition-colors" },
});
if (__VLS_ctx.loading) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "py-12 flex flex-col items-center gap-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "w-12 h-12 border-4 border-green/20 border-t-green rounded-full animate-spin" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm animate-pulse italic" },
});
}
else if (__VLS_ctx.result) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "space-y-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-4 bg-bg-hard p-3 rounded-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-3xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text font-bold text-lg" },
});
(__VLS_ctx.result.common_name);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] text-text-muted uppercase tracking-widest font-bold" },
});
((__VLS_ctx.result.confidence * 100).toFixed(1));
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "space-y-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] font-bold text-green uppercase tracking-widest" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-sm text-text-muted leading-relaxed bg-green/5 p-3 rounded-lg border border-green/10" },
});
(__VLS_ctx.result.conseil);
if (__VLS_ctx.result.actions?.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "space-y-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] font-bold text-orange uppercase tracking-widest" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex flex-wrap gap-2" },
});
for (const [action] of __VLS_getVForSourceType((__VLS_ctx.result.actions))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
key: (action),
...{ class: "badge badge-orange py-1.5 px-3" },
});
(action);
}
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.open))
return;
if (!!(__VLS_ctx.loading))
return;
if (!(__VLS_ctx.result))
return;
__VLS_ctx.$emit('close');
} },
...{ class: "btn-primary w-full mt-4" },
});
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "py-8 text-center text-text-muted" },
});
}
}
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['inset-0']} */ ;
/** @type {__VLS_StyleScopedClasses['z-[100]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/80']} */ ;
/** @type {__VLS_StyleScopedClasses['backdrop-blur-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-md']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-fade-in']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/30']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['py-12']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['w-12']} */ ;
/** @type {__VLS_StyleScopedClasses['h-12']} */ ;
/** @type {__VLS_StyleScopedClasses['border-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/20']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t-green']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-spin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['italic']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-6']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-relaxed']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green/5']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/10']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['badge']} */ ;
/** @type {__VLS_StyleScopedClasses['badge-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-8']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {
return {};
},
emits: {},
__typeProps: {},
});
export default (await import('vue')).defineComponent({
setup() {
return {};
},
emits: {},
__typeProps: {},
});
; /* PartiallyEnd: #4569/main.vue */

View File

@@ -0,0 +1,127 @@
/// <reference types="../../node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts" />
import { useToast } from '@/composables/useToast';
const { toasts, remove } = useToast();
function toastClass(type) {
const map = {
success: 'bg-[#3c3836] border-[#b8bb26]/50 text-[#b8bb26]',
error: 'bg-[#3c3836] border-[#fb4934]/50 text-[#fb4934]',
warning: 'bg-[#3c3836] border-[#fabd2f]/50 text-[#fabd2f]',
info: 'bg-[#3c3836] border-[#83a598]/50 text-[#83a598]',
};
return map[type] ?? 'bg-[#3c3836] border-[#a89984]/40 text-[#ebdbb2]';
}
function toastIcon(type) {
const map = {
success: '✓',
error: '✕',
warning: '⚠',
info: '',
};
return map[type] ?? '';
}
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
// CSS variable injection
// CSS variable injection end
const __VLS_0 = {}.Teleport;
/** @type {[typeof __VLS_components.Teleport, typeof __VLS_components.Teleport, ]} */ ;
// @ts-ignore
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
to: "body",
}));
const __VLS_2 = __VLS_1({
to: "body",
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
__VLS_3.slots.default;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "fixed bottom-4 right-4 z-[200] flex flex-col gap-2 max-w-sm w-full pointer-events-none" },
});
const __VLS_4 = {}.TransitionGroup;
/** @type {[typeof __VLS_components.TransitionGroup, typeof __VLS_components.TransitionGroup, ]} */ ;
// @ts-ignore
const __VLS_5 = __VLS_asFunctionalComponent(__VLS_4, new __VLS_4({
name: "toast",
}));
const __VLS_6 = __VLS_5({
name: "toast",
}, ...__VLS_functionalComponentArgsRest(__VLS_5));
__VLS_7.slots.default;
for (const [toast] of __VLS_getVForSourceType((__VLS_ctx.toasts))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (...[$event]) => {
__VLS_ctx.remove(toast.id);
} },
key: (toast.id),
...{ class: "pointer-events-auto flex items-start gap-3 rounded-xl px-4 py-3 shadow-2xl border text-sm font-medium cursor-pointer" },
...{ class: (__VLS_ctx.toastClass(toast.type)) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-base leading-none mt-0.5 shrink-0" },
});
(__VLS_ctx.toastIcon(toast.type));
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "flex-1 leading-snug" },
});
(toast.message);
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.remove(toast.id);
} },
...{ class: "ml-1 opacity-50 hover:opacity-100 transition-opacity shrink-0 text-xs" },
});
}
var __VLS_7;
var __VLS_3;
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['bottom-4']} */ ;
/** @type {__VLS_StyleScopedClasses['right-4']} */ ;
/** @type {__VLS_StyleScopedClasses['z-[200]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['pointer-events-none']} */ ;
/** @type {__VLS_StyleScopedClasses['pointer-events-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['text-base']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-none']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-snug']} */ ;
/** @type {__VLS_StyleScopedClasses['ml-1']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-50']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-100']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-opacity']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {
return {
toasts: toasts,
remove: remove,
toastClass: toastClass,
toastIcon: toastIcon,
};
},
});
export default (await import('vue')).defineComponent({
setup() {
return {};
},
});
; /* PartiallyEnd: #4569/main.vue */

View File

@@ -0,0 +1,26 @@
import { reactive } from 'vue';
const toasts = reactive([]);
let nextId = 1;
function add(message, type = 'info', duration = 4000) {
const id = nextId++;
toasts.push({ id, type, message, duration });
if (duration > 0) {
setTimeout(() => remove(id), duration);
}
return id;
}
function remove(id) {
const index = toasts.findIndex(t => t.id === id);
if (index !== -1)
toasts.splice(index, 1);
}
export function useToast() {
return {
toasts,
success: (msg, duration) => add(msg, 'success', duration ?? 4000),
error: (msg, duration) => add(msg, 'error', duration ?? 6000),
warning: (msg, duration) => add(msg, 'warning', duration ?? 5000),
info: (msg, duration) => add(msg, 'info', duration ?? 4000),
remove,
};
}

View File

@@ -3,4 +3,6 @@ import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import './style.css';
import { registerSW } from 'virtual:pwa-register';
registerSW({ immediate: true });
createApp(App).use(createPinia()).use(router).mount('#app');

View File

@@ -3,6 +3,8 @@ export const UI_SIZE_DEFAULTS = {
ui_menu_font_size: 13,
ui_menu_icon_size: 18,
ui_thumb_size: 96,
ui_weather_icon_size: 48,
ui_dashboard_icon_size: 24,
};
export function applyUiSizesToRoot(data) {
const root = document.documentElement;

File diff suppressed because it is too large Load Diff

View File

@@ -119,22 +119,27 @@ const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4 max-w-4xl mx-auto" },
...{ class: "p-4 max-w-6xl mx-auto space-y-8" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-6" },
...{ class: "flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-green" },
...{ class: "text-3xl font-bold text-green tracking-tight" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.showIdentify = true;
} },
...{ class: "bg-green text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
...{ class: "btn-primary flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 mb-4 flex-wrap" },
...{ class: "flex gap-2 mb-4 bg-bg-soft/30 p-1 rounded-full w-fit border border-bg-soft overflow-x-auto max-w-full no-scrollbar" },
});
for (const [f] of __VLS_getVForSourceType((__VLS_ctx.filters))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
@@ -142,24 +147,36 @@ for (const [f] of __VLS_getVForSourceType((__VLS_ctx.filters))) {
__VLS_ctx.activeFilter = f.val;
} },
key: (f.val),
...{ class: (['px-3 py-1 rounded-full text-xs font-medium transition-colors',
__VLS_ctx.activeFilter === f.val ? 'bg-green text-bg' : 'bg-bg-soft text-text-muted hover:text-text']) },
...{ class: (['px-4 py-1.5 rounded-full text-[10px] font-black uppercase tracking-widest transition-all whitespace-nowrap',
__VLS_ctx.activeFilter === f.val ? 'bg-green text-bg shadow-lg' : 'text-text-muted hover:text-text']) },
});
(f.label);
}
if (__VLS_ctx.loading) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm" },
...{ class: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4" },
});
for (const [i] of __VLS_getVForSourceType((5))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (i),
...{ class: "aspect-square card-jardin animate-pulse opacity-20" },
});
}
}
else if (!__VLS_ctx.filtered.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm py-4" },
...{ class: "card-jardin text-center py-16 opacity-50 border-dashed" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-4xl mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm uppercase font-black tracking-widest" },
});
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-3 md:grid-cols-4 gap-2" },
...{ class: "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4" },
});
for (const [m] of __VLS_getVForSourceType((__VLS_ctx.filtered))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
@@ -171,21 +188,27 @@ else {
__VLS_ctx.openLightbox(m);
} },
key: (m.id),
...{ class: "aspect-square rounded-lg overflow-hidden bg-bg-hard relative group cursor-pointer" },
...{ class: "group relative aspect-square rounded-2xl overflow-hidden bg-bg-hard border border-bg-soft/50 cursor-pointer shadow-sm hover:shadow-2xl hover:scale-[1.02] transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (m.thumbnail_url || m.url),
alt: (m.titre || ''),
...{ class: "w-full h-full object-cover" },
...{ class: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-110" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute bottom-2 left-2 right-2 pointer-events-none" },
});
if (m.identified_common) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute bottom-0 left-0 right-0 bg-black/70 text-xs text-green px-1 py-0.5 truncate" },
...{ class: "text-[10px] text-green font-black uppercase tracking-tighter truncate drop-shadow-md" },
});
(m.identified_common);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute top-1 left-1 bg-black/60 text-text-muted text-xs px-1 rounded" },
...{ class: "text-[8px] text-text-muted font-bold uppercase tracking-widest opacity-80" },
});
(__VLS_ctx.labelFor(m.entity_type));
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
@@ -196,7 +219,10 @@ else {
return;
__VLS_ctx.deleteMedia(m);
} },
...{ class: "hidden group-hover:flex absolute top-1 right-1 bg-red/80 text-white text-xs rounded px-1" },
...{ class: "absolute top-2 right-2 bg-red/80 hover:bg-red text-white p-1.5 rounded-lg opacity-0 group-hover:opacity-100 transition-all scale-75 group-hover:scale-100" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs" },
});
}
}
@@ -207,24 +233,35 @@ if (__VLS_ctx.lightbox) {
return;
__VLS_ctx.lightbox = null;
} },
...{ class: "fixed inset-0 bg-black/80 z-50 flex items-center justify-center p-4" },
...{ class: "fixed inset-0 bg-black/95 backdrop-blur-md z-[150] flex items-center justify-center p-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "max-w-lg w-full bg-bg-hard rounded-xl overflow-hidden border border-bg-soft" },
...{ class: "max-w-2xl w-full bg-bg-hard rounded-3xl overflow-hidden border border-bg-soft shadow-2xl animate-fade-in" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "relative aspect-video sm:aspect-square bg-bg overflow-hidden" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.lightbox.url),
...{ class: "w-full" },
...{ class: "w-full h-full object-contain" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.lightbox))
return;
__VLS_ctx.lightbox = null;
} },
...{ class: "absolute top-4 right-4 bg-black/50 text-white w-10 h-10 rounded-full flex items-center justify-center hover:bg-red transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4" },
...{ class: "p-6 space-y-6" },
});
if (__VLS_ctx.lightbox.identified_species) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-center mb-3" },
...{ class: "text-center space-y-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-green font-semibold text-base" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-green font-black text-2xl uppercase tracking-tighter" },
});
(__VLS_ctx.lightbox.identified_common);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
@@ -232,24 +269,27 @@ if (__VLS_ctx.lightbox) {
});
(__VLS_ctx.lightbox.identified_species);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-xs text-text-muted mt-1" },
...{ class: "badge badge-green !text-[9px] mt-2" },
});
(Math.round((__VLS_ctx.lightbox.identified_confidence || 0) * 100));
(__VLS_ctx.lightbox.identified_source);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-xs text-text-muted mb-3 text-center" },
...{ class: "flex items-center justify-center gap-2 text-xs text-text-muted font-bold uppercase tracking-widest border-y border-bg-soft py-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text" },
});
(__VLS_ctx.labelFor(__VLS_ctx.lightbox.entity_type));
if (__VLS_ctx.lightbox.entity_type === 'plante' && __VLS_ctx.plantName(__VLS_ctx.lightbox.entity_id)) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-green font-medium" },
...{ class: "text-green" },
});
(__VLS_ctx.plantName(__VLS_ctx.lightbox.entity_id));
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 flex-wrap" },
...{ class: "flex gap-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
@@ -257,7 +297,7 @@ if (__VLS_ctx.lightbox) {
return;
__VLS_ctx.startLink(__VLS_ctx.lightbox);
} },
...{ class: "flex-1 bg-blue/20 text-blue hover:bg-blue/30 px-3 py-2 rounded-lg text-xs font-medium transition-colors" },
...{ class: "btn-outline flex-1 py-3 border-blue/20 text-blue hover:bg-blue/10 text-[10px] font-black uppercase tracking-widest" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
@@ -265,12 +305,10 @@ if (__VLS_ctx.lightbox) {
return;
__VLS_ctx.toggleAdventice(__VLS_ctx.lightbox);
} },
...{ class: ([
'px-3 py-2 rounded-lg text-xs font-medium transition-colors',
__VLS_ctx.isAdventice(__VLS_ctx.lightbox) ? 'bg-red/20 text-red hover:bg-red/30' : 'bg-green/20 text-green hover:bg-green/30'
]) },
...{ class: (['btn-outline flex-1 py-3 text-[10px] font-black uppercase tracking-widest',
__VLS_ctx.isAdventice(__VLS_ctx.lightbox) ? 'border-red/20 text-red hover:bg-red/10' : 'border-green/20 text-green hover:bg-green/10']) },
});
(__VLS_ctx.isAdventice(__VLS_ctx.lightbox) ? '🪓 Retirer adventice' : '🌾 Marquer adventice');
(__VLS_ctx.isAdventice(__VLS_ctx.lightbox) ? '🪓 Pas Adventice' : '🌾 Adventice');
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.lightbox))
@@ -278,15 +316,7 @@ if (__VLS_ctx.lightbox) {
__VLS_ctx.deleteMedia(__VLS_ctx.lightbox);
__VLS_ctx.lightbox = null;
} },
...{ class: "bg-red/20 text-red hover:bg-red/30 px-3 py-2 rounded-lg text-xs font-medium transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.lightbox))
return;
__VLS_ctx.lightbox = null;
} },
...{ class: "mt-3 w-full text-text-muted hover:text-text text-sm" },
...{ class: "btn-outline py-3 px-4 border-red/20 text-red hover:bg-red/10" },
});
}
if (__VLS_ctx.linkMedia) {
@@ -296,17 +326,17 @@ if (__VLS_ctx.linkMedia) {
return;
__VLS_ctx.linkMedia = null;
} },
...{ class: "fixed inset-0 bg-black/70 z-50 flex items-center justify-center p-4" },
...{ class: "fixed inset-0 bg-black/80 backdrop-blur-sm z-[200] flex items-center justify-center p-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "bg-bg-hard rounded-xl p-6 w-full max-w-sm border border-bg-soft" },
...{ class: "bg-bg-hard rounded-2xl p-6 w-full max-w-sm border border-bg-soft shadow-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h3, __VLS_intrinsicElements.h3)({
...{ class: "text-text font-bold mb-4" },
...{ class: "text-text font-black uppercase tracking-tighter text-lg mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.select, __VLS_intrinsicElements.select)({
value: (__VLS_ctx.linkPlantId),
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-green mb-4" },
...{ class: "w-full bg-bg border border-bg-soft rounded-xl px-4 py-3 text-text text-sm outline-none focus:border-green mb-6 appearance-none shadow-inner" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.option, __VLS_intrinsicElements.option)({
value: (null),
@@ -319,7 +349,7 @@ if (__VLS_ctx.linkMedia) {
(__VLS_ctx.formatPlantLabel(p));
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 justify-end" },
...{ class: "flex gap-3 justify-end" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
@@ -327,12 +357,12 @@ if (__VLS_ctx.linkMedia) {
return;
__VLS_ctx.linkMedia = null;
} },
...{ class: "px-4 py-2 text-text-muted hover:text-text text-sm" },
...{ class: "btn-outline border-transparent text-text-muted hover:text-red uppercase text-xs font-bold px-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.confirmLink) },
disabled: (!__VLS_ctx.linkPlantId),
...{ class: "bg-green text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90 disabled:opacity-40" },
...{ class: "btn-primary px-6 disabled:opacity-30" },
});
}
if (__VLS_ctx.showIdentify) {
@@ -362,182 +392,261 @@ if (__VLS_ctx.showIdentify) {
var __VLS_2;
}
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-4xl']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-6xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mx-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-8']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['py-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['p-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['w-fit']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-x-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['no-scrollbar']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-5']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['aspect-square']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-20']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-16']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-50']} */ ;
/** @type {__VLS_StyleScopedClasses['border-dashed']} */ ;
/** @type {__VLS_StyleScopedClasses['text-4xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-5']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['aspect-square']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft/50']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:scale-[1.02]']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-transform']} */ ;
/** @type {__VLS_StyleScopedClasses['duration-500']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:scale-110']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['bottom-0']} */ ;
/** @type {__VLS_StyleScopedClasses['left-0']} */ ;
/** @type {__VLS_StyleScopedClasses['right-0']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/70']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['inset-0']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-gradient-to-t']} */ ;
/** @type {__VLS_StyleScopedClasses['from-black/80']} */ ;
/** @type {__VLS_StyleScopedClasses['via-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['to-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-0']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:opacity-100']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-opacity']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['bottom-2']} */ ;
/** @type {__VLS_StyleScopedClasses['left-2']} */ ;
/** @type {__VLS_StyleScopedClasses['right-2']} */ ;
/** @type {__VLS_StyleScopedClasses['pointer-events-none']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['px-1']} */ ;
/** @type {__VLS_StyleScopedClasses['py-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['top-1']} */ ;
/** @type {__VLS_StyleScopedClasses['left-1']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/60']} */ ;
/** @type {__VLS_StyleScopedClasses['drop-shadow-md']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[8px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['px-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:flex']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-80']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['top-1']} */ ;
/** @type {__VLS_StyleScopedClasses['right-1']} */ ;
/** @type {__VLS_StyleScopedClasses['top-2']} */ ;
/** @type {__VLS_StyleScopedClasses['right-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-red/80']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-red']} */ ;
/** @type {__VLS_StyleScopedClasses['text-white']} */ ;
/** @type {__VLS_StyleScopedClasses['p-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-0']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:opacity-100']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['scale-75']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:scale-100']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-1']} */ ;
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['inset-0']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/80']} */ ;
/** @type {__VLS_StyleScopedClasses['z-50']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/95']} */ ;
/** @type {__VLS_StyleScopedClasses['backdrop-blur-md']} */ ;
/** @type {__VLS_StyleScopedClasses['z-[150]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-fade-in']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['aspect-video']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:aspect-square']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['object-contain']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['top-4']} */ ;
/** @type {__VLS_StyleScopedClasses['right-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/50']} */ ;
/** @type {__VLS_StyleScopedClasses['text-white']} */ ;
/** @type {__VLS_StyleScopedClasses['w-10']} */ ;
/** @type {__VLS_StyleScopedClasses['h-10']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-red']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['p-6']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-base']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['italic']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['badge']} */ ;
/** @type {__VLS_StyleScopedClasses['badge-green']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-blue/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-blue/30']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-red/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-red/30']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-3']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['border-y']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['border-blue/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-blue/10']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-red/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-red/10']} */ ;
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['inset-0']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/70']} */ ;
/** @type {__VLS_StyleScopedClasses['z-50']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/80']} */ ;
/** @type {__VLS_StyleScopedClasses['backdrop-blur-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['z-[200]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-6']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['appearance-none']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-inner']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-end']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['border-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['disabled:opacity-40']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['px-6']} */ ;
/** @type {__VLS_StyleScopedClasses['disabled:opacity-30']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,14 @@
/// <reference types="../../node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts" />
import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useRouter, RouterLink } from 'vue-router';
import { useGardensStore } from '@/stores/gardens';
import { useTasksStore } from '@/stores/tasks';
import { meteoApi } from '@/api/meteo';
import { useToast } from '@/composables/useToast';
const router = useRouter();
const gardensStore = useGardensStore();
const tasksStore = useTasksStore();
const toast = useToast();
const pendingTasks = computed(() => tasksStore.tasks.filter(t => t.statut === 'a_faire').slice(0, 5));
const meteo7j = ref([]);
const stationCurrent = ref(null);
@@ -14,7 +16,8 @@ const meteoCurrent = computed(() => meteo7j.value[0] || null);
function formatDate(s) {
if (!s)
return '—';
return new Date(s + 'T12:00:00').toLocaleDateString('fr-FR', { day: 'numeric', month: 'short' });
const date = new Date(s + 'T12:00:00');
return date.toLocaleDateString('fr-FR', { weekday: 'short', day: 'numeric' });
}
function weatherIcon(code) {
const available = [0, 1, 2, 3, 45, 48, 51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 71, 73, 75, 77, 80, 81, 82, 85, 86, 95, 96, 99];
@@ -22,8 +25,20 @@ function weatherIcon(code) {
return `/icons/weather/${closest}.svg`;
}
onMounted(async () => {
gardensStore.fetchAll();
tasksStore.fetchAll();
// Chargement des données principales (silencieux si erreur)
try {
await gardensStore.fetchAll();
}
catch {
toast.warning('Jardins non disponibles');
}
try {
await tasksStore.fetchAll();
}
catch {
toast.warning('Tâches non disponibles');
}
// Météo : fallback silencieux, pas de toast intrusif
try {
stationCurrent.value = await meteoApi.getStationCurrent();
}
@@ -43,273 +58,517 @@ const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4 max-w-6xl mx-auto" },
...{ class: "p-4 max-w-6xl mx-auto space-y-8" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-green mb-6" },
...{ class: "text-3xl font-bold text-green tracking-tight" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs font-medium bg-bg-hard px-3 py-1 rounded-full border border-bg-soft" },
});
(new Date().toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' }));
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-1 lg:grid-cols-3 gap-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "mb-6" },
...{ class: "lg:col-span-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-3" },
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-yellow" },
});
const __VLS_0 = {}.RouterLink;
/** @type {[typeof __VLS_components.RouterLink, typeof __VLS_components.RouterLink, ]} */ ;
// @ts-ignore
const __VLS_1 = __VLS_asFunctionalComponent(__VLS_0, new __VLS_0({
to: "/taches",
...{ class: "text-xs text-yellow hover:underline font-bold uppercase tracking-wide" },
}));
const __VLS_2 = __VLS_1({
to: "/taches",
...{ class: "text-xs text-yellow hover:underline font-bold uppercase tracking-wide" },
}, ...__VLS_functionalComponentArgsRest(__VLS_1));
__VLS_3.slots.default;
var __VLS_3;
if (!__VLS_ctx.pendingTasks.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm py-2" },
...{ class: "card-jardin text-center py-10 opacity-50" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "space-y-3" },
});
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.pendingTasks))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (t.id),
...{ class: "bg-bg-soft rounded-lg p-3 mb-2 flex items-center gap-3 border border-bg-hard" },
...{ class: "card-jardin flex items-center gap-4 group" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: ({
'text-red': t.priorite === 'haute',
'text-yellow': t.priorite === 'normale',
'text-text-muted': t.priorite === 'basse'
}) },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: ([
'w-2 h-10 rounded-full shrink-0',
t.priorite === 'haute' ? 'bg-red' : t.priorite === 'normale' ? 'bg-yellow' : 'bg-bg-hard'
]) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text text-sm flex-1" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1 min-w-0" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text font-semibold text-sm truncate" },
});
(t.titre);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-[10px] uppercase font-bold tracking-tight" },
});
(t.priorite);
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.tasksStore.updateStatut(t.id, 'fait');
} },
...{ class: "text-xs text-green hover:underline px-2" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "mb-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-3" },
});
if (__VLS_ctx.stationCurrent || __VLS_ctx.meteo7j.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "bg-bg-soft rounded-xl p-3 border border-bg-hard mb-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3" },
});
if (__VLS_ctx.meteoCurrent?.wmo != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.weatherIcon(__VLS_ctx.meteoCurrent.wmo)),
...{ class: "w-8 h-8" },
alt: (__VLS_ctx.meteoCurrent.label || 'Météo'),
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-sm text-text" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
(__VLS_ctx.meteoCurrent?.label || '—');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs" },
});
(__VLS_ctx.stationCurrent?.temp_ext != null ? `${__VLS_ctx.stationCurrent.temp_ext.toFixed(1)}°C` : 'Temp. indisponible');
if (__VLS_ctx.stationCurrent?.date_heure) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
(__VLS_ctx.stationCurrent.date_heure.slice(11, 16));
}
}
if (__VLS_ctx.meteo7j.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-7 gap-2" },
});
for (const [day] of __VLS_getVForSourceType((__VLS_ctx.meteo7j))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (day.date),
...{ class: "bg-bg-soft rounded-xl p-3 border border-bg-hard flex flex-col items-center gap-1 min-w-0" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs" },
});
(__VLS_ctx.formatDate(day.date || ''));
if (day.wmo != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.weatherIcon(day.wmo)),
...{ class: "w-8 h-8" },
alt: (day.label || 'Météo'),
});
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-2xl" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[11px] text-center text-text-muted leading-tight min-h-[30px]" },
});
(day.label || '—');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-1 text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-orange" },
});
(day.t_max != null ? day.t_max.toFixed(0) : '—');
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-blue" },
});
(day.t_min != null ? day.t_min.toFixed(0) : '—');
}
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm py-2" },
...{ class: "btn-outline py-1 px-3 border-green/30 text-green hover:bg-green/10" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-3" },
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest mb-4 flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-blue" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "card-jardin border-blue/20 bg-gradient-to-br from-bg-soft to-bg-hard relative overflow-hidden" },
});
if (__VLS_ctx.meteoCurrent) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "relative z-10 flex flex-col items-center py-4" },
});
if (__VLS_ctx.meteoCurrent?.wmo != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.weatherIcon(__VLS_ctx.meteoCurrent.wmo)),
...{ class: "drop-shadow-2xl mb-2" },
...{ style: ({ width: 'calc(var(--ui-weather-icon-size, 48px) * 2)', height: 'calc(var(--ui-weather-icon-size, 48px) * 2)' }) },
alt: (__VLS_ctx.meteoCurrent.label || 'Météo'),
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-3xl font-bold text-text mb-1" },
});
(__VLS_ctx.stationCurrent?.temp_ext != null ? `${__VLS_ctx.stationCurrent.temp_ext.toFixed(1)}°C` : '—°');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-sm font-bold text-blue uppercase tracking-widest mb-4" },
});
(__VLS_ctx.meteoCurrent?.label || '—');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-2 gap-4 w-full pt-4 border-t border-bg-hard/50" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-center" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] text-text-muted uppercase font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-sm text-blue" },
});
(__VLS_ctx.stationCurrent?.humidite ?? '--');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-center" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] text-text-muted uppercase font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-sm text-text" },
});
(__VLS_ctx.stationCurrent?.vent_kmh ?? '--');
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px]" },
});
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-center py-10 opacity-50 text-sm" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest mb-4 flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-aqua" },
});
if (__VLS_ctx.meteo7j.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-7 gap-3" },
});
for (const [day, index] of __VLS_getVForSourceType((__VLS_ctx.meteo7j))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (day.date),
...{ class: (['card-jardin flex flex-col items-center gap-2 text-center transition-all group hover:-translate-y-1',
index === 0 ? 'border-yellow/30 bg-yellow/5' : '']) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] font-bold uppercase tracking-tighter" },
...{ class: (index === 0 ? 'text-yellow' : 'text-text-muted') },
});
(index === 0 ? 'Aujourd\'hui' : __VLS_ctx.formatDate(day.date || ''));
if (day.wmo != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.weatherIcon(day.wmo)),
...{ class: "group-hover:scale-110 transition-transform" },
...{ style: ({ width: 'var(--ui-weather-icon-size, 48px)', height: 'var(--ui-weather-icon-size, 48px)' }) },
alt: (day.label || 'Météo'),
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] text-text-muted font-medium line-clamp-1 h-3" },
});
(day.label || '—');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 text-xs font-bold pt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-orange" },
});
(day.t_max?.toFixed(1));
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-blue" },
});
(day.t_min?.toFixed(1));
}
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-orange" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.router.push('/jardins');
} },
...{ class: "btn-primary py-1 px-4 text-xs" },
});
if (__VLS_ctx.gardensStore.loading) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm" },
...{ class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" },
});
for (const [i] of __VLS_getVForSourceType((3))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (i),
...{ class: "card-jardin h-24 animate-pulse opacity-20" },
});
}
}
for (const [g] of __VLS_getVForSourceType((__VLS_ctx.gardensStore.gardens))) {
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (...[$event]) => {
__VLS_ctx.router.push(`/jardins/${g.id}`);
} },
key: (g.id),
...{ class: "bg-bg-soft rounded-lg p-4 mb-2 border border-bg-hard cursor-pointer hover:border-green transition-colors" },
...{ class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text font-medium" },
});
(g.nom);
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "ml-2 text-xs text-text-muted px-2 py-0.5 bg-bg rounded" },
});
(g.type);
for (const [g] of __VLS_getVForSourceType((__VLS_ctx.gardensStore.gardens))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (...[$event]) => {
if (!!(__VLS_ctx.gardensStore.loading))
return;
__VLS_ctx.router.push(`/jardins/${g.id}`);
} },
key: (g.id),
...{ class: "card-jardin flex flex-col justify-between group cursor-pointer hover:border-green/50" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-start justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
...{ style: ({ fontSize: 'var(--ui-dashboard-icon-size, 24px)' }) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h3, __VLS_intrinsicElements.h3)({
...{ class: "text-text font-bold text-lg group-hover:text-green transition-colors" },
});
(g.nom);
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "badge badge-yellow" },
});
(g.type?.replace('_', ' '));
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-4 flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] text-text-muted uppercase font-bold tracking-widest" },
});
(g.exposition);
(g.surface_m2);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-green text-xl opacity-0 group-hover:opacity-100 transition-all" },
});
}
}
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-6xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mx-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-8']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['w-8']} */ ;
/** @type {__VLS_StyleScopedClasses['h-8']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-6']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-wide']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-10']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-50']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-3']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['min-w-0']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/30']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-green/10']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['border-blue/20']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-gradient-to-br']} */ ;
/** @type {__VLS_StyleScopedClasses['from-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['to-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['z-10']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['min-w-0']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['w-8']} */ ;
/** @type {__VLS_StyleScopedClasses['h-8']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[11px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['min-h-[30px]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['py-4']} */ ;
/** @type {__VLS_StyleScopedClasses['drop-shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard/50']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-green']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['ml-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-10']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-50']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:scale-110']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-transform']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['line-clamp-1']} */ ;
/** @type {__VLS_StyleScopedClasses['h-3']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['h-24']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-20']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-green/50']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['badge']} */ ;
/** @type {__VLS_StyleScopedClasses['badge-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-0']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:opacity-100']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {
return {
RouterLink: RouterLink,
router: router,
gardensStore: gardensStore,
tasksStore: tasksStore,

View File

@@ -2,10 +2,16 @@
import { computed, onMounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { gardensApi } from '@/api/gardens';
import { plantingsApi } from '@/api/plantings';
import { plantsApi } from '@/api/plants';
const route = useRoute();
const router = useRouter();
const garden = ref(null);
const cells = ref([]);
const plantings = ref([]);
const plants = ref([]);
const editMode = ref(false);
const saving = ref(false);
const displayCells = computed(() => {
if (!garden.value)
return [];
@@ -22,10 +28,88 @@ const displayCells = computed(() => {
}
return result;
});
// Plantations actives (ni terminées ni échouées) pour ce jardin
const activePlantings = computed(() => plantings.value.filter(p => p.garden_id === garden.value?.id &&
p.statut !== 'termine' &&
p.statut !== 'echoue'));
// Map cellId → Planting active
const activePlantingsByCellId = computed(() => {
const map = new Map();
for (const p of activePlantings.value) {
if (p.cell_ids?.length) {
p.cell_ids.forEach(cid => map.set(cid, p));
}
else if (p.cell_id) {
map.set(p.cell_id, p);
}
}
return map;
});
function getCellPlanting(cell) {
if (cell.id == null)
return undefined;
return activePlantingsByCellId.value.get(cell.id);
}
function plantName(p) {
const plant = plants.value.find(pl => pl.id === p.variety_id);
return plant?.nom_commun ?? `Plante #${p.variety_id}`;
}
function plantShortName(p) {
return plantName(p).slice(0, 8);
}
function plantCellLabel(p) {
const ids = p.cell_ids?.length ? p.cell_ids : (p.cell_id ? [p.cell_id] : []);
if (!ids.length)
return '—';
return ids
.map(cid => cells.value.find(c => c.id === cid)?.libelle ?? `#${cid}`)
.join(', ');
}
function getCellTitle(cell) {
const planting = getCellPlanting(cell);
if (planting)
return `Planté : ${plantName(planting)} (${planting.statut})`;
if (cell.etat === 'non_cultivable')
return 'Non cultivable — cliquer pour rendre cultivable';
if (editMode.value)
return 'Marquer comme non cultivable';
return cell.libelle ?? '';
}
async function toggleNonCultivable(cell) {
if (!garden.value?.id || saving.value)
return;
const newEtat = cell.etat === 'non_cultivable' ? 'libre' : 'non_cultivable';
saving.value = true;
try {
if (cell.id) {
const updated = await gardensApi.updateCell(garden.value.id, cell.id, { ...cell, etat: newEtat });
const idx = cells.value.findIndex(c => c.id === cell.id);
if (idx !== -1)
cells.value[idx] = updated;
}
else {
const created = await gardensApi.createCell(garden.value.id, {
col: cell.col, row: cell.row,
libelle: cell.libelle,
etat: newEtat,
garden_id: garden.value.id,
});
cells.value.push(created);
}
}
catch { /* L'intercepteur affiche l'erreur */ }
finally {
saving.value = false;
}
}
onMounted(async () => {
const id = Number(route.params.id);
garden.value = await gardensApi.get(id);
cells.value = await gardensApi.cells(id);
[garden.value, cells.value, plantings.value, plants.value] = await Promise.all([
gardensApi.get(id),
gardensApi.cells(id),
plantingsApi.list(),
plantsApi.list(),
]);
});
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
const __VLS_ctx = {};
@@ -42,8 +126,11 @@ __VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElement
});
if (__VLS_ctx.garden) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-start justify-between mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-green mb-1" },
...{ class: "text-2xl font-bold text-green" },
});
(__VLS_ctx.garden.nom);
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
@@ -119,26 +206,129 @@ if (__VLS_ctx.garden) {
...{ class: "w-full max-h-72 object-cover rounded-lg border border-bg-hard bg-bg-soft" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-3" },
...{ class: "text-text-muted text-xs uppercase tracking-widest" },
});
(__VLS_ctx.garden.grille_largeur);
(__VLS_ctx.garden.grille_hauteur);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-2" },
});
if (__VLS_ctx.editMode) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs text-orange" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.garden))
return;
__VLS_ctx.editMode = !__VLS_ctx.editMode;
} },
...{ class: (['px-3 py-1 rounded-full text-xs font-bold border transition-all',
__VLS_ctx.editMode ? 'bg-orange text-bg border-orange' : 'border-bg-soft text-text-muted hover:border-orange hover:text-orange']) },
});
(__VLS_ctx.editMode ? '✓ Terminer' : '✏️ Éditer zones');
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex flex-wrap gap-4 mb-3 text-[10px] text-text-muted font-bold uppercase tracking-wider" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "flex items-center gap-1.5" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-3 h-3 rounded bg-bg border border-bg-soft inline-block" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "flex items-center gap-1.5" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-3 h-3 rounded bg-green/20 border border-green/60 inline-block" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "flex items-center gap-1.5" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-3 h-3 rounded bg-red/20 border border-red/40 inline-block" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "overflow-x-auto pb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid gap-1 w-max" },
...{ style: (`grid-template-columns: repeat(${__VLS_ctx.garden.grille_largeur}, 52px)`) },
...{ style: (`grid-template-columns: repeat(${__VLS_ctx.garden.grille_largeur}, 56px)`) },
});
for (const [cell] of __VLS_getVForSourceType((__VLS_ctx.displayCells))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (...[$event]) => {
if (!(__VLS_ctx.garden))
return;
__VLS_ctx.editMode && !__VLS_ctx.getCellPlanting(cell) && cell.etat !== 'occupe' ? __VLS_ctx.toggleNonCultivable(cell) : undefined;
} },
key: (`${cell.row}-${cell.col}`),
...{ class: "w-[52px] h-[52px] bg-bg-soft border border-bg-hard rounded-md flex items-center justify-center text-xs text-text-muted cursor-pointer hover:border-green transition-colors select-none" },
...{ class: ({ 'border-orange/60 bg-orange/10 text-orange': cell.etat === 'occupe' }) },
title: (cell.libelle),
...{ class: ([
'w-[56px] h-[56px] border rounded-md flex flex-col items-center justify-center text-[10px] select-none transition-all overflow-hidden',
__VLS_ctx.editMode && cell.etat !== 'occupe' && !__VLS_ctx.getCellPlanting(cell) ? 'cursor-pointer' : '',
__VLS_ctx.getCellPlanting(cell)
? 'bg-green/10 border-green/60 text-green'
: cell.etat === 'non_cultivable'
? 'bg-red/10 border-red/30 text-red/50'
: 'bg-bg-soft border-bg-hard text-text-muted',
__VLS_ctx.editMode && !__VLS_ctx.getCellPlanting(cell) && cell.etat !== 'occupe'
? (cell.etat === 'non_cultivable' ? 'hover:bg-red/20 hover:border-red/60' : 'hover:border-orange hover:bg-orange/10')
: ''
]) },
title: (__VLS_ctx.getCellTitle(cell)),
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['font-mono leading-none', __VLS_ctx.getCellPlanting(cell) ? 'text-[9px] font-bold' : '']) },
});
(cell.libelle);
if (__VLS_ctx.getCellPlanting(cell)) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[8px] text-green/80 leading-none mt-0.5 px-0.5 text-center truncate w-full" },
});
(__VLS_ctx.plantShortName(__VLS_ctx.getCellPlanting(cell)));
}
else if (cell.etat === 'non_cultivable') {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[9px] leading-none" },
});
}
}
if (__VLS_ctx.saving) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-2 text-xs text-text-muted animate-pulse" },
});
}
if (__VLS_ctx.activePlantings.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h3, __VLS_intrinsicElements.h3)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-2" },
});
(__VLS_ctx.activePlantings.length);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex flex-wrap gap-2" },
});
for (const [p] of __VLS_getVForSourceType((__VLS_ctx.activePlantings))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (p.id),
...{ class: "bg-bg-soft border border-green/30 rounded px-2 py-1 text-xs text-green flex items-center gap-1.5" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text-muted font-mono text-[10px]" },
});
(__VLS_ctx.plantCellLabel(p));
(__VLS_ctx.plantName(p));
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text-muted" },
});
(p.statut);
}
}
}
else {
@@ -153,10 +343,13 @@ else {
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
@@ -201,31 +394,101 @@ else {
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-wider']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['w-3']} */ ;
/** @type {__VLS_StyleScopedClasses['h-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['inline-block']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['w-3']} */ ;
/** @type {__VLS_StyleScopedClasses['h-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green/20']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/60']} */ ;
/** @type {__VLS_StyleScopedClasses['inline-block']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['w-3']} */ ;
/** @type {__VLS_StyleScopedClasses['h-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-red/20']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-red/40']} */ ;
/** @type {__VLS_StyleScopedClasses['inline-block']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-x-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-max']} */ ;
/** @type {__VLS_StyleScopedClasses['w-[52px]']} */ ;
/** @type {__VLS_StyleScopedClasses['h-[52px]']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-md']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[8px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green/80']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-none']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['px-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-none']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-green']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['select-none']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/30']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-mono']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
var __VLS_dollars;
@@ -234,7 +497,16 @@ const __VLS_self = (await import('vue')).defineComponent({
return {
router: router,
garden: garden,
editMode: editMode,
saving: saving,
displayCells: displayCells,
activePlantings: activePlantings,
getCellPlanting: getCellPlanting,
plantName: plantName,
plantShortName: plantShortName,
plantCellLabel: plantCellLabel,
getCellTitle: getCellTitle,
toggleNonCultivable: toggleNonCultivable,
};
},
});

File diff suppressed because it is too large Load Diff

View File

@@ -58,6 +58,11 @@ function onVideoSelected(event) {
if (file)
videoPreview.value = URL.createObjectURL(file);
}
function autoResize(event) {
const el = event.target;
el.style.height = 'auto';
el.style.height = el.scrollHeight + 'px';
}
function startEdit(t) {
editId.value = t.id;
Object.assign(form, {
@@ -134,159 +139,200 @@ const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4 max-w-4xl mx-auto" },
...{ class: "p-4 max-w-[1800px] mx-auto space-y-8" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-6" },
...{ class: "flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-yellow" },
...{ class: "text-3xl font-bold text-yellow tracking-tight" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openCreate) },
...{ class: "bg-yellow text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
...{ class: "btn-primary !bg-yellow !text-bg flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-lg leading-none" },
});
if (__VLS_ctx.toolsStore.loading) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm" },
...{ class: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 3xl:grid-cols-6 gap-4" },
});
for (const [i] of __VLS_getVForSourceType((6))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (i),
...{ class: "card-jardin h-32 animate-pulse opacity-20" },
});
}
}
else if (!__VLS_ctx.toolsStore.tools.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-sm py-4" },
...{ class: "card-jardin text-center py-16 opacity-50 border-dashed" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-4xl mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm uppercase font-black tracking-widest" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3" },
...{ class: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 3xl:grid-cols-6 gap-4" },
});
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.toolsStore.tools))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (t.id),
...{ class: "bg-bg-soft rounded-lg p-4 border border-bg-hard flex flex-col gap-2" },
...{ class: "card-jardin group flex flex-col h-full hover:border-yellow/30 transition-all !p-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between" },
...{ class: "flex items-start justify-between mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text font-semibold" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "min-w-0 flex-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-bold text-base group-hover:text-yellow transition-colors truncate" },
title: (t.nom),
});
(t.nom);
if (t.categorie) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "badge badge-yellow !text-[8px] mt-0.5" },
});
(t.categorie);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2" },
...{ class: "flex gap-2 shrink-0 ml-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.startEdit(t);
} },
...{ class: "text-yellow text-xs hover:underline" },
...{ class: "text-[10px] text-text-muted hover:text-yellow font-bold uppercase tracking-tighter transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (...[$event]) => {
__VLS_ctx.removeTool(t.id);
} },
...{ class: "text-red text-xs hover:underline" },
...{ class: "text-[10px] text-text-muted hover:text-red font-bold uppercase tracking-tighter transition-colors" },
});
if (t.categorie) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs text-yellow bg-yellow/10 rounded-full px-2 py-0.5 w-fit" },
});
(t.categorie);
}
if (t.description) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs" },
...{ class: "text-text-muted text-[11px] leading-snug line-clamp-2 mb-3 italic opacity-80" },
});
(t.description);
}
if (t.boutique_nom || t.prix_achat != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs" },
if (t.photo_url || t.video_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mb-3 rounded-lg overflow-hidden bg-bg-hard border border-bg-soft/30 relative aspect-video shrink-0" },
});
if (t.boutique_nom) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
(t.boutique_nom);
if (t.photo_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (t.photo_url),
...{ class: "w-full h-full object-cover transition-transform group-hover:scale-105" },
});
}
if (t.prix_achat != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({});
(t.prix_achat);
if (t.video_url && !t.photo_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "w-full h-full flex items-center justify-center text-aqua opacity-30" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
});
}
if (t.video_url && t.photo_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute bottom-1 right-1 bg-black/60 rounded px-1 py-0.5 text-[8px] text-aqua font-bold uppercase" },
});
}
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-auto pt-2 border-t border-bg-hard/30" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 text-[9px] font-bold text-text-muted truncate" },
});
if (t.boutique_nom) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "truncate" },
});
(t.boutique_nom);
}
if (t.prix_achat != null) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "shrink-0 text-yellow" },
});
(t.prix_achat);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-1" },
});
if (t.boutique_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.a, __VLS_intrinsicElements.a)({
href: (t.boutique_url),
target: "_blank",
rel: "noopener noreferrer",
...{ class: "text-blue text-xs hover:underline truncate" },
...{ class: "p-1 hover:bg-blue/10 rounded transition-colors text-blue" },
title: "Boutique",
});
}
if (t.video_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.a, __VLS_intrinsicElements.a)({
href: (t.video_url),
target: "_blank",
rel: "noopener noreferrer",
...{ class: "text-aqua text-xs hover:underline truncate" },
...{ class: "p-1 hover:bg-aqua/10 rounded transition-colors text-aqua" },
title: "Vidéo",
});
}
if (t.notice_texte) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs whitespace-pre-line" },
});
(t.notice_texte);
}
else if (t.notice_fichier_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.a, __VLS_intrinsicElements.a)({
href: (t.notice_fichier_url),
target: "_blank",
rel: "noopener noreferrer",
...{ class: "text-aqua text-xs hover:underline truncate" },
});
}
if (t.photo_url || t.video_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-auto pt-2 space-y-2" },
});
if (t.photo_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (t.photo_url),
alt: "photo outil",
...{ class: "w-full h-28 object-cover rounded border border-bg-hard bg-bg" },
});
}
if (t.video_url) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.video)({
src: (t.video_url),
controls: true,
muted: true,
...{ class: "w-full h-36 object-cover rounded border border-bg-hard bg-bg" },
});
}
}
}
if (__VLS_ctx.showForm) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ onClick: (__VLS_ctx.closeForm) },
...{ class: "fixed inset-0 bg-black/60 z-50 flex items-center justify-center p-4" },
...{ class: "fixed inset-0 bg-black/80 backdrop-blur-sm z-[100] flex items-center justify-center p-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "bg-bg-hard rounded-xl p-6 w-full max-w-md border border-bg-soft" },
...{ class: "bg-bg-hard rounded-2xl p-6 w-full max-w-xl border border-bg-soft shadow-2xl max-h-[90vh] overflow-y-auto" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-6 border-b border-bg-soft pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-bold text-lg mb-4" },
...{ class: "text-text font-bold text-xl" },
});
(__VLS_ctx.editId ? 'Modifier l\'outil' : 'Nouvel outil');
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.closeForm) },
...{ class: "text-text-muted hover:text-red transition-colors text-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.form, __VLS_intrinsicElements.form)({
...{ onSubmit: (__VLS_ctx.submitTool) },
...{ class: "flex flex-col gap-3" },
...{ class: "grid grid-cols-1 md:grid-cols-2 gap-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "md:col-span-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
placeholder: "Nom de l'outil *",
required: true,
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
placeholder: "Grelinette, Sécateur...",
...{ class: "w-full bg-bg border border-bg-soft rounded-xl px-4 py-3 text-text text-sm focus:border-yellow outline-none transition-all shadow-inner" },
});
(__VLS_ctx.form.nom);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.select, __VLS_intrinsicElements.select)({
value: (__VLS_ctx.form.categorie),
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
...{ class: "w-full bg-bg border border-bg-soft rounded-xl px-4 py-2.5 text-text text-sm outline-none focus:border-yellow" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.option, __VLS_intrinsicElements.option)({
value: "",
@@ -309,347 +355,425 @@ if (__VLS_ctx.showForm) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.option, __VLS_intrinsicElements.option)({
value: "autre",
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-2 gap-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
placeholder: "Nom boutique",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
});
(__VLS_ctx.form.boutique_nom);
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
type: "number",
min: "0",
step: "0.01",
placeholder: "Prix achat (€)",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
});
(__VLS_ctx.form.prix_achat);
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
type: "url",
placeholder: "URL boutique (https://...)",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
});
(__VLS_ctx.form.boutique_url);
__VLS_asFunctionalElement(__VLS_intrinsicElements.textarea)({
value: (__VLS_ctx.form.description),
placeholder: "Description...",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow resize-none h-16" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-xs block mb-1" },
...{ class: "text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
type: "number",
step: "0.01",
...{ class: "w-full bg-bg border border-bg-soft rounded-xl px-4 py-2.5 text-text text-sm outline-none focus:border-yellow" },
});
(__VLS_ctx.form.prix_achat);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "md:col-span-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.textarea)({
...{ onInput: (__VLS_ctx.autoResize) },
value: (__VLS_ctx.form.description),
rows: "1",
...{ class: "w-full bg-bg border border-bg-soft rounded-xl px-4 py-2 text-text text-sm focus:border-yellow outline-none resize-none transition-all overflow-hidden" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "bg-bg-soft/30 p-3 rounded-xl border border-bg-soft" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-[9px] font-black uppercase tracking-widest block mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
...{ onChange: (__VLS_ctx.onPhotoSelected) },
type: "file",
accept: "image/*",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
...{ class: "text-[10px] text-text-muted w-full" },
});
if (__VLS_ctx.photoPreview) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.img)({
src: (__VLS_ctx.photoPreview),
alt: "Prévisualisation photo",
...{ class: "mt-2 w-full h-28 object-cover rounded border border-bg-hard bg-bg" },
...{ class: "mt-2 w-full h-24 object-cover rounded border border-bg-hard shadow-lg" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "bg-bg-soft/30 p-3 rounded-xl border border-bg-soft" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-text-muted text-xs block mb-1" },
...{ class: "text-text-muted text-[9px] font-black uppercase tracking-widest block mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
...{ onChange: (__VLS_ctx.onVideoSelected) },
type: "file",
accept: "video/*",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow" },
...{ class: "text-[10px] text-text-muted w-full" },
});
if (__VLS_ctx.videoPreview) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.video)({
src: (__VLS_ctx.videoPreview),
controls: true,
muted: true,
...{ class: "mt-2 w-full h-36 object-cover rounded border border-bg-hard bg-bg" },
...{ class: "mt-2 w-full h-24 object-cover rounded border border-bg-hard shadow-lg" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.textarea)({
value: (__VLS_ctx.form.notice_texte),
placeholder: "Notice (texte libre)...",
...{ class: "bg-bg border border-bg-soft rounded-lg px-3 py-2 text-text text-sm w-full outline-none focus:border-yellow resize-none h-24" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex gap-2 justify-end" },
...{ class: "md:col-span-2 flex justify-between items-center pt-6 border-t border-bg-soft mt-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.closeForm) },
type: "button",
...{ class: "px-4 py-2 text-text-muted hover:text-text text-sm" },
...{ class: "btn-outline border-transparent text-text-muted hover:text-red uppercase text-xs font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
type: "submit",
...{ class: "bg-yellow text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
...{ class: "btn-primary !bg-yellow !text-bg px-8" },
});
(__VLS_ctx.editId ? 'Enregistrer' : 'Créer');
(__VLS_ctx.editId ? 'Sauvegarder' : 'Enregistrer l\'outil');
}
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-4xl']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-[1800px]']} */ ;
/** @type {__VLS_StyleScopedClasses['mx-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-8']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['py-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-none']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['xl:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['2xl:grid-cols-5']} */ ;
/** @type {__VLS_StyleScopedClasses['3xl:grid-cols-6']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['h-32']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-20']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-16']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-50']} */ ;
/** @type {__VLS_StyleScopedClasses['border-dashed']} */ ;
/** @type {__VLS_StyleScopedClasses['text-4xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['xl:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['2xl:grid-cols-5']} */ ;
/** @type {__VLS_StyleScopedClasses['3xl:grid-cols-6']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-yellow/30']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['!p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['min-w-0']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-base']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['badge']} */ ;
/** @type {__VLS_StyleScopedClasses['badge-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-[8px]']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['ml-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[11px]']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-snug']} */ ;
/** @type {__VLS_StyleScopedClasses['line-clamp-2']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['italic']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-80']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['aspect-video']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-transform']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:scale-105']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-30']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['bottom-1']} */ ;
/** @type {__VLS_StyleScopedClasses['right-1']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/60']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-1']} */ ;
/** @type {__VLS_StyleScopedClasses['py-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[8px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard/30']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow/10']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['w-fit']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['p-1']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-blue/10']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['whitespace-pre-line']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-28']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['p-1']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-aqua/10']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-36']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['fixed']} */ ;
/** @type {__VLS_StyleScopedClasses['inset-0']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/60']} */ ;
/** @type {__VLS_StyleScopedClasses['z-50']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-black/80']} */ ;
/** @type {__VLS_StyleScopedClasses['backdrop-blur-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['z-[100]']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-center']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-6']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-md']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['max-h-[90vh]']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-y-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['resize-none']} */ ;
/** @type {__VLS_StyleScopedClasses['h-16']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['md:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-28']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-inner']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['md:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['resize-none']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-36']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['outline-none']} */ ;
/** @type {__VLS_StyleScopedClasses['focus:border-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['resize-none']} */ ;
/** @type {__VLS_StyleScopedClasses['h-24']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-end']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['block']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-24']} */ ;
/** @type {__VLS_StyleScopedClasses['object-cover']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['md:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['border-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-red']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-8']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {
@@ -663,6 +787,7 @@ const __VLS_self = (await import('vue')).defineComponent({
openCreate: openCreate,
onPhotoSelected: onPhotoSelected,
onVideoSelected: onVideoSelected,
autoResize: autoResize,
startEdit: startEdit,
closeForm: closeForm,
submitTool: submitTool,

View File

@@ -93,17 +93,20 @@ function goToday() {
function selectDay(iso) {
selectedIso.value = iso;
}
const priorityClass = (p) => ({
haute: 'bg-red/20 text-red',
normale: 'bg-yellow/20 text-yellow',
basse: 'bg-bg-hard text-text-muted',
}[p] || 'bg-bg-hard text-text-muted');
const priorityBorderClass = (p) => ({
haute: 'border-red/30 text-red bg-red/5',
normale: 'border-yellow/30 text-yellow bg-yellow/5',
basse: 'border-bg-soft text-text-muted bg-bg-hard/50',
}[p] || 'border-bg-soft text-text-muted');
const dotClass = (p) => ({
haute: 'bg-red', normale: 'bg-yellow', basse: 'bg-text-muted',
haute: 'bg-red shadow-[0_0_5px_rgba(251,73,52,0.5)]',
normale: 'bg-yellow shadow-[0_0_5px_rgba(250,189,47,0.5)]',
basse: 'bg-text-muted',
}[p] || 'bg-text-muted');
const statutClass = (s) => ({
a_faire: 'bg-blue/20 text-blue', en_cours: 'bg-green/20 text-green',
fait: 'bg-text-muted/20 text-text-muted',
a_faire: 'badge-blue',
en_cours: 'badge-green',
fait: 'badge-text-muted',
}[s] || '');
onMounted(() => store.fetchAll());
debugger; /* PartiallyEnd: #3632/scriptSetup.vue */
@@ -111,45 +114,55 @@ const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4 max-w-3xl mx-auto" },
...{ class: "p-4 max-w-6xl mx-auto space-y-8" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center justify-between mb-6" },
...{ class: "flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-green" },
...{ class: "text-3xl font-bold text-green tracking-tight" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-2" },
...{ class: "flex items-center gap-2 bg-bg-soft/30 p-1 rounded-xl border border-bg-soft" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.prevPeriod) },
...{ class: "text-xs text-text-muted border border-bg-hard rounded px-2 py-1 hover:text-text hover:border-text-muted" },
...{ class: "btn-outline !py-1.5 !px-3 text-xs font-bold uppercase tracking-widest border-transparent hover:bg-bg-soft transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.goToday) },
...{ class: "text-xs text-green border border-green/30 rounded px-2 py-1 hover:bg-green/10" },
...{ class: "btn-primary !py-1.5 !px-4 text-xs !rounded-lg" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.nextPeriod) },
...{ class: "text-xs text-text-muted border border-bg-hard rounded px-2 py-1 hover:text-text hover:border-text-muted" },
...{ class: "btn-outline !py-1.5 !px-3 text-xs font-bold uppercase tracking-widest border-transparent hover:bg-bg-soft transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text text-sm font-medium mb-3" },
...{ class: "flex items-center gap-3" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-yellow font-bold text-sm tracking-widest uppercase bg-yellow/5 px-4 py-1 rounded-full border border-yellow/10" },
});
(__VLS_ctx.periodLabel);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-7 gap-1 mb-2" },
...{ class: "space-y-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-7 gap-3" },
});
for (const [dayName] of __VLS_getVForSourceType((__VLS_ctx.dayHeaders))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (dayName),
...{ class: "text-center text-xs py-1 rounded text-text-muted" },
...{ class: "text-center text-[10px] font-black uppercase tracking-[0.2em] text-text-muted/60 pb-2" },
});
(dayName);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-7 gap-1" },
...{ class: "grid grid-cols-7 gap-3" },
});
for (const [d] of __VLS_getVForSourceType((__VLS_ctx.periodDays))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
@@ -157,236 +170,349 @@ for (const [d] of __VLS_getVForSourceType((__VLS_ctx.periodDays))) {
__VLS_ctx.selectDay(d.iso);
} },
key: (d.iso),
...{ class: (['min-h-24 rounded-lg p-1 border transition-colors cursor-pointer',
d.isToday ? 'border-green/40 bg-green/5' : 'border-bg-hard bg-bg-soft',
__VLS_ctx.selectedIso === d.iso ? 'ring-1 ring-yellow/60 border-yellow/40' : '']) },
...{ class: (['min-h-32 card-jardin !p-2 flex flex-col group relative cursor-pointer border-2 transition-all',
d.isToday ? 'border-green/40 bg-green/5' : 'border-bg-hard/50',
__VLS_ctx.selectedIso === d.iso ? '!border-yellow bg-yellow/5 scale-[1.02] z-10 shadow-xl' : 'hover:border-bg-soft']) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[11px] text-text-muted mb-1" },
...{ class: "flex items-center justify-between mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (d.isToday ? 'text-green font-bold' : '') },
...{ class: (['text-xs font-bold font-mono', d.isToday ? 'text-green' : 'text-text-muted']) },
});
(d.dayNum);
if (d.showMonth) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "ml-1" },
...{ class: "text-[9px] font-black uppercase tracking-tighter text-aqua" },
});
(d.monthShort);
}
if (__VLS_ctx.todoTasksByDay[d.iso]?.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-1 flex-wrap mb-1" },
});
for (const [t, i] of __VLS_getVForSourceType((__VLS_ctx.todoTasksByDay[d.iso].slice(0, 10)))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
key: (`${d.iso}-${t.id ?? i}`),
...{ class: (['w-1.5 h-1.5 rounded-full', __VLS_ctx.dotClass(t.priorite)]) },
});
}
}
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.tasksByDay[d.iso] || []))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1 space-y-1 overflow-hidden" },
});
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.tasksByDay[d.iso]?.slice(0, 3)))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (t.id),
...{ class: (['text-xs rounded px-1 py-0.5 mb-0.5 cursor-pointer hover:opacity-80 truncate',
__VLS_ctx.priorityClass(t.priorite)]) },
title: (t.titre),
...{ class: (['text-[9px] font-bold uppercase tracking-tighter rounded px-1.5 py-0.5 truncate border', __VLS_ctx.priorityBorderClass(t.priorite)]) },
});
(t.titre);
}
if (!(__VLS_ctx.tasksByDay[d.iso]?.length)) {
if (__VLS_ctx.tasksByDay[d.iso]?.length > 3) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs text-center pt-2 opacity-40" },
...{ class: "text-[9px] text-text-muted font-bold text-center pt-1" },
});
(__VLS_ctx.tasksByDay[d.iso].length - 3);
}
if (__VLS_ctx.todoTasksByDay[d.iso]?.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute bottom-2 right-2 flex gap-0.5" },
});
for (const [t, i] of __VLS_getVForSourceType((__VLS_ctx.todoTasksByDay[d.iso].slice(0, 3)))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
key: (i),
...{ class: (['w-1 h-1 rounded-full', __VLS_ctx.dotClass(t.priorite)]) },
});
}
}
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-4 bg-bg-soft rounded-lg p-3 border border-bg-hard" },
...{ class: "grid grid-cols-1 lg:grid-cols-3 gap-8 pt-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text text-sm font-semibold" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "lg:col-span-2 space-y-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-yellow" },
});
(__VLS_ctx.selectedLabel);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs mt-0.5" },
});
(__VLS_ctx.selectedTasks.length);
if (!__VLS_ctx.selectedTasks.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs mt-2" },
...{ class: "card-jardin text-center py-12 opacity-40 border-dashed" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm italic" },
});
}
else {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-2 space-y-1" },
...{ class: "space-y-3" },
});
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.selectedTasks))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (t.id),
...{ class: "bg-bg rounded px-2 py-1 border border-bg-hard flex items-center gap-2" },
...{ class: "card-jardin flex items-center gap-4 group" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['w-2 h-2 rounded-full shrink-0', __VLS_ctx.dotClass(t.priorite)]) },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: (['w-1.5 h-10 rounded-full shrink-0', __VLS_ctx.dotClass(t.priorite)]) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text text-xs flex-1 truncate" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1 min-w-0" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text font-bold text-sm" },
});
(t.titre);
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['text-[10px] px-1.5 py-0.5 rounded shrink-0', __VLS_ctx.statutClass(t.statut)]) },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['badge !text-[9px]', __VLS_ctx.statutClass(t.statut)]) },
});
(t.statut?.replace('_', ' '));
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] text-text-muted uppercase font-bold tracking-tighter opacity-60" },
});
(t.priorite);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-green text-xl opacity-0 group-hover:opacity-100 transition-all" },
});
(t.statut);
}
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-6" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "space-y-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text-muted text-xs uppercase tracking-widest mb-2" },
...{ class: "text-text-muted text-xs font-bold uppercase tracking-widest flex items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "w-2 h-2 rounded-full bg-orange" },
});
if (!__VLS_ctx.unscheduled.length) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-text-muted text-xs pl-2" },
...{ class: "card-jardin text-center py-12 opacity-30 border-dashed" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-[10px] font-bold uppercase" },
});
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "space-y-2" },
});
for (const [t] of __VLS_getVForSourceType((__VLS_ctx.unscheduled))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (t.id),
...{ class: "bg-bg-soft rounded-lg p-2 mb-1 border border-bg-hard flex items-center gap-2" },
...{ class: "card-jardin !p-3 flex flex-col gap-2 hover:border-orange/30 transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-start justify-between gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['text-xs w-2 h-2 rounded-full flex-shrink-0', __VLS_ctx.dotClass(t.priorite)]) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text text-sm flex-1 truncate" },
...{ class: "text-text font-bold text-xs flex-1 line-clamp-2" },
});
(t.titre);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: (['w-2 h-2 rounded-full shrink-0 mt-1', __VLS_ctx.dotClass(t.priorite)]) },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex justify-between items-center" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: (['text-xs px-1.5 py-0.5 rounded', __VLS_ctx.statutClass(t.statut)]) },
...{ class: (['badge !text-[8px]', __VLS_ctx.statutClass(t.statut)]) },
});
(t.statut);
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ class: "text-[10px] text-orange font-bold uppercase hover:underline" },
});
}
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-6xl']} */ ;
/** @type {__VLS_StyleScopedClasses['mx-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-8']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['p-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/30']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-green/10']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-medium']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[11px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['ml-1']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-1']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-40']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-2']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-1']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['!py-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['!px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['border-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!py-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['!px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['!rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['!py-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['!px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['border-transparent']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow/5']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-1']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-yellow/10']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-4']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-[0.2em]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted/60']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-7']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-1']} */ ;
/** @type {__VLS_StyleScopedClasses['overflow-hidden']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['bottom-2']} */ ;
/** @type {__VLS_StyleScopedClasses['right-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-0.5']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-8']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['lg:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['pl-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['p-2']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-1']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-12']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-40']} */ ;
/** @type {__VLS_StyleScopedClasses['border-dashed']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['italic']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-3']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['truncate']} */ ;
/** @type {__VLS_StyleScopedClasses['min-w-0']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tighter']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-60']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-0']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:opacity-100']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['w-2']} */ ;
/** @type {__VLS_StyleScopedClasses['h-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['py-12']} */ ;
/** @type {__VLS_StyleScopedClasses['opacity-30']} */ ;
/** @type {__VLS_StyleScopedClasses['border-dashed']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-2']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['!p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-orange/30']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['line-clamp-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-orange']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:underline']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({
setup() {
@@ -404,7 +530,7 @@ const __VLS_self = (await import('vue')).defineComponent({
nextPeriod: nextPeriod,
goToday: goToday,
selectDay: selectDay,
priorityClass: priorityClass,
priorityBorderClass: priorityBorderClass,
dotClass: dotClass,
statutClass: statutClass,
};

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
</button>
</div>
</div>
<div class="flex items-center gap-3">
<div class="relative min-w-[300px]">
<span class="absolute left-3 top-1/2 -translate-y-1/2 opacity-40">🔍</span>
@@ -29,28 +29,34 @@
</div>
</div>
<!-- Grille de 5 colonnes -->
<!-- Grille -->
<div v-if="plantsStore.loading" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4">
<div v-for="i in 10" :key="i" class="card-jardin h-40 animate-pulse opacity-20"></div>
</div>
<div v-else class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4">
<div v-for="p in filteredPlants" :key="p.id"
<div v-for="p in filteredPlants" :key="(p.nom_commun||'').toLowerCase()"
class="card-jardin !p-0 group overflow-hidden flex flex-col hover:border-yellow/40 transition-all border-l-[6px] relative min-h-[160px] cursor-pointer"
:style="{ borderLeftColor: getCatColor(p.categorie || '') }"
:style="{ borderLeftColor: getCatColor(groupPrimaryCategory(p.nom_commun||'')) }"
@click="openDetails(p)">
<!-- Badge catégorie en haut à gauche -->
<!-- Badge catégorie -->
<div class="absolute top-2 left-2">
<span :class="['text-[7px] font-black uppercase tracking-[0.2em] px-2 py-0.5 rounded bg-bg/60 backdrop-blur-sm', catTextClass(p.categorie || '')]">
{{ p.categorie }}
<span :class="['text-[7px] font-black uppercase tracking-[0.2em] px-2 py-0.5 rounded bg-bg/60 backdrop-blur-sm', catTextClass(groupPrimaryCategory(p.nom_commun||''))]">
{{ groupPrimaryCategory(p.nom_commun||'') }}
</span>
</div>
<!-- Badge nombre de variétés -->
<div v-if="groupSize(p.nom_commun||'') > 1" class="absolute top-2 right-2">
<span class="text-[9px] font-black px-2 py-0.5 rounded-full bg-yellow/20 text-yellow border border-yellow/30">
{{ groupSize(p.nom_commun||'') }} variétés
</span>
</div>
<div class="p-5 flex-1 flex flex-col justify-center">
<h2 class="text-text font-bold text-2xl leading-tight group-hover:text-yellow transition-colors">{{ p.nom_commun }}</h2>
<p v-if="p.variete" class="text-text-muted text-[10px] font-black uppercase tracking-widest mt-1 opacity-60">{{ p.variete }}</p>
<h2 class="text-text font-bold text-2xl leading-tight group-hover:text-yellow transition-colors capitalize">{{ p.nom_commun }}</h2>
<div class="mt-4 flex flex-wrap gap-2">
<div v-if="p.plantation_mois" class="flex items-center gap-2 bg-bg/40 px-2 py-1 rounded border border-bg-soft">
<span class="text-[10px]">📅</span>
@@ -65,22 +71,45 @@
</div>
</div>
<!-- Modale de Détails (Popup) -->
<div v-if="detailPlant" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4" @click.self="detailPlant = null">
<!-- Modale Détails -->
<div v-if="detailPlant" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-50 flex items-center justify-center p-4" @click.self="closeDetail">
<div class="bg-bg-hard rounded-3xl w-full max-w-2xl border border-bg-soft shadow-2xl overflow-hidden flex flex-col max-h-[90vh]">
<!-- Header de la modale -->
<div class="p-6 border-b border-bg-soft flex justify-between items-start" :style="{ borderLeft: `8px solid ${getCatColor(detailPlant.categorie || '')}` }">
<div>
<span :class="['text-[10px] font-black uppercase tracking-widest px-2 py-1 rounded mb-2 inline-block bg-bg/50', catTextClass(detailPlant.categorie || '')]">
{{ detailPlant.categorie }}
</span>
<h2 class="text-text font-black text-4xl leading-none">{{ detailPlant.nom_commun }}</h2>
<p v-if="detailPlant.variete" class="text-yellow font-bold uppercase tracking-widest text-sm mt-1">{{ detailPlant.variete }}</p>
<!-- Header -->
<div class="p-6 border-b border-bg-soft" :style="{ borderLeft: `8px solid ${getCatColor(detailPlant.categorie || '')}` }">
<div class="flex justify-between items-start">
<div class="flex-1 min-w-0">
<span :class="['text-[10px] font-black uppercase tracking-widest px-2 py-1 rounded mb-2 inline-block bg-bg/50', catTextClass(detailPlant.categorie || '')]">
{{ detailPlant.categorie }}
</span>
<h2 class="text-text font-black text-4xl leading-none capitalize">{{ detailPlant.nom_commun }}</h2>
<!-- Navigation variétés -->
<div class="flex items-center gap-3 mt-3">
<div v-if="detailVarieties.length > 1" class="flex items-center gap-2">
<button @click="prevVariety"
:disabled="detailVarietyIdx === 0"
:class="['w-7 h-7 rounded-full border flex items-center justify-center text-sm font-bold transition-all',
detailVarietyIdx === 0 ? 'border-bg-soft text-text-muted/30 cursor-not-allowed' : 'border-yellow/50 text-yellow hover:bg-yellow/10']">
</button>
<span class="text-text-muted text-xs font-bold">
Variété {{ detailVarietyIdx + 1 }} / {{ detailVarieties.length }}
</span>
<button @click="nextVariety"
:disabled="detailVarietyIdx === detailVarieties.length - 1"
:class="['w-7 h-7 rounded-full border flex items-center justify-center text-sm font-bold transition-all',
detailVarietyIdx === detailVarieties.length - 1 ? 'border-bg-soft text-text-muted/30 cursor-not-allowed' : 'border-yellow/50 text-yellow hover:bg-yellow/10']">
</button>
</div>
<p v-if="detailPlant.variete" class="text-yellow font-bold uppercase tracking-widest text-sm">{{ detailPlant.variete }}</p>
</div>
</div>
<button @click="closeDetail" class="text-text-muted hover:text-red transition-colors text-2xl ml-4"></button>
</div>
<button @click="detailPlant = null" class="text-text-muted hover:text-red transition-colors text-2xl"></button>
</div>
<!-- Corps de la modale -->
<!-- Corps -->
<div class="p-6 overflow-y-auto space-y-6">
<!-- Caractéristiques -->
<div class="grid grid-cols-3 gap-4">
@@ -107,6 +136,40 @@
</div>
</div>
<!-- Boutique -->
<div v-if="detailPlant.boutique_nom || detailPlant.prix_achat || detailPlant.poids || detailPlant.dluo" class="space-y-2">
<h3 class="text-[10px] font-black text-text-muted uppercase tracking-widest">🛒 Approvisionnement</h3>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3">
<div v-if="detailPlant.boutique_nom" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">Enseigne</span>
<span class="text-text text-sm font-bold">{{ detailPlant.boutique_nom }}</span>
</div>
<div v-if="detailPlant.prix_achat" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">Prix</span>
<span class="text-yellow font-bold">{{ detailPlant.prix_achat.toFixed(2) }} </span>
</div>
<div v-if="detailPlant.date_achat" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">Date d'achat</span>
<span class="text-text text-sm">{{ detailPlant.date_achat }}</span>
</div>
<div v-if="detailPlant.poids" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">Poids / Qté</span>
<span class="text-text text-sm font-bold">{{ detailPlant.poids }}</span>
</div>
<div v-if="detailPlant.dluo" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">DLUO</span>
<span :class="['text-sm font-bold', isDluoExpired(detailPlant.dluo) ? 'text-red' : 'text-green']">
{{ detailPlant.dluo }}{{ isDluoExpired(detailPlant.dluo) ? ' ' : '' }}
</span>
</div>
<div v-if="detailPlant.boutique_url" class="bg-bg/30 p-3 rounded-xl border border-bg-soft">
<span class="text-[9px] font-black text-text-muted uppercase block mb-0.5">Lien</span>
<a :href="detailPlant.boutique_url" target="_blank" rel="noopener"
class="text-blue text-xs hover:underline truncate block">🔗 Voir le produit</a>
</div>
</div>
</div>
<!-- Notes -->
<div v-if="detailPlant.notes" class="space-y-2">
<h3 class="text-[10px] font-black text-text-muted uppercase tracking-widest">Conseils & Notes</h3>
@@ -115,6 +178,31 @@
</div>
</div>
<!-- Associations (niveau nom commun) -->
<div v-if="detailAssociations?.associations_favorables?.length || detailAssociations?.associations_defavorables?.length" class="space-y-3">
<h3 class="text-[10px] font-black text-text-muted uppercase tracking-widest">Associations</h3>
<div class="grid grid-cols-2 gap-4">
<div v-if="detailAssociations?.associations_favorables?.length">
<div class="text-[10px] font-black text-green uppercase mb-1.5">🤝 Favorables</div>
<div class="flex flex-wrap gap-1.5">
<span v-for="n in detailAssociations.associations_favorables" :key="n"
class="bg-green/10 border border-green/40 text-green text-[11px] px-2 py-0.5 rounded-full capitalize">
{{ n }}
</span>
</div>
</div>
<div v-if="detailAssociations?.associations_defavorables?.length">
<div class="text-[10px] font-black text-red uppercase mb-1.5">⚡ À éviter</div>
<div class="flex flex-wrap gap-1.5">
<span v-for="n in detailAssociations.associations_defavorables" :key="n"
class="bg-red/10 border border-red/40 text-red text-[11px] px-2 py-0.5 rounded-full capitalize">
{{ n }}
</span>
</div>
</div>
</div>
</div>
<!-- Galerie Photos -->
<div class="space-y-3">
<div class="flex justify-between items-center">
@@ -125,7 +213,7 @@
<div v-for="i in 4" :key="i" class="aspect-square bg-bg-soft rounded-lg"></div>
</div>
<div v-else-if="plantPhotos.length" class="grid grid-cols-4 gap-2">
<div v-for="m in plantPhotos" :key="m.id"
<div v-for="m in plantPhotos" :key="m.id"
class="aspect-square rounded-lg overflow-hidden bg-bg relative group cursor-pointer border border-bg-soft"
@click="lightbox = m">
<img :src="m.thumbnail_url || m.url" class="w-full h-full object-cover group-hover:scale-110 transition-transform" />
@@ -138,7 +226,7 @@
</div>
</div>
<!-- Footer de la modale -->
<!-- Footer -->
<div class="p-4 bg-bg-hard border-t border-bg-soft flex gap-3">
<button @click="startEdit(detailPlant)" class="btn-primary !bg-yellow !text-bg flex-1 py-3 font-black uppercase text-xs tracking-widest">Modifier la fiche</button>
<button @click="removePlant(detailPlant.id!)" class="btn-outline !border-red/20 !text-red hover:bg-red/10 px-6 py-3 font-black uppercase text-xs tracking-widest">Supprimer</button>
@@ -155,7 +243,6 @@
</div>
<form @submit.prevent="submitPlant" class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Champs de formulaire identiques -->
<div class="space-y-4">
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">Nom commun *</label>
@@ -208,6 +295,84 @@
</div>
</div>
<!-- Boutique / Approvisionnement (par variété) -->
<div class="md:col-span-2 bg-bg/40 border border-bg-soft rounded-2xl p-4">
<div class="flex items-center gap-2 mb-4">
<span class="text-[10px] font-black text-text-muted uppercase tracking-widest">🛒 Boutique / Approvisionnement</span>
<span class="text-[9px] text-text-muted/50 italic">spécifique à cette variété</span>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">Enseigne</label>
<select v-model="form.boutique_nom" class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm outline-none focus:border-yellow appearance-none">
<option value="">— Non renseigné —</option>
<option v-for="b in BOUTIQUES" :key="b" :value="b">{{ b }}</option>
</select>
</div>
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">Prix (€)</label>
<input v-model.number="form.prix_achat" type="number" step="0.01" min="0" placeholder="0.00"
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">Date d'achat</label>
<input v-model="form.date_achat" type="date"
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">Poids / Quantité</label>
<input v-model="form.poids" placeholder="ex: 5g, 50 graines, 1kg"
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">DLUO</label>
<input v-model="form.dluo" type="date"
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
<div>
<label class="text-text-muted text-[10px] font-black uppercase tracking-widest block mb-1">URL produit</label>
<input v-model="form.boutique_url" type="url" placeholder="https://..."
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
</div>
</div>
<!-- Associations (niveau nom commun s'applique à toutes les variétés) -->
<div class="md:col-span-2 bg-bg/40 border border-bg-soft rounded-2xl p-4">
<div class="flex items-center justify-between mb-3">
<div>
<span class="text-[10px] font-black text-text-muted uppercase tracking-widest">Associations</span>
<span class="text-[9px] text-text-muted/50 ml-2 italic">s'applique à toutes les variétés</span>
</div>
<button type="button" @click="showAssocModal = true"
class="px-3 py-1 rounded-full text-xs font-bold border border-bg-soft text-text-muted hover:border-yellow hover:text-yellow transition-all">
Modifier
</button>
</div>
<div class="mb-2">
<div class="text-[9px] font-black text-green uppercase tracking-widest mb-1">🤝 Favorables</div>
<div class="flex flex-wrap gap-1.5 min-h-[22px]">
<span v-if="!form.associations_favorables.length" class="text-[10px] text-text-muted/40 italic">aucune</span>
<span v-for="n in form.associations_favorables" :key="n"
class="flex items-center gap-1 bg-green/10 border border-green/40 text-green text-[11px] px-2 py-0.5 rounded-full capitalize">
{{ n }}
<button type="button" @click="askRemoveAssoc('fav', n)" class="hover:text-red leading-none ml-0.5"></button>
</span>
</div>
</div>
<div>
<div class="text-[9px] font-black text-red uppercase tracking-widest mb-1"> À éviter</div>
<div class="flex flex-wrap gap-1.5 min-h-[22px]">
<span v-if="!form.associations_defavorables.length" class="text-[10px] text-text-muted/40 italic">aucune</span>
<span v-for="n in form.associations_defavorables" :key="n"
class="flex items-center gap-1 bg-red/10 border border-red/40 text-red text-[11px] px-2 py-0.5 rounded-full capitalize">
{{ n }}
<button type="button" @click="askRemoveAssoc('def', n)" class="hover:text-red/60 leading-none ml-0.5"></button>
</span>
</div>
</div>
</div>
<div class="md:col-span-2 flex justify-between items-center pt-6 border-t border-bg-soft mt-4">
<button type="button" @click="closeForm" class="btn-outline border-transparent text-text-muted hover:text-red uppercase text-xs font-bold px-6">Annuler</button>
<button type="submit" class="btn-primary px-12 py-4 text-base shadow-xl !bg-yellow !text-bg">
@@ -224,7 +389,78 @@
<button class="absolute top-6 right-6 text-white text-4xl hover:text-yellow"></button>
</div>
<!-- Upload Photo Trigger (Invisible) -->
<!-- Popup Gestion Associations -->
<div v-if="showAssocModal" class="fixed inset-0 bg-black/80 backdrop-blur-sm z-[60] flex items-center justify-center p-4" @click.self="showAssocModal = false">
<div class="bg-bg-hard rounded-2xl w-full max-w-lg border border-bg-soft shadow-2xl flex flex-col max-h-[80vh]">
<div class="flex items-center justify-between p-4 border-b border-bg-soft">
<h3 class="text-text font-black uppercase tracking-tight">
Associations {{ form.nom_commun || 'plante' }}
</h3>
<button @click="showAssocModal = false" class="text-text-muted hover:text-red text-xl transition-colors"></button>
</div>
<div class="px-4 pt-3 pb-2">
<input v-model="assocFilter" placeholder="🔍 Filtrer les plantes..."
class="w-full bg-bg border border-bg-soft rounded-xl px-3 py-2 text-text text-sm focus:border-yellow outline-none" />
</div>
<div class="overflow-y-auto flex-1 px-4 pb-4 space-y-1">
<div v-for="name in filteredAssocPlants" :key="name"
class="flex items-center justify-between py-2 px-3 rounded-xl hover:bg-bg/40 transition-colors">
<span class="text-text text-sm font-medium flex-1 capitalize">{{ name }}</span>
<div class="flex gap-1.5">
<button type="button"
:class="['px-2 py-1 rounded-lg text-[10px] font-black uppercase transition-all border',
getAssocState(name) === 'fav'
? 'bg-green text-bg border-green'
: 'border-green/30 text-green/60 hover:border-green hover:text-green']"
@click="setAssocState(name, 'fav')">
🤝 Ami
</button>
<button type="button"
:class="['px-2 py-1 rounded-lg text-[10px] font-black uppercase transition-all border',
getAssocState(name) === 'def'
? 'bg-red text-bg border-red'
: 'border-red/30 text-red/60 hover:border-red hover:text-red']"
@click="setAssocState(name, 'def')">
Ennemi
</button>
<button type="button"
:class="['px-2 py-1 rounded-lg text-[10px] font-black uppercase transition-all border',
getAssocState(name) === null
? 'bg-bg-soft text-text-muted border-bg-soft'
: 'border-bg-soft/40 text-text-muted/40 hover:border-bg-soft hover:text-text-muted']"
@click="setAssocState(name, null)">
· Neutre
</button>
</div>
</div>
<div v-if="!filteredAssocPlants.length" class="text-center py-8 text-text-muted/40 text-xs italic">
Aucune plante trouvée
</div>
</div>
<div class="p-4 border-t border-bg-soft text-center">
<button @click="showAssocModal = false"
class="px-6 py-2 rounded-xl bg-yellow text-bg font-black text-xs uppercase tracking-widest hover:opacity-90 transition-opacity">
Valider
</button>
</div>
</div>
</div>
<!-- Confirmation suppression tag -->
<div v-if="confirmRemove" class="fixed inset-0 bg-black/60 z-[70] flex items-center justify-center p-4">
<div class="bg-bg-hard rounded-2xl p-6 w-full max-w-sm border border-bg-soft shadow-2xl text-center">
<p class="text-text mb-1 font-bold">Retirer <span class="text-yellow capitalize">{{ confirmRemove.name }}</span> ?</p>
<p class="text-text-muted text-xs mb-5">
{{ confirmRemove.type === 'fav' ? 'Retirer des associations favorables' : 'Retirer des associations défavorables' }}
</p>
<div class="flex gap-3 justify-center">
<button @click="confirmRemove = null" class="px-4 py-2 rounded-xl border border-bg-soft text-text-muted text-xs font-bold hover:text-text transition-colors">Annuler</button>
<button @click="confirmRemoveAssoc" class="px-4 py-2 rounded-xl bg-red text-bg text-xs font-black uppercase hover:opacity-90 transition-opacity">Retirer</button>
</div>
</div>
</div>
<!-- Upload Photo -->
<input type="file" ref="fileInput" accept="image/*" class="hidden" @change="handleFileUpload" />
</div>
</template>
@@ -234,7 +470,6 @@ import { computed, onMounted, reactive, ref } from 'vue'
import axios from 'axios'
import { usePlantsStore } from '@/stores/plants'
import type { Plant } from '@/api/plants'
import { formatPlantLabel } from '@/utils/plants'
import { useToast } from '@/composables/useToast'
const plantsStore = usePlantsStore()
@@ -242,7 +477,6 @@ const toast = useToast()
const showForm = ref(false)
const submitting = ref(false)
const editPlant = ref<Plant | null>(null)
const detailPlant = ref<Plant | null>(null)
const selectedCat = ref('')
const searchQuery = ref('')
const plantPhotos = ref<Media[]>([])
@@ -251,6 +485,17 @@ const lightbox = ref<Media | null>(null)
const fileInput = ref<HTMLInputElement | null>(null)
const uploadTarget = ref<Plant | null>(null)
// Navigation variétés
const detailVarieties = ref<Plant[]>([])
const detailVarietyIdx = ref(0)
const detailPlant = computed(() => detailVarieties.value[detailVarietyIdx.value] ?? null)
// Associations au niveau nom_commun (première variété ayant des données)
const detailAssociations = computed(() =>
detailVarieties.value.find(v => v.associations_favorables?.length || v.associations_defavorables?.length)
?? detailPlant.value
)
interface Media {
id: number; entity_type: string; entity_id: number
url: string; thumbnail_url?: string; titre?: string
@@ -265,25 +510,118 @@ const categories = [
{ val: 'adventice', label: '🌾 ADVENTICES' },
]
const BOUTIQUES = [
'Gamm Vert', 'Lidl', 'Super U', 'Intermarché', 'Truffaut', 'Botanic',
'Amazon', 'Graines Baumaux', 'Vilmorin', 'Germinance', 'Direct producteur',
'Marché local', 'Autre',
]
const form = reactive({
nom_commun: '', variete: '', famille: '',
categorie: 'potager', besoin_eau: 'moyen', besoin_soleil: 'plein soleil',
plantation_mois: '', notes: '',
associations_favorables: [] as string[],
associations_defavorables: [] as string[],
boutique_nom: '', boutique_url: '', prix_achat: null as number | null,
date_achat: '', poids: '', dluo: '',
})
const showAssocModal = ref(false)
const assocFilter = ref('')
const confirmRemove = ref<{ type: 'fav' | 'def'; name: string } | null>(null)
// Grouper toutes les plantes par nom_commun (insensible à la casse)
const plantGroups = computed(() => {
const groups = new Map<string, Plant[]>()
for (const p of plantsStore.plants) {
const key = (p.nom_commun || '').toLowerCase()
if (!groups.has(key)) groups.set(key, [])
groups.get(key)!.push(p)
}
return groups
})
function groupSize(nom: string): number {
return plantGroups.value.get(nom.toLowerCase())?.length ?? 1
}
function groupPrimaryCategory(nom: string): string {
const group = plantGroups.value.get(nom.toLowerCase()) || []
return group[0]?.categorie || ''
}
// Une carte par nom_commun unique dans la liste
const filteredPlants = computed(() => {
let source = plantsStore.plants
if (selectedCat.value) source = source.filter(p => p.categorie === selectedCat.value)
const uniqueByName = new Map<string, Plant>()
for (const p of [...plantsStore.plants].sort((a, b) => (a.id || 0) - (b.id || 0))) {
const key = (p.nom_commun || '').toLowerCase()
if (!uniqueByName.has(key)) uniqueByName.set(key, p)
}
let result = [...uniqueByName.values()]
if (selectedCat.value) {
result = result.filter(p => {
const group = plantGroups.value.get((p.nom_commun || '').toLowerCase()) || []
return group.some(v => v.categorie === selectedCat.value)
})
}
if (searchQuery.value) {
const q = searchQuery.value.toLowerCase()
source = source.filter(p =>
p.nom_commun?.toLowerCase().includes(q) ||
p.variete?.toLowerCase().includes(q)
)
result = result.filter(p => {
const group = plantGroups.value.get((p.nom_commun || '').toLowerCase()) || []
return group.some(v =>
v.nom_commun?.toLowerCase().includes(q) || v.variete?.toLowerCase().includes(q)
)
})
}
return [...source].sort((a, b) => (a.nom_commun || '').localeCompare(b.nom_commun || '', 'fr'))
return result.sort((a, b) => (a.nom_commun || '').localeCompare(b.nom_commun || '', 'fr'))
})
// Plantes disponibles pour les associations (nom_commun uniques, hors plante courante)
const filteredAssocPlants = computed(() => {
const q = assocFilter.value.toLowerCase()
const uniqueNames = [...plantGroups.value.keys()]
return uniqueNames
.filter(n => n !== form.nom_commun.toLowerCase() && (!q || n.includes(q)))
.sort()
})
function getAssocState(name: string): 'fav' | 'def' | null {
const lower = name.toLowerCase()
if (form.associations_favorables.some(n => n.toLowerCase() === lower)) return 'fav'
if (form.associations_defavorables.some(n => n.toLowerCase() === lower)) return 'def'
return null
}
function setAssocState(name: string, state: 'fav' | 'def' | null) {
const lower = name.toLowerCase()
form.associations_favorables = form.associations_favorables.filter(n => n.toLowerCase() !== lower)
form.associations_defavorables = form.associations_defavorables.filter(n => n.toLowerCase() !== lower)
if (state === 'fav') form.associations_favorables.push(lower)
else if (state === 'def') form.associations_defavorables.push(lower)
}
function askRemoveAssoc(type: 'fav' | 'def', name: string) {
confirmRemove.value = { type, name }
}
function confirmRemoveAssoc() {
if (!confirmRemove.value) return
const { type, name } = confirmRemove.value
const list = type === 'fav' ? form.associations_favorables : form.associations_defavorables
const lower = name.toLowerCase()
const idx = list.findIndex(n => n.toLowerCase() === lower)
if (idx !== -1) list.splice(idx, 1)
confirmRemove.value = null
}
function isDluoExpired(dluo: string): boolean {
return !!dluo && new Date(dluo) < new Date()
}
function getCatColor(cat: string) {
return ({
potager: '#b8bb26', fleur: '#fabd2f', arbre: '#83a598',
@@ -298,9 +636,32 @@ function catTextClass(cat: string) {
} as any)[cat] || 'text-text-muted'
}
function closeDetail() {
detailVarieties.value = []
detailVarietyIdx.value = 0
plantPhotos.value = []
}
async function openDetails(p: Plant) {
detailPlant.value = p
await fetchPhotos(p.id!)
const key = (p.nom_commun || '').toLowerCase()
const group = plantGroups.value.get(key) || [p]
detailVarieties.value = [...group].sort((a, b) => (a.id || 0) - (b.id || 0))
detailVarietyIdx.value = 0
await fetchPhotos(detailVarieties.value[0].id!)
}
async function prevVariety() {
if (detailVarietyIdx.value > 0) {
detailVarietyIdx.value--
await fetchPhotos(detailPlant.value!.id!)
}
}
async function nextVariety() {
if (detailVarietyIdx.value < detailVarieties.value.length - 1) {
detailVarietyIdx.value++
await fetchPhotos(detailPlant.value!.id!)
}
}
async function fetchPhotos(plantId: number) {
@@ -316,31 +677,64 @@ async function fetchPhotos(plantId: number) {
}
function startEdit(p: Plant) {
detailPlant.value = null
// Chercher les associations dans le groupe (première variété qui en a)
const key = (p.nom_commun || '').toLowerCase()
const group = plantGroups.value.get(key) || [p]
const withAssoc = group.find(v => v.associations_favorables?.length || v.associations_defavorables?.length) ?? p
closeDetail()
editPlant.value = p
Object.assign(form, {
nom_commun: p.nom_commun || '', variete: p.variete || '', famille: p.famille || '',
categorie: p.categorie || 'potager', besoin_eau: p.besoin_eau || 'moyen', besoin_soleil: p.besoin_soleil || 'plein soleil',
plantation_mois: p.plantation_mois || '', notes: p.notes || '',
associations_favorables: [...(withAssoc.associations_favorables ?? [])],
associations_defavorables: [...(withAssoc.associations_defavorables ?? [])],
boutique_nom: p.boutique_nom || '', boutique_url: p.boutique_url || '',
prix_achat: p.prix_achat ?? null, date_achat: p.date_achat || '',
poids: p.poids || '', dluo: p.dluo || '',
})
assocFilter.value = ''
showAssocModal.value = false
showForm.value = true
}
function closeForm() {
showForm.value = false
editPlant.value = null
showAssocModal.value = false
assocFilter.value = ''
confirmRemove.value = null
Object.assign(form, {
boutique_nom: '', boutique_url: '', prix_achat: null,
date_achat: '', poids: '', dluo: '',
})
}
async function submitPlant() {
if (submitting.value) return
submitting.value = true
try {
const payload = { ...form, prix_achat: form.prix_achat ?? undefined }
if (editPlant.value) {
await axios.put(`/api/plants/${editPlant.value.id}`, { ...form })
await axios.put(`/api/plants/${editPlant.value.id}`, payload)
// Synchroniser les associations à toutes les variétés du même nom commun
const nomKey = form.nom_commun.toLowerCase()
const siblings = plantsStore.plants.filter(
p => p.id !== editPlant.value!.id && (p.nom_commun || '').toLowerCase() === nomKey
)
for (const sibling of siblings) {
await axios.put(`/api/plants/${sibling.id}`, {
associations_favorables: form.associations_favorables,
associations_defavorables: form.associations_defavorables,
})
}
await plantsStore.fetchAll()
toast.success('Plante modifiée')
} else {
await plantsStore.create({ ...form })
await plantsStore.create(payload)
toast.success('Plante créée')
}
closeForm()
@@ -355,7 +749,7 @@ async function removePlant(id: number) {
if (!confirm('Supprimer définitivement cette plante ?')) return
try {
await plantsStore.remove(id)
detailPlant.value = null
closeDetail()
toast.success('Plante supprimée')
} catch {
// L'intercepteur Axios affiche le message

File diff suppressed because it is too large Load Diff

View File

@@ -12,10 +12,12 @@ const backupMsg = ref('');
const apiBaseUrl = detectApiBaseUrl();
// --- UI Size settings ---
const uiSizeSettings = [
{ key: 'ui_font_size', label: 'Taille texte', min: 12, max: 20, step: 1, unit: 'px' },
{ key: 'ui_menu_font_size', label: 'Texte menu latéral', min: 11, max: 18, step: 1, unit: 'px' },
{ key: 'ui_menu_icon_size', label: 'Icônes menu', min: 14, max: 28, step: 1, unit: 'px' },
{ key: 'ui_thumb_size', label: 'Miniatures images/vidéo', min: 60, max: 200, step: 4, unit: 'px' },
{ key: 'ui_font_size', label: 'Corps de texte', min: 12, max: 24, step: 1, unit: 'px' },
{ key: 'ui_menu_font_size', label: 'Texte menu latéral', min: 11, max: 20, step: 1, unit: 'px' },
{ key: 'ui_menu_icon_size', label: 'Icônes menu', min: 14, max: 32, step: 1, unit: 'px' },
{ key: 'ui_thumb_size', label: 'Miniatures médias', min: 60, max: 300, step: 4, unit: 'px' },
{ key: 'ui_weather_icon_size', label: 'Icônes Météo', min: 32, max: 128, step: 4, unit: 'px' },
{ key: 'ui_dashboard_icon_size', label: 'Icônes Dashboard', min: 16, max: 64, step: 2, unit: 'px' },
];
const uiSizes = ref({ ...UI_SIZE_DEFAULTS });
const savingUi = ref(false);
@@ -67,15 +69,9 @@ function openInNewTab(path) {
const url = `${apiBaseUrl}${path}`;
window.open(url, '_blank', 'noopener,noreferrer');
}
function openApiDocs() {
openInNewTab('/docs');
}
function openApiRedoc() {
openInNewTab('/redoc');
}
function openApiHealth() {
openInNewTab('/api/health');
}
function openApiDocs() { openInNewTab('/docs'); }
function openApiRedoc() { openInNewTab('/redoc'); }
function openApiHealth() { openInNewTab('/api/health'); }
function toBool(value) {
if (typeof value === 'boolean')
return value;
@@ -99,7 +95,7 @@ async function loadSettings() {
applyUiSizes();
}
catch {
// Laisse la valeur locale si l'API n'est pas disponible.
// Laisse la valeur locale
}
}
async function saveSettings() {
@@ -108,7 +104,7 @@ async function saveSettings() {
try {
await settingsApi.update({ debug_mode: debugMode.value ? '1' : '0' });
notifyDebugChanged(debugMode.value);
savedMsg.value = 'Enregistré';
savedMsg.value = 'Pris en compte';
window.setTimeout(() => { savedMsg.value = ''; }, 1800);
}
finally {
@@ -137,10 +133,10 @@ async function downloadBackup() {
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
backupMsg.value = 'Téléchargement lancé.';
backupMsg.value = 'ZIP prêt !';
}
catch {
backupMsg.value = 'Erreur lors de la sauvegarde.';
backupMsg.value = 'Erreur export.';
}
finally {
downloadingBackup.value = false;
@@ -155,342 +151,622 @@ const __VLS_ctx = {};
let __VLS_components;
let __VLS_directives;
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "p-4 max-w-3xl mx-auto" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-2xl font-bold text-green mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "bg-bg-soft border border-bg-hard rounded-xl p-4 mb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-semibold mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm mb-4" },
...{ class: "p-4 max-w-[1800px] mx-auto space-y-8" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-1 gap-4" },
...{ class: "flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h1, __VLS_intrinsicElements.h1)({
...{ class: "text-3xl font-bold text-green tracking-tight" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 2xl:grid-cols-4 gap-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "card-jardin flex flex-col h-full border-green/20" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mb-6 border-b border-bg-hard pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-bold uppercase tracking-widest text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-[10px] text-text-muted font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1 space-y-6" },
});
for (const [s] of __VLS_getVForSourceType((__VLS_ctx.uiSizeSettings))) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
key: (s.key),
...{ class: "flex items-center gap-3" },
...{ class: "space-y-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex justify-between items-center" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "text-sm text-text w-44 shrink-0" },
...{ class: "text-[10px] font-black uppercase tracking-widest text-text-muted" },
});
(s.label);
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs font-mono text-green" },
});
(__VLS_ctx.uiSizes[s.key]);
(s.unit);
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
...{ onInput: (__VLS_ctx.applyUiSizes) },
type: "range",
min: (s.min),
max: (s.max),
step: (s.step),
...{ class: "flex-1 accent-green" },
...{ class: "w-full h-1.5 bg-bg-hard rounded-lg appearance-none cursor-pointer accent-green" },
});
(__VLS_ctx.uiSizes[s.key]);
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text-muted text-xs w-12 text-right" },
});
(__VLS_ctx.uiSizes[s.key]);
(s.unit);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-4 flex items-center gap-2" },
...{ class: "mt-8 pt-4 border-t border-bg-hard flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.saveUiSettings) },
...{ class: "bg-green text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
disabled: (__VLS_ctx.savingUi),
});
(__VLS_ctx.savingUi ? 'Enregistrement...' : 'Enregistrer');
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.resetUiSettings) },
...{ class: "text-text-muted text-xs hover:text-text px-2" },
...{ class: "text-[10px] font-black uppercase tracking-widest text-text-muted hover:text-text transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3" },
});
if (__VLS_ctx.uiSavedMsg) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs text-aqua" },
...{ class: "text-[10px] font-bold text-aqua animate-pulse" },
});
(__VLS_ctx.uiSavedMsg);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "bg-bg-soft border border-bg-hard rounded-xl p-4 mb-4" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.saveUiSettings) },
...{ class: "btn-primary !py-2 !px-6 text-xs" },
disabled: (__VLS_ctx.savingUi),
});
(__VLS_ctx.savingUi ? '...' : 'Enregistrer');
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "card-jardin flex flex-col h-full border-yellow/20" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mb-6 border-b border-bg-hard pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-semibold mb-2" },
...{ class: "text-text font-bold uppercase tracking-widest text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm mb-3" },
...{ class: "text-[10px] text-text-muted font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1 space-y-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.label, __VLS_intrinsicElements.label)({
...{ class: "inline-flex items-center gap-2 text-sm text-text" },
...{ class: "flex items-start gap-4 cursor-pointer group bg-bg-hard/30 p-4 rounded-2xl border border-bg-soft/50 hover:border-yellow/30 transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "relative mt-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.input)({
type: "checkbox",
...{ class: "accent-green" },
...{ class: "sr-only peer" },
});
(__VLS_ctx.debugMode);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-3 flex items-center gap-2" },
...{ class: "w-10 h-5 bg-bg-hard rounded-full peer peer-checked:bg-yellow transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.saveSettings) },
...{ class: "bg-green text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
disabled: (__VLS_ctx.saving),
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "absolute left-1 top-1 w-3 h-3 bg-text-muted peer-checked:bg-bg peer-checked:translate-x-5 rounded-full transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-sm font-bold text-text group-hover:text-yellow transition-colors" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-[10px] text-text-muted mt-1 leading-relaxed italic" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-8 pt-4 border-t border-bg-hard flex items-center justify-end gap-3" },
});
(__VLS_ctx.saving ? 'Enregistrement...' : 'Enregistrer');
if (__VLS_ctx.savedMsg) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs text-aqua" },
...{ class: "text-[10px] font-bold text-aqua" },
});
(__VLS_ctx.savedMsg);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "bg-bg-soft border border-bg-hard rounded-xl p-4 mb-4" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.saveSettings) },
...{ class: "btn-primary !bg-yellow !text-bg !py-2 !px-6 text-xs" },
disabled: (__VLS_ctx.saving),
});
(__VLS_ctx.saving ? '...' : 'Appliquer');
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "card-jardin flex flex-col h-full border-blue/20" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mb-6 border-b border-bg-hard pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-semibold mb-2" },
...{ class: "text-text font-bold uppercase tracking-widest text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm mb-3" },
...{ class: "text-[10px] text-text-muted font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex-1" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-xs text-text-muted leading-relaxed mb-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.refreshMeteo) },
...{ class: "bg-blue text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
...{ class: "btn-outline w-full py-4 border-blue/20 text-blue hover:bg-blue/10 flex flex-col items-center gap-2" },
disabled: (__VLS_ctx.refreshingMeteo),
});
(__VLS_ctx.refreshingMeteo ? 'Rafraîchissement...' : 'Rafraîchir maintenant');
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-lg" },
});
(__VLS_ctx.refreshingMeteo ? '🔄' : '⚡');
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] font-black uppercase tracking-widest" },
});
(__VLS_ctx.refreshingMeteo ? 'Rafraîchissement en cours...' : 'Forcer la mise à jour');
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "bg-bg-soft border border-bg-hard rounded-xl p-4 mb-4" },
...{ class: "card-jardin flex flex-col h-full border-aqua/20" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-semibold mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm mb-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-xs mb-3" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mb-6 border-b border-bg-hard pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-text" },
});
(__VLS_ctx.apiBaseUrl);
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex flex-wrap items-center gap-2" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiDocs) },
...{ class: "bg-blue text-bg px-3 py-2 rounded-lg text-xs font-semibold hover:opacity-90" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiRedoc) },
...{ class: "bg-aqua text-bg px-3 py-2 rounded-lg text-xs font-semibold hover:opacity-90" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiHealth) },
...{ class: "bg-bg border border-bg-hard text-text px-3 py-2 rounded-lg text-xs font-semibold hover:border-text-muted" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "bg-bg-soft border border-bg-hard rounded-xl p-4" },
...{ class: "text-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-semibold mb-2" },
...{ class: "text-text font-bold uppercase tracking-widest text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-text-muted text-sm mb-3" },
...{ class: "text-[10px] text-text-muted font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-2" },
...{ class: "flex-1 space-y-6" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-xs text-text-muted leading-relaxed" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.downloadBackup) },
...{ class: "bg-aqua text-bg px-4 py-2 rounded-lg text-sm font-semibold hover:opacity-90" },
...{ class: "btn-primary !bg-aqua !text-bg w-full py-4 flex flex-col items-center gap-2 shadow-lg hover:shadow-aqua/20" },
disabled: (__VLS_ctx.downloadingBackup),
});
(__VLS_ctx.downloadingBackup ? 'Préparation du ZIP...' : 'Télécharger la sauvegarde (.zip)');
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] font-black uppercase tracking-widest" },
});
(__VLS_ctx.downloadingBackup ? 'Préparation...' : 'Télécharger le Pack Complet');
if (__VLS_ctx.backupMsg) {
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs text-aqua" },
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "text-[10px] text-center font-bold text-aqua animate-bounce" },
});
(__VLS_ctx.backupMsg);
}
__VLS_asFunctionalElement(__VLS_intrinsicElements.section, __VLS_intrinsicElements.section)({
...{ class: "card-jardin xl:col-span-2 flex flex-col border-bg-soft/50" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "flex items-center gap-3 mb-6 border-b border-bg-hard pb-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-2xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({});
__VLS_asFunctionalElement(__VLS_intrinsicElements.h2, __VLS_intrinsicElements.h2)({
...{ class: "text-text font-bold uppercase tracking-widest text-xs" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.p, __VLS_intrinsicElements.p)({
...{ class: "text-[10px] text-text-muted font-bold" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "grid grid-cols-1 sm:grid-cols-3 gap-4" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiDocs) },
...{ class: "btn-outline flex flex-col items-center gap-2 py-6 border-bg-soft hover:bg-bg-hard transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] font-bold uppercase" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiRedoc) },
...{ class: "btn-outline flex flex-col items-center gap-2 py-6 border-bg-soft hover:bg-bg-hard transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] font-bold uppercase" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.button, __VLS_intrinsicElements.button)({
...{ onClick: (__VLS_ctx.openApiHealth) },
...{ class: "btn-outline flex flex-col items-center gap-2 py-6 border-bg-soft hover:bg-bg-hard transition-all" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xl" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[10px] font-bold uppercase" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.div, __VLS_intrinsicElements.div)({
...{ class: "mt-6 p-3 bg-bg-hard/50 rounded-xl border border-bg-soft/30 flex items-center justify-between" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-[9px] font-bold text-text-muted uppercase tracking-widest" },
});
__VLS_asFunctionalElement(__VLS_intrinsicElements.span, __VLS_intrinsicElements.span)({
...{ class: "text-xs font-mono text-aqua" },
});
(__VLS_ctx.apiBaseUrl);
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['max-w-[1800px]']} */ ;
/** @type {__VLS_StyleScopedClasses['mx-auto']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-8']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-3xl']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-tight']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['md:grid-cols-2']} */ ;
/** @type {__VLS_StyleScopedClasses['xl:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['2xl:grid-cols-4']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-6']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border-green/20']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['w-44']} */ ;
/** @type {__VLS_StyleScopedClasses['shrink-0']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['accent-green']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-6']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['w-12']} */ ;
/** @type {__VLS_StyleScopedClasses['text-right']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['font-mono']} */ ;
/** @type {__VLS_StyleScopedClasses['text-green']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['h-1.5']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['appearance-none']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['accent-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-8']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['px-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['inline-flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['accent-green']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-3']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-pulse']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['!px-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border-yellow/20']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-green']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-6']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-start']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['cursor-pointer']} */ ;
/** @type {__VLS_StyleScopedClasses['group']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard/30']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft/50']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-yellow/30']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['relative']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['sr-only']} */ ;
/** @type {__VLS_StyleScopedClasses['peer']} */ ;
/** @type {__VLS_StyleScopedClasses['w-10']} */ ;
/** @type {__VLS_StyleScopedClasses['h-5']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['peer']} */ ;
/** @type {__VLS_StyleScopedClasses['peer-checked:bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['absolute']} */ ;
/** @type {__VLS_StyleScopedClasses['left-1']} */ ;
/** @type {__VLS_StyleScopedClasses['top-1']} */ ;
/** @type {__VLS_StyleScopedClasses['w-3']} */ ;
/** @type {__VLS_StyleScopedClasses['h-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['peer-checked:bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['peer-checked:translate-x-5']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-full']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['group-hover:text-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-colors']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-1']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-relaxed']} */ ;
/** @type {__VLS_StyleScopedClasses['italic']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-8']} */ ;
/** @type {__VLS_StyleScopedClasses['pt-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-t']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-end']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!bg-yellow']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['!py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['!px-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-wrap']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['px-3']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:border-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['p-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-3']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border-blue/20']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['px-4']} */ ;
/** @type {__VLS_StyleScopedClasses['py-2']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-sm']} */ ;
/** @type {__VLS_StyleScopedClasses['font-semibold']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:opacity-90']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-relaxed']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['py-4']} */ ;
/** @type {__VLS_StyleScopedClasses['border-blue/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-blue']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-blue/10']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['text-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['h-full']} */ ;
/** @type {__VLS_StyleScopedClasses['border-aqua/20']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-1']} */ ;
/** @type {__VLS_StyleScopedClasses['space-y-6']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['leading-relaxed']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-primary']} */ ;
/** @type {__VLS_StyleScopedClasses['!bg-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['!text-bg']} */ ;
/** @type {__VLS_StyleScopedClasses['w-full']} */ ;
/** @type {__VLS_StyleScopedClasses['py-4']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['shadow-lg']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:shadow-aqua/20']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-black']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-center']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
/** @type {__VLS_StyleScopedClasses['animate-bounce']} */ ;
/** @type {__VLS_StyleScopedClasses['card-jardin']} */ ;
/** @type {__VLS_StyleScopedClasses['xl:col-span-2']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft/50']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-3']} */ ;
/** @type {__VLS_StyleScopedClasses['mb-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-b']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['pb-4']} */ ;
/** @type {__VLS_StyleScopedClasses['text-2xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['grid']} */ ;
/** @type {__VLS_StyleScopedClasses['grid-cols-1']} */ ;
/** @type {__VLS_StyleScopedClasses['sm:grid-cols-3']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-4']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['btn-outline']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['flex-col']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['gap-2']} */ ;
/** @type {__VLS_StyleScopedClasses['py-6']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft']} */ ;
/** @type {__VLS_StyleScopedClasses['hover:bg-bg-hard']} */ ;
/** @type {__VLS_StyleScopedClasses['transition-all']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[10px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['mt-6']} */ ;
/** @type {__VLS_StyleScopedClasses['p-3']} */ ;
/** @type {__VLS_StyleScopedClasses['bg-bg-hard/50']} */ ;
/** @type {__VLS_StyleScopedClasses['rounded-xl']} */ ;
/** @type {__VLS_StyleScopedClasses['border']} */ ;
/** @type {__VLS_StyleScopedClasses['border-bg-soft/30']} */ ;
/** @type {__VLS_StyleScopedClasses['flex']} */ ;
/** @type {__VLS_StyleScopedClasses['items-center']} */ ;
/** @type {__VLS_StyleScopedClasses['justify-between']} */ ;
/** @type {__VLS_StyleScopedClasses['text-[9px]']} */ ;
/** @type {__VLS_StyleScopedClasses['font-bold']} */ ;
/** @type {__VLS_StyleScopedClasses['text-text-muted']} */ ;
/** @type {__VLS_StyleScopedClasses['uppercase']} */ ;
/** @type {__VLS_StyleScopedClasses['tracking-widest']} */ ;
/** @type {__VLS_StyleScopedClasses['text-xs']} */ ;
/** @type {__VLS_StyleScopedClasses['font-mono']} */ ;
/** @type {__VLS_StyleScopedClasses['text-aqua']} */ ;
var __VLS_dollars;
const __VLS_self = (await import('vue')).defineComponent({

File diff suppressed because it is too large Load Diff