Remplace l'exemple "pompe avec position sur la machine" par un palier de tete vs palier de pied : exemple plus concret et plus universellement compris pour illustrer la difference entre champs catalogue et champs contextuels (custom field values).
1003 lines
60 KiB
Vue
1003 lines
60 KiB
Vue
<template>
|
|
<main class="min-h-screen bg-gradient-to-br from-base-200/50 via-base-100 to-base-200/30">
|
|
<div class="container mx-auto max-w-7xl px-4 py-10">
|
|
<!-- Mobile TOC toggle -->
|
|
<div class="lg:hidden mb-6">
|
|
<button
|
|
class="btn btn-outline btn-sm gap-2 w-full justify-between"
|
|
@click="mobileMenuOpen = !mobileMenuOpen"
|
|
>
|
|
<span class="flex items-center gap-2">
|
|
<IconLucideBookOpen class="w-4 h-4" />
|
|
Sommaire
|
|
</span>
|
|
<IconLucideChevronDown
|
|
class="w-4 h-4 transition-transform duration-300"
|
|
:class="{ 'rotate-180': mobileMenuOpen }"
|
|
/>
|
|
</button>
|
|
<Transition name="slide">
|
|
<nav
|
|
v-show="mobileMenuOpen"
|
|
class="mt-2 card bg-base-100 border border-base-300 shadow-lg"
|
|
>
|
|
<ul class="menu menu-sm p-3">
|
|
<li v-for="section in sections" :key="section.id">
|
|
<a
|
|
:href="`#${section.id}`"
|
|
class="flex items-center gap-2 rounded-lg"
|
|
:class="activeSection === section.id
|
|
? 'bg-primary text-primary-content font-semibold'
|
|
: 'text-base-content/70 hover:bg-base-200'"
|
|
@click.prevent="scrollTo(section.id)"
|
|
>
|
|
<component :is="section.icon" class="w-4 h-4 shrink-0" />
|
|
{{ section.label }}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</Transition>
|
|
</div>
|
|
|
|
<div class="flex gap-10">
|
|
<!-- Sidebar desktop -->
|
|
<aside class="hidden lg:block w-60 shrink-0">
|
|
<nav class="sticky top-20 max-h-[calc(100vh-6rem)] overflow-y-auto">
|
|
<p class="text-[10px] font-bold uppercase tracking-[0.2em] text-base-content/30 mb-4 px-3">
|
|
Guide
|
|
</p>
|
|
<ul class="space-y-0.5">
|
|
<li v-for="section in sections" :key="section.id">
|
|
<a
|
|
:href="`#${section.id}`"
|
|
class="flex items-center gap-2.5 px-3 py-2 rounded-lg text-sm transition-all duration-200"
|
|
:class="activeSection === section.id
|
|
? 'bg-primary text-primary-content font-semibold shadow-sm'
|
|
: 'text-base-content/60 hover:text-base-content hover:bg-base-200/60'"
|
|
@click.prevent="scrollTo(section.id)"
|
|
>
|
|
<component :is="section.icon" class="w-4 h-4 shrink-0" />
|
|
{{ section.label }}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
</aside>
|
|
|
|
<!-- Contenu principal -->
|
|
<div class="flex-1 min-w-0 space-y-20">
|
|
<!-- En-tete -->
|
|
<header>
|
|
<div class="flex items-center gap-4 mb-3">
|
|
<div class="w-14 h-14 rounded-2xl bg-primary/10 flex items-center justify-center">
|
|
<IconLucideBookOpen class="w-7 h-7 text-primary" />
|
|
</div>
|
|
<div>
|
|
<h1 class="text-3xl font-extrabold text-base-content tracking-tight">Guide d'utilisation</h1>
|
|
<p class="text-base-content/40 text-sm mt-1">Tout ce qu'il faut savoir pour utiliser Inventory</p>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- ==================== 1. COMMENT C'EST ORGANISE ==================== -->
|
|
<section id="organisation" :ref="el => setSectionRef('organisation', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideNetwork" color="primary">
|
|
Comment c'est organise ?
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
L'application range vos equipements comme des poupees russes : chaque niveau contient le suivant.
|
|
Voici les 5 niveaux, du plus grand au plus petit :
|
|
</p>
|
|
|
|
<!-- Arbre visuel simplifie -->
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm mb-8 overflow-hidden">
|
|
<div class="card-body p-6">
|
|
<div class="space-y-0">
|
|
<!-- Site -->
|
|
<div class="flex items-center gap-4">
|
|
<div class="w-11 h-11 rounded-xl bg-primary/15 flex items-center justify-center shrink-0">
|
|
<IconLucideFactory class="w-5 h-5 text-primary" />
|
|
</div>
|
|
<div>
|
|
<span class="font-bold text-base-content">Le site</span>
|
|
<span class="text-base-content/50"> — votre usine, votre atelier, votre entrepot</span>
|
|
</div>
|
|
</div>
|
|
<div class="ml-5 border-l-2 border-primary/20 h-4"></div>
|
|
|
|
<!-- Machine -->
|
|
<div class="flex items-center gap-4 ml-8">
|
|
<div class="w-11 h-11 rounded-xl bg-secondary/15 flex items-center justify-center shrink-0">
|
|
<IconLucideCog class="w-5 h-5 text-secondary" />
|
|
</div>
|
|
<div>
|
|
<span class="font-bold text-base-content">La machine</span>
|
|
<span class="text-base-content/50"> — la presse, le tour, la ligne de production</span>
|
|
</div>
|
|
</div>
|
|
<div class="ml-13 border-l-2 border-secondary/20 h-4"></div>
|
|
|
|
<!-- Composant -->
|
|
<div class="flex items-center gap-4 ml-16">
|
|
<div class="w-11 h-11 rounded-xl bg-accent/15 flex items-center justify-center shrink-0">
|
|
<IconLucideBoxes class="w-5 h-5 text-accent" />
|
|
</div>
|
|
<div>
|
|
<span class="font-bold text-base-content">Le composant</span>
|
|
<span class="text-base-content/50"> — le moteur, la pompe, le tableau electrique</span>
|
|
</div>
|
|
</div>
|
|
<div class="ml-21 border-l-2 border-accent/20 h-4"></div>
|
|
|
|
<!-- Piece & Produit -->
|
|
<div class="ml-24 grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-11 h-11 rounded-xl bg-warning/15 flex items-center justify-center shrink-0">
|
|
<IconLucideWrench class="w-5 h-5 text-warning" />
|
|
</div>
|
|
<div>
|
|
<span class="font-bold text-base-content">La piece</span>
|
|
<p class="text-xs text-base-content/50">Joint, roulement, courroie...</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-3">
|
|
<div class="w-11 h-11 rounded-xl bg-success/15 flex items-center justify-center shrink-0">
|
|
<IconLucideDroplets class="w-5 h-5 text-success" />
|
|
</div>
|
|
<div>
|
|
<span class="font-bold text-base-content">Le produit</span>
|
|
<p class="text-xs text-base-content/50">Huile, graisse, liquide...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Piece vs Produit -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Quelle difference entre une piece et un produit ?</h3>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
|
<div class="card bg-warning/5 border border-warning/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideWrench class="w-5 h-5 text-warning" />
|
|
<h4 class="font-bold text-base-content">Une piece</h4>
|
|
</div>
|
|
<p class="text-sm text-base-content/70">
|
|
C'est quelque chose qu'on <strong>monte</strong> physiquement sur la machine
|
|
et qu'on <strong>remplace</strong> quand c'est use. Un joint, un roulement, un capteur.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-success/5 border border-success/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideDroplets class="w-5 h-5 text-success" />
|
|
<h4 class="font-bold text-base-content">Un produit</h4>
|
|
</div>
|
|
<p class="text-sm text-base-content/70">
|
|
C'est quelque chose qu'on <strong>consomme</strong> et qu'on
|
|
<strong>rachete regulierement</strong>. De l'huile, de la graisse, un degraissant.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert shadow-sm mb-4">
|
|
<IconLucideInfo class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Bon a savoir :</strong> un composant peut contenir d'autres composants a l'interieur.
|
|
Par exemple, un moteur peut contenir un reducteur, qui lui-meme contient des roulements.
|
|
C'est comme des boites dans des boites.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 2. CREER UNE MACHINE ==================== -->
|
|
<section id="machines" :ref="el => setSectionRef('machines', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideCog" color="secondary">
|
|
Creer une machine
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
Pour ajouter une nouvelle machine dans l'application, suivez ces etapes :
|
|
</p>
|
|
|
|
<div class="space-y-4 mb-8">
|
|
<StepCard n="1" title="Choisissez le site">
|
|
Dans quel batiment ou atelier se trouve la machine ?
|
|
Selectionnez-le dans la liste.
|
|
</StepCard>
|
|
<StepCard n="2" title="Remplissez la fiche">
|
|
Donnez un nom a la machine, sa reference, son prix si vous le connaissez,
|
|
et le(s) fournisseur(s) qui l'ont fournie.
|
|
</StepCard>
|
|
<StepCard n="3" title="Ajoutez les composants">
|
|
Quels sont les gros elements de cette machine ? Un moteur, une pompe, un variateur ?
|
|
Ajoutez-les un par un. (Voir la section suivante.)
|
|
</StepCard>
|
|
<StepCard n="4" title="Ajoutez les pieces et produits">
|
|
Certaines pieces ou produits sont lies directement a la machine
|
|
(pas a un composant en particulier). Ajoutez-les ici.
|
|
</StepCard>
|
|
<StepCard n="5" title="Completez avec documents et infos supplementaires">
|
|
Joignez des photos, plans, factures, et remplissez les informations supplementaires
|
|
propres a cette machine (voir section Champs personnalises).
|
|
</StepCard>
|
|
</div>
|
|
|
|
<div class="alert shadow-sm mb-2">
|
|
<IconLucideCopy class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Astuce :</strong> si vous avez plusieurs machines identiques,
|
|
utilisez le bouton <strong>"Cloner"</strong> pour dupliquer une machine existante
|
|
avec tout son contenu. Il ne reste plus qu'a ajuster les details.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 3. LES COMPOSANTS ==================== -->
|
|
<section id="composants" :ref="el => setSectionRef('composants', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideBoxes" color="accent">
|
|
Les composants d'une machine
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
Un composant, c'est un <strong>gros morceau</strong> de votre machine : le moteur,
|
|
la pompe, le tableau electrique, le verin... Chaque composant a besoin de pieces
|
|
et de produits pour fonctionner.
|
|
</p>
|
|
|
|
<!-- Explication emplacements -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Le systeme d'emplacements</h3>
|
|
<p class="text-base-content/70 mb-4 text-sm leading-relaxed">
|
|
Quand vous ajoutez un composant a une machine, l'application cree automatiquement
|
|
des <strong>emplacements vides</strong> a remplir. C'est comme un formulaire pre-fait :
|
|
il vous indique tout ce qu'il faut pour que le composant soit complet.
|
|
</p>
|
|
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm mb-6">
|
|
<div class="card-body p-5">
|
|
<p class="text-xs font-bold uppercase tracking-wider text-base-content/30 mb-4">Exemple : vous ajoutez une pompe hydraulique</p>
|
|
<div class="space-y-3">
|
|
<div class="flex items-center gap-3 bg-warning/5 rounded-lg px-4 py-3 border border-warning/10">
|
|
<IconLucideWrench class="w-5 h-5 text-warning shrink-0" />
|
|
<div>
|
|
<p class="font-semibold text-sm">Emplacement piece : "Joint principal"</p>
|
|
<p class="text-xs text-base-content/50">A remplir avec le joint que vous utilisez vraiment</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-3 bg-warning/5 rounded-lg px-4 py-3 border border-warning/10">
|
|
<IconLucideWrench class="w-5 h-5 text-warning shrink-0" />
|
|
<div>
|
|
<p class="font-semibold text-sm">Emplacement piece : "Roulement"</p>
|
|
<p class="text-xs text-base-content/50">A remplir avec le roulement en place</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-3 bg-success/5 rounded-lg px-4 py-3 border border-success/10">
|
|
<IconLucideDroplets class="w-5 h-5 text-success shrink-0" />
|
|
<div>
|
|
<p class="font-semibold text-sm">Emplacement produit : "Huile hydraulique"</p>
|
|
<p class="text-xs text-base-content/50">A remplir avec l'huile utilisee</p>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-3 bg-accent/5 rounded-lg px-4 py-3 border border-accent/10">
|
|
<IconLucideBoxes class="w-5 h-5 text-accent shrink-0" />
|
|
<div>
|
|
<p class="font-semibold text-sm">Emplacement composant : "Moteur electrique"</p>
|
|
<p class="text-xs text-base-content/50">Un composant dans un composant (comme des poupees russes)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert shadow-sm mb-2">
|
|
<IconLucideInfo class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Pas de panique :</strong> un emplacement peut rester vide. Vous n'etes pas oblige
|
|
de tout remplir d'un coup. Completez au fur et a mesure, a votre rythme.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 4. PIECES ET PRODUITS ==================== -->
|
|
<section id="pieces-produits" :ref="el => setSectionRef('pieces-produits', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideWrench" color="warning">
|
|
Pieces et produits
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
Les pieces et les produits sont les elements les plus "petits" de l'application.
|
|
Ils peuvent etre rattaches a un composant (via un emplacement) ou directement a une machine.
|
|
</p>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-8">
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-5">
|
|
<h4 class="font-bold text-base-content flex items-center gap-2 mb-3">
|
|
<span class="badge badge-warning">Piece</span>
|
|
Creer une piece
|
|
</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Donnez-lui un nom, une reference, choisissez son modele type
|
|
(voir section suivante), indiquez la quantite et le fournisseur.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-5">
|
|
<h4 class="font-bold text-base-content flex items-center gap-2 mb-3">
|
|
<span class="badge badge-success">Produit</span>
|
|
Creer un produit
|
|
</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Meme chose : un nom, une reference, un modele type, et le fournisseur.
|
|
Les produits n'ont pas de quantite (c'est du consommable).
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert shadow-sm mb-2">
|
|
<IconLucideDroplets class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Bon a savoir :</strong> une piece peut elle-meme avoir besoin de produits.
|
|
Par exemple, un roulement a besoin de graisse. L'application gere ca automatiquement
|
|
si c'est prevu dans le modele type de la piece.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 5. MODELES TYPES ==================== -->
|
|
<section id="modeles-types" :ref="el => setSectionRef('modeles-types', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideLayoutTemplate" color="primary">
|
|
Les modeles types
|
|
</SectionTitle>
|
|
|
|
<!-- Analogie simple -->
|
|
<div class="card bg-primary/5 border border-primary/20 mb-8">
|
|
<div class="card-body p-6">
|
|
<h3 class="font-bold text-base-content text-lg mb-3 flex items-center gap-2">
|
|
<IconLucideLightbulb class="w-5 h-5 text-primary" />
|
|
C'est quoi ?
|
|
</h3>
|
|
<p class="text-base-content/70 leading-relaxed mb-4">
|
|
Imaginez un <strong>bon de commande type</strong> : il liste tout ce qu'il faut pour un
|
|
equipement donne. Un modele type, c'est exactement pareil. Vous le creez une seule fois,
|
|
et ensuite chaque fois que vous ajoutez un equipement de ce type, la liste est deja pre-remplie.
|
|
</p>
|
|
<p class="text-base-content/70 leading-relaxed">
|
|
<strong>Exemple :</strong> vous creez un modele type "Pompe hydraulique" qui dit :
|
|
"il faut 2 joints, 1 roulement, et de l'huile hydraulique". A chaque nouvelle pompe,
|
|
ces emplacements sont crees automatiquement. Plus besoin de tout refaire a la main.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 3 familles -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Il existe 3 familles de modeles</h3>
|
|
<p class="text-base-content/70 mb-4 text-sm">
|
|
Un modele type s'applique a une seule famille d'element :
|
|
</p>
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
|
<div class="card bg-accent/5 border border-accent/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideBoxes class="w-5 h-5 text-accent" />
|
|
<span class="font-bold text-base-content">Pour les composants</span>
|
|
</div>
|
|
<p class="text-sm text-base-content/60">
|
|
Peut prevoir des emplacements pour des pieces, des produits,
|
|
et meme d'autres composants a l'interieur.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-warning/5 border border-warning/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideWrench class="w-5 h-5 text-warning" />
|
|
<span class="font-bold text-base-content">Pour les pieces</span>
|
|
</div>
|
|
<p class="text-sm text-base-content/60">
|
|
Peut prevoir des emplacements pour des produits.
|
|
Par exemple : un roulement qui a besoin de graisse.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-success/5 border border-success/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideDroplets class="w-5 h-5 text-success" />
|
|
<span class="font-bold text-base-content">Pour les produits</span>
|
|
</div>
|
|
<p class="text-sm text-base-content/60">
|
|
Pas d'emplacements prevus. Un produit est un consommable simple,
|
|
il ne contient rien d'autre.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Reference automatique -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">
|
|
<IconLucideHash class="w-5 h-5 inline text-base-content/50 mr-1" />
|
|
Reference automatique
|
|
</h3>
|
|
<p class="text-base-content/70 mb-4 text-sm leading-relaxed">
|
|
Pour les modeles de composants et de pieces, vous pouvez definir une
|
|
<strong>formule de reference</strong> qui genere automatiquement un code unique
|
|
pour chaque element, a partir de ses informations.
|
|
</p>
|
|
<div class="card bg-base-200/50 border border-base-300 shadow-sm mb-8">
|
|
<div class="card-body p-5">
|
|
<div class="flex flex-col sm:flex-row items-start sm:items-center gap-4">
|
|
<div>
|
|
<p class="text-xs text-base-content/40 mb-1">Formule :</p>
|
|
<code class="bg-base-300/50 px-3 py-1.5 rounded-lg text-sm font-mono text-primary">
|
|
{site}-{type}-{numero}
|
|
</code>
|
|
</div>
|
|
<IconLucideArrowRight class="w-5 h-5 text-base-content/20 shrink-0 hidden sm:block" />
|
|
<div>
|
|
<p class="text-xs text-base-content/40 mb-1">Resultat :</p>
|
|
<code class="bg-primary/10 px-3 py-1.5 rounded-lg text-sm font-mono text-primary font-bold">
|
|
LYON-POMPE-001
|
|
</code>
|
|
</div>
|
|
</div>
|
|
<p class="text-xs text-base-content/40 mt-3">
|
|
La reference se met a jour automatiquement quand les informations changent.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Synchronisation -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">
|
|
<IconLucideRefreshCw class="w-5 h-5 inline text-base-content/50 mr-1" />
|
|
Mettre a jour les elements existants
|
|
</h3>
|
|
<p class="text-base-content/70 mb-4 text-sm leading-relaxed">
|
|
Vous avez modifie un modele type (par exemple, ajoute un emplacement "filtre"
|
|
a votre modele de pompe) et vous voulez que <strong>toutes les pompes deja creees</strong>
|
|
recoivent aussi ce nouvel emplacement ? C'est possible grace a la synchronisation :
|
|
</p>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm mb-4">
|
|
<div class="card-body p-5">
|
|
<ul class="steps steps-horizontal w-full text-xs sm:text-sm">
|
|
<li class="step step-primary">Modifier le modele</li>
|
|
<li class="step step-primary">Voir l'apercu</li>
|
|
<li class="step step-primary">Confirmer</li>
|
|
<li class="step step-primary">C'est fait !</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="alert shadow-sm mb-2">
|
|
<IconLucideLightbulb class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Astuce :</strong> cette fonction est surtout utile au debut, quand vous etes
|
|
en train de configurer l'application et que les modeles evoluent souvent.
|
|
Un apercu est toujours affiche avant d'appliquer les changements.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 6. FOURNISSEURS ==================== -->
|
|
<section id="fournisseurs" :ref="el => setSectionRef('fournisseurs', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideTruck" color="primary">
|
|
Fournisseurs
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
Vous pouvez enregistrer vos fournisseurs dans l'application et les associer a
|
|
n'importe quel element : machine, composant, piece ou produit.
|
|
</p>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-5 mb-6">
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-5">
|
|
<h4 class="font-bold text-base-content flex items-center gap-2 mb-2">
|
|
<IconLucidePlus class="w-4 h-4 text-primary" />
|
|
Creer un fournisseur
|
|
</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Allez dans Administration > Fournisseurs et ajoutez le nom
|
|
et les coordonnees de votre fournisseur.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-5">
|
|
<h4 class="font-bold text-base-content flex items-center gap-2 mb-2">
|
|
<IconLucideLink class="w-4 h-4 text-primary" />
|
|
Associer a un element
|
|
</h4>
|
|
<p class="text-sm text-base-content/70">
|
|
Sur la fiche de n'importe quel element, vous pouvez ajouter un ou
|
|
plusieurs fournisseurs avec leur reference propre.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert shadow-sm mb-2">
|
|
<IconLucideInfo class="w-5 h-5 shrink-0 text-info" />
|
|
<p class="text-sm">
|
|
<strong>Reference fournisseur :</strong> chaque fournisseur peut avoir sa propre reference
|
|
pour le meme produit. Par exemple, un roulement SKF peut avoir la reference "6205-2Z"
|
|
chez un fournisseur et "SKF-6205-ZZ" chez un autre.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ==================== 7. DOCUMENTS ==================== -->
|
|
<section id="documents" :ref="el => setSectionRef('documents', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideFileText" color="primary">
|
|
Documents
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
Vous pouvez joindre des fichiers (PDF, images, etc.) a n'importe quel element de
|
|
l'application. Chaque document a un type pour faciliter le tri :
|
|
</p>
|
|
|
|
<div class="flex flex-wrap gap-2 mb-8">
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideBook class="w-4 h-4" />
|
|
Documentation
|
|
</span>
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideFileSpreadsheet class="w-4 h-4" />
|
|
Devis
|
|
</span>
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideReceipt class="w-4 h-4" />
|
|
Facture
|
|
</span>
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideRuler class="w-4 h-4" />
|
|
Plan
|
|
</span>
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideCamera class="w-4 h-4" />
|
|
Photo
|
|
</span>
|
|
<span class="badge badge-lg gap-2 py-3">
|
|
<IconLucideFile class="w-4 h-4" />
|
|
Autre
|
|
</span>
|
|
</div>
|
|
|
|
<p class="text-sm text-base-content/60">
|
|
Les documents sont consultables et telechargeables directement depuis la fiche
|
|
de l'element auquel ils sont rattaches.
|
|
</p>
|
|
</section>
|
|
|
|
<!-- ==================== 8. CHAMPS PERSONNALISES ==================== -->
|
|
<section id="champs-personnalises" :ref="el => setSectionRef('champs-personnalises', el)" class="scroll-mt-24">
|
|
<SectionTitle icon="IconLucideSettings" color="primary">
|
|
Informations supplementaires (champs personnalises)
|
|
</SectionTitle>
|
|
|
|
<p class="text-base-content/70 mb-6 leading-relaxed">
|
|
En plus des informations de base (nom, reference, fournisseur...),
|
|
vous pouvez ajouter des <strong>informations supplementaires</strong> sur mesure
|
|
pour chaque element. Par exemple : un numero de serie, une date de garantie,
|
|
une puissance en kW, etc.
|
|
</p>
|
|
|
|
<!-- Chaque element a ses champs -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Qui peut avoir des informations supplementaires ?</h3>
|
|
<p class="text-base-content/70 mb-4 text-sm">
|
|
Tout le monde ! Mais la facon de les definir est differente :
|
|
</p>
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
|
<div class="card bg-secondary/5 border border-secondary/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideCog class="w-5 h-5 text-secondary" />
|
|
<span class="font-bold text-base-content">Sur une machine</span>
|
|
</div>
|
|
<p class="text-sm text-base-content/70 mb-3">
|
|
Vous ajoutez les champs <strong>directement sur la machine</strong>,
|
|
un par un. Chaque machine peut avoir ses propres champs.
|
|
</p>
|
|
<div class="bg-base-200/50 rounded-lg p-3 text-xs space-y-1 text-base-content/60">
|
|
<p class="font-semibold text-base-content/40">Exemples :</p>
|
|
<p>Date de mise en service</p>
|
|
<p>Numero d'inventaire</p>
|
|
<p>Cout d'acquisition</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card bg-accent/5 border border-accent/20">
|
|
<div class="card-body p-5">
|
|
<div class="flex items-center gap-2 mb-3">
|
|
<IconLucideBoxes class="w-5 h-5 text-accent" />
|
|
<span class="font-bold text-base-content">Sur composant, piece, produit</span>
|
|
</div>
|
|
<p class="text-sm text-base-content/70 mb-3">
|
|
Les champs sont definis <strong>dans le modele type</strong>.
|
|
Tous les elements du meme modele partagent les memes champs.
|
|
</p>
|
|
<div class="bg-base-200/50 rounded-lg p-3 text-xs space-y-1 text-base-content/60">
|
|
<p class="font-semibold text-base-content/40">Exemple pour "Pompe hydraulique" :</p>
|
|
<p>Debit max (nombre)</p>
|
|
<p>Type de fluide (liste de choix)</p>
|
|
<p>Certifie ATEX (oui/non)</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Types de champs -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Les types d'informations possibles</h3>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 mb-8">
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<IconLucideType class="w-4 h-4 text-primary" />
|
|
<span class="font-bold text-sm">Texte</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60">Saisie libre au clavier</p>
|
|
<div class="mt-2 bg-base-200/50 rounded px-2 py-1.5 text-xs text-base-content/40 italic">
|
|
Acier inoxydable 316L
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<IconLucideHash class="w-4 h-4 text-primary" />
|
|
<span class="font-bold text-sm">Nombre</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60">Uniquement des chiffres</p>
|
|
<div class="mt-2 bg-base-200/50 rounded px-2 py-1.5 text-xs text-base-content/40 italic">
|
|
1500 tours/min
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<IconLucideList class="w-4 h-4 text-primary" />
|
|
<span class="font-bold text-sm">Liste de choix</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60">Choisir parmi des options</p>
|
|
<div class="mt-2 bg-base-200/50 rounded px-2 py-1.5 text-xs text-base-content/40 italic">
|
|
Gauche / Droite / Centre
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<IconLucideToggleLeft class="w-4 h-4 text-primary" />
|
|
<span class="font-bold text-sm">Oui / Non</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60">Juste cocher ou decocher</p>
|
|
<div class="mt-2 bg-base-200/50 rounded px-2 py-1.5 text-xs text-base-content/40 italic">
|
|
ATEX certifie : Oui
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<div class="flex items-center gap-2 mb-2">
|
|
<IconLucideCalendar class="w-4 h-4 text-primary" />
|
|
<span class="font-bold text-sm">Date</span>
|
|
</div>
|
|
<p class="text-xs text-base-content/60">Choisir une date dans le calendrier</p>
|
|
<div class="mt-2 bg-base-200/50 rounded px-2 py-1.5 text-xs text-base-content/40 italic">
|
|
15/03/2026
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Champs contextuels -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">
|
|
<IconLucideAlertTriangle class="w-5 h-5 inline text-warning mr-1" />
|
|
Champs visibles uniquement dans une machine
|
|
</h3>
|
|
|
|
<div class="card bg-warning/5 border border-warning/20 mb-6">
|
|
<div class="card-body p-6">
|
|
<p class="text-base-content/70 leading-relaxed mb-4">
|
|
Quand vous creez un champ dans un modele type (pour un composant, une piece ou un produit),
|
|
vous pouvez choisir : <strong>est-ce que ce champ doit apparaitre partout,
|
|
ou seulement quand on regarde l'element depuis une machine ?</strong>
|
|
</p>
|
|
<p class="text-base-content/70 leading-relaxed mb-4">
|
|
<strong>Pourquoi ?</strong> Certaines informations n'ont de sens que quand
|
|
l'element est monte sur une machine. Prenons l'exemple d'un palier : sur une
|
|
machine, vous en avez souvent deux, un en haut (le palier de tete) et un en
|
|
bas (le palier de pied). Dans le catalogue, le palier n'est monte nulle part,
|
|
donc savoir s'il est "en haut" ou "en bas" ne veut rien dire. Mais des qu'on
|
|
regarde ce palier depuis la fiche d'une machine, on veut savoir lequel des
|
|
deux c'est.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-sm font-semibold text-base-content mb-3">Voici la difference :</p>
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
|
<div class="card bg-base-100 border-2 border-base-300">
|
|
<div class="card-body p-5">
|
|
<p class="font-bold text-sm text-base-content mb-1">Dans le catalogue</p>
|
|
<p class="text-xs text-base-content/40 mb-4">Quand on consulte l'element tout seul</p>
|
|
<div class="space-y-2 text-sm">
|
|
<div class="flex justify-between">
|
|
<span class="text-base-content/70">Diametre interieur</span>
|
|
<span>50 mm</span>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span class="text-base-content/70">Type</span>
|
|
<span>Roulement a billes</span>
|
|
</div>
|
|
<div class="border-t border-dashed border-base-300 pt-2 mt-2">
|
|
<div class="flex justify-between opacity-30">
|
|
<span class="line-through">Emplacement</span>
|
|
<span class="text-xs italic">pas affiche ici</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border-2 border-primary/30">
|
|
<div class="card-body p-5">
|
|
<p class="font-bold text-sm text-base-content mb-1">Depuis une machine</p>
|
|
<p class="text-xs text-base-content/40 mb-4">Quand on regarde l'element dans sa machine</p>
|
|
<div class="space-y-2 text-sm">
|
|
<div class="flex justify-between">
|
|
<span class="text-base-content/70">Diametre interieur</span>
|
|
<span>50 mm</span>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<span class="text-base-content/70">Type</span>
|
|
<span>Roulement a billes</span>
|
|
</div>
|
|
<div class="border-t border-primary/20 pt-2 mt-2">
|
|
<div class="flex justify-between bg-primary/10 rounded px-2 py-1.5">
|
|
<span class="text-base-content font-medium">Emplacement</span>
|
|
<span class="font-bold">Haut (palier de tete)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Options -->
|
|
<h3 class="font-bold text-base-content mb-4 text-lg">Options des champs</h3>
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<h4 class="font-bold text-sm flex items-center gap-2">
|
|
<IconLucideAsterisk class="w-4 h-4 text-error" />
|
|
Obligatoire
|
|
</h4>
|
|
<p class="text-xs text-base-content/60 mt-1">
|
|
L'element ne peut pas etre sauvegarde tant que ce champ n'est pas rempli.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<h4 class="font-bold text-sm flex items-center gap-2">
|
|
<IconLucideClipboardCheck class="w-4 h-4 text-base-content/50" />
|
|
Valeur par defaut
|
|
</h4>
|
|
<p class="text-xs text-base-content/60 mt-1">
|
|
Le champ est pre-rempli automatiquement a la creation. Vous pouvez le modifier apres.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<h4 class="font-bold text-sm flex items-center gap-2">
|
|
<IconLucideList class="w-4 h-4 text-base-content/50" />
|
|
Options de la liste
|
|
</h4>
|
|
<p class="text-xs text-base-content/60 mt-1">
|
|
Pour les champs "liste de choix", vous definissez les options possibles.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="card bg-base-100 border border-base-300 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<h4 class="font-bold text-sm flex items-center gap-2">
|
|
<IconLucideArrowUpDown class="w-4 h-4 text-base-content/50" />
|
|
Ordre d'affichage
|
|
</h4>
|
|
<p class="text-xs text-base-content/60 mt-1">
|
|
Vous choisissez dans quel ordre les champs apparaissent sur la fiche.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Footer spacer -->
|
|
<div class="h-32" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted, onUnmounted, type Component as VueComponent, defineComponent, h } from 'vue'
|
|
import { useHead } from '#imports'
|
|
|
|
// Icons
|
|
import IconLucideBookOpen from '~icons/lucide/book-open'
|
|
import IconLucideNetwork from '~icons/lucide/network'
|
|
import IconLucideFactory from '~icons/lucide/factory'
|
|
import IconLucideCog from '~icons/lucide/cog'
|
|
import IconLucideBoxes from '~icons/lucide/boxes'
|
|
import IconLucideWrench from '~icons/lucide/wrench'
|
|
import IconLucideDroplets from '~icons/lucide/droplets'
|
|
import IconLucideCheck from '~icons/lucide/check'
|
|
import IconLucideInfo from '~icons/lucide/info'
|
|
import IconLucideCopy from '~icons/lucide/copy'
|
|
import IconLucideLayoutTemplate from '~icons/lucide/layout-template'
|
|
import IconLucideLightbulb from '~icons/lucide/lightbulb'
|
|
import IconLucideHash from '~icons/lucide/hash'
|
|
import IconLucideArrowRight from '~icons/lucide/arrow-right'
|
|
import IconLucideRefreshCw from '~icons/lucide/refresh-cw'
|
|
import IconLucideTruck from '~icons/lucide/truck'
|
|
import IconLucidePlus from '~icons/lucide/plus'
|
|
import IconLucideLink from '~icons/lucide/link'
|
|
import IconLucideFileText from '~icons/lucide/file-text'
|
|
import IconLucideBook from '~icons/lucide/book'
|
|
import IconLucideFileSpreadsheet from '~icons/lucide/file-spreadsheet'
|
|
import IconLucideReceipt from '~icons/lucide/receipt'
|
|
import IconLucideRuler from '~icons/lucide/ruler'
|
|
import IconLucideCamera from '~icons/lucide/camera'
|
|
import IconLucideFile from '~icons/lucide/file'
|
|
import IconLucideSettings from '~icons/lucide/settings'
|
|
import IconLucideType from '~icons/lucide/type'
|
|
import IconLucideToggleLeft from '~icons/lucide/toggle-left'
|
|
import IconLucideCalendar from '~icons/lucide/calendar'
|
|
import IconLucideAlertTriangle from '~icons/lucide/alert-triangle'
|
|
import IconLucideClipboardCheck from '~icons/lucide/clipboard-check'
|
|
import IconLucideAsterisk from '~icons/lucide/asterisk'
|
|
import IconLucideArrowUpDown from '~icons/lucide/arrow-up-down'
|
|
import IconLucideList from '~icons/lucide/list'
|
|
import IconLucideChevronDown from '~icons/lucide/chevron-down'
|
|
|
|
useHead({ title: 'Documentation' })
|
|
|
|
// ─── Inline sub-components ───
|
|
|
|
const iconMap: Record<string, VueComponent> = {
|
|
IconLucideNetwork,
|
|
IconLucideCog,
|
|
IconLucideBoxes,
|
|
IconLucideWrench,
|
|
IconLucideLayoutTemplate,
|
|
IconLucideTruck,
|
|
IconLucideFileText,
|
|
IconLucideSettings,
|
|
}
|
|
|
|
const SectionTitle = defineComponent({
|
|
props: {
|
|
icon: { type: String, required: true },
|
|
color: { type: String, default: 'primary' },
|
|
},
|
|
setup(props, { slots }) {
|
|
return () => h('div', { class: 'flex items-center gap-3 mb-6' }, [
|
|
h(iconMap[props.icon] ?? 'span', { class: `w-6 h-6 text-${props.color}` }),
|
|
h('h2', { class: 'text-2xl font-bold text-base-content tracking-tight' }, slots.default?.()),
|
|
])
|
|
},
|
|
})
|
|
|
|
const StepCard = defineComponent({
|
|
props: {
|
|
n: { type: String, required: true },
|
|
title: { type: String, required: true },
|
|
},
|
|
setup(props, { slots }) {
|
|
return () => h('div', { class: 'flex gap-4 items-start' }, [
|
|
h('div', {
|
|
class: 'w-9 h-9 rounded-full bg-primary/10 text-primary font-bold text-sm flex items-center justify-center shrink-0 mt-0.5',
|
|
}, props.n),
|
|
h('div', {}, [
|
|
h('p', { class: 'font-bold text-base-content' }, props.title),
|
|
h('p', { class: 'text-sm text-base-content/60 mt-0.5' }, slots.default?.()),
|
|
]),
|
|
])
|
|
},
|
|
})
|
|
|
|
// ─── Sections ───
|
|
|
|
interface Section {
|
|
id: string
|
|
label: string
|
|
icon: VueComponent
|
|
}
|
|
|
|
const sections: Section[] = [
|
|
{ id: 'organisation', label: 'Organisation', icon: IconLucideNetwork },
|
|
{ id: 'machines', label: 'Machines', icon: IconLucideCog },
|
|
{ id: 'composants', label: 'Composants', icon: IconLucideBoxes },
|
|
{ id: 'pieces-produits', label: 'Pieces & Produits', icon: IconLucideWrench },
|
|
{ id: 'modeles-types', label: 'Modeles types', icon: IconLucideLayoutTemplate },
|
|
{ id: 'fournisseurs', label: 'Fournisseurs', icon: IconLucideTruck },
|
|
{ id: 'documents', label: 'Documents', icon: IconLucideFileText },
|
|
{ id: 'champs-personnalises', label: 'Champs perso', icon: IconLucideSettings },
|
|
]
|
|
|
|
const activeSection = ref('organisation')
|
|
const mobileMenuOpen = ref(false)
|
|
|
|
const sectionRefs = new Map<string, Element>()
|
|
|
|
function setSectionRef(id: string, el: unknown) {
|
|
if (el instanceof Element) {
|
|
sectionRefs.set(id, el)
|
|
}
|
|
}
|
|
|
|
function scrollTo(id: string) {
|
|
const el = document.getElementById(id)
|
|
if (el) {
|
|
el.scrollIntoView({ behavior: 'smooth' })
|
|
mobileMenuOpen.value = false
|
|
}
|
|
}
|
|
|
|
let observer: IntersectionObserver | null = null
|
|
|
|
onMounted(() => {
|
|
observer = new IntersectionObserver(
|
|
(entries) => {
|
|
for (const entry of entries) {
|
|
if (entry.isIntersecting) {
|
|
activeSection.value = entry.target.id
|
|
}
|
|
}
|
|
},
|
|
{
|
|
rootMargin: '-20% 0px -60% 0px',
|
|
threshold: 0,
|
|
},
|
|
)
|
|
|
|
for (const el of sectionRefs.values()) {
|
|
observer.observe(el)
|
|
}
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
observer?.disconnect()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.slide-enter-active,
|
|
.slide-leave-active {
|
|
transition: max-height 0.25s ease, opacity 0.25s ease;
|
|
overflow: hidden;
|
|
}
|
|
.slide-enter-from,
|
|
.slide-leave-to {
|
|
max-height: 0;
|
|
opacity: 0;
|
|
}
|
|
.slide-enter-to,
|
|
.slide-leave-from {
|
|
max-height: 30rem;
|
|
opacity: 1;
|
|
}
|
|
</style>
|