Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11491b02c5 | ||
| 024af5887e | |||
|
|
91c0125876 | ||
| b510cdcc42 | |||
|
|
d0213c3212 | ||
| 3ac676689d | |||
|
|
9f47e81efd | ||
| 257b93e691 | |||
|
|
dc5320b324 | ||
| 09a641e5cf | |||
|
|
a0557b077b | ||
| 2d2b38eae4 | |||
|
|
d3581b8ce6 | ||
| 9e53be8ac3 |
19
.idea/dataSources.xml
generated
19
.idea/dataSources.xml
generated
@@ -1,19 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
|
||||||
<data-source source="LOCAL" name="ferme" uuid="f407a514-c6b4-4b26-9555-445a85892502">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://localhost:5432/ferme</jdbc-url>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
</data-source>
|
|
||||||
<data-source source="LOCAL" name="Ferme recette" uuid="ae622167-c834-4e7b-87a5-c1721036f5dc">
|
|
||||||
<driver-ref>postgresql</driver-ref>
|
|
||||||
<synchronize>true</synchronize>
|
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
|
||||||
<jdbc-url>jdbc:postgresql://localhost:5432/postgres</jdbc-url>
|
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
|
||||||
</data-source>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
2
.idea/db-forest-config.xml
generated
2
.idea/db-forest-config.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="db-tree-configuration">
|
<component name="db-tree-configuration">
|
||||||
<option name="data" value="---------------------------------------- 1:0:f407a514-c6b4-4b26-9555-445a85892502 2:0:ae622167-c834-4e7b-87a5-c1721036f5dc " />
|
<option name="data" value="---------------------------------------- 1:0:f407a514-c6b4-4b26-9555-445a85892502 2:0:ae622167-c834-4e7b-87a5-c1721036f5dc 3:0:9cad43df-2147-4989-b7a4-443067034884 4:0:09e221b8-067a-488b-9c1d-4e155a333079 " />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
328
.idea/workspace.xml
generated
328
.idea/workspace.xml
generated
@@ -4,11 +4,13 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="fix : corrections diverses">
|
<list default="true" id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="fix : on ne bloque plus le poids max d'une pesée">
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/dataSources.xml" beforeDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/db-forest-config.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/db-forest-config.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/AGENTS.md" beforeDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/config/reference.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/reference.php" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/config/reference.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/reference.php" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/pages/infrastructure/case.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/pages/infrastructure/case.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Command/SeedCommand.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Command/SeedCommand.php" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Entity/BuildingCase.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Entity/BuildingCase.php" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -31,16 +33,16 @@
|
|||||||
<component name="FileTemplateManagerImpl">
|
<component name="FileTemplateManagerImpl">
|
||||||
<option name="RECENT_TEMPLATES">
|
<option name="RECENT_TEMPLATES">
|
||||||
<list>
|
<list>
|
||||||
<option value="Vue Composition API Component" />
|
|
||||||
<option value="TypeScript File" />
|
<option value="TypeScript File" />
|
||||||
<option value="PHP File" />
|
<option value="PHP File" />
|
||||||
|
<option value="Vue Composition API Component" />
|
||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="Git.Settings">
|
<component name="Git.Settings">
|
||||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||||
<map>
|
<map>
|
||||||
<entry key="$PROJECT_DIR$" value="fit/332-refonte-reception-terminee" />
|
<entry key="$PROJECT_DIR$" value="feat/327-voir-modifier-une-expedition-terminee" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||||
@@ -224,38 +226,39 @@
|
|||||||
<option name="hideEmptyMiddlePackages" value="true" />
|
<option name="hideEmptyMiddlePackages" value="true" />
|
||||||
<option name="showLibraryContents" value="true" />
|
<option name="showLibraryContents" value="true" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent"><![CDATA[{
|
<component name="PropertiesComponent">{
|
||||||
"keyToString": {
|
"keyToString": {
|
||||||
"RunOnceActivity.MCP Project settings loaded": "true",
|
"RunOnceActivity.MCP Project settings loaded": "true",
|
||||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||||
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
"RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
|
||||||
"RunOnceActivity.git.unshallow": "true",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||||
"git-widget-placeholder": "feat/278-plan-du-site",
|
"git-widget-placeholder": "develop",
|
||||||
"last_opened_file_path": "//wsl.localhost/Ubuntu-24.04/home/m-tristan/workspace/Ferme",
|
"last_opened_file_path": "/home/sroy/Documents/test/Ferme/frontend/components/commun",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.detected.package.tslint": "true",
|
"node.js.detected.package.tslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
"node.js.selected.package.tslint": "(autodetect)",
|
"node.js.selected.package.tslint": "(autodetect)",
|
||||||
"nodejs_package_manager_path": "npm",
|
"nodejs_package_manager_path": "npm",
|
||||||
"settings.editor.selected.configurable": "preferences.pluginManager",
|
"settings.editor.selected.configurable": "advanced.settings",
|
||||||
"ts.external.directory.path": "/opt/phpstorm/plugins/javascript-plugin/jsLanguageServicesImpl/external",
|
"ts.external.directory.path": "/opt/phpstorm/plugins/javascript-plugin/jsLanguageServicesImpl/external",
|
||||||
"vue.rearranger.settings.migration": "true"
|
"vue.rearranger.settings.migration": "true"
|
||||||
},
|
},
|
||||||
"keyToStringList": {
|
"keyToStringList": {
|
||||||
"DatabaseDriversLRU": [
|
"DatabaseDriversLRU": [
|
||||||
"postgresql"
|
"postgresql"
|
||||||
],
|
],
|
||||||
"com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
|
"com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
|
||||||
"TEXT"
|
"TEXT"
|
||||||
],
|
],
|
||||||
"vue.recent.templates": [
|
"vue.recent.templates": [
|
||||||
"Vue Composition API Component"
|
"Vue Composition API Component"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}]]></component>
|
}</component>
|
||||||
<component name="RecentsManager">
|
<component name="RecentsManager">
|
||||||
<key name="CopyFile.RECENT_KEYS">
|
<key name="CopyFile.RECENT_KEYS">
|
||||||
|
<recent name="$PROJECT_DIR$/frontend/components/commun" />
|
||||||
<recent name="\\wsl.localhost\Ubuntu-24.04\home\m-tristan\workspace\Ferme" />
|
<recent name="\\wsl.localhost\Ubuntu-24.04\home\m-tristan\workspace\Ferme" />
|
||||||
<recent name="\\wsl.localhost\Ubuntu-24.04\home\kevin\Stage\Ferme\frontend\pages\shipment" />
|
<recent name="\\wsl.localhost\Ubuntu-24.04\home\kevin\Stage\Ferme\frontend\pages\shipment" />
|
||||||
<recent name="\\wsl.localhost\Ubuntu-24.04\home\kevin\Stage\Ferme\frontend\composables" />
|
<recent name="\\wsl.localhost\Ubuntu-24.04\home\kevin\Stage\Ferme\frontend\composables" />
|
||||||
@@ -272,10 +275,11 @@
|
|||||||
<component name="SharedIndexes">
|
<component name="SharedIndexes">
|
||||||
<attachedChunks>
|
<attachedChunks>
|
||||||
<set>
|
<set>
|
||||||
<option value="bundled-php-predefined-a98d8de5180a-0e0d91225499-com.jetbrains.php.sharedIndexes-PS-253.30387.85" />
|
<option value="bundled-php-predefined-a98d8de5180a-0e0d91225499-com.jetbrains.php.sharedIndexes-PS-253.31033.138" />
|
||||||
</set>
|
</set>
|
||||||
</attachedChunks>
|
</attachedChunks>
|
||||||
</component>
|
</component>
|
||||||
|
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||||
<component name="TaskManager">
|
<component name="TaskManager">
|
||||||
<task active="true" id="Default" summary="Default task">
|
<task active="true" id="Default" summary="Default task">
|
||||||
<changelist id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="" />
|
<changelist id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="" />
|
||||||
@@ -310,118 +314,16 @@
|
|||||||
<workItem from="1770879701502" duration="25805000" />
|
<workItem from="1770879701502" duration="25805000" />
|
||||||
<workItem from="1770966186589" duration="914000" />
|
<workItem from="1770966186589" duration="914000" />
|
||||||
<workItem from="1770967274060" duration="2388000" />
|
<workItem from="1770967274060" duration="2388000" />
|
||||||
</task>
|
<workItem from="1772466451823" duration="598000" />
|
||||||
<task id="LOCAL-00007" summary="test : ajout de TU sur les services et providers">
|
<workItem from="1772626984813" duration="969000" />
|
||||||
<option name="closed" value="true" />
|
<workItem from="1772786360430" duration="21000" />
|
||||||
<created>1768318921478</created>
|
<workItem from="1772786475316" duration="3016000" />
|
||||||
<option name="number" value="00007" />
|
<workItem from="1773049125640" duration="406000" />
|
||||||
<option name="presentableId" value="LOCAL-00007" />
|
<workItem from="1773049540928" duration="539000" />
|
||||||
<option name="project" value="LOCAL" />
|
<workItem from="1773050154207" duration="1879000" />
|
||||||
<updated>1768318921478</updated>
|
<workItem from="1773212999001" duration="652000" />
|
||||||
</task>
|
<workItem from="1773215356754" duration="5754000" />
|
||||||
<task id="LOCAL-00008" summary="feat : ajout de la génération du bon de reception, correction de la base du formulaire multi-etape de reception et ajout d'une gestion d'erreur global">
|
<workItem from="1773756072697" duration="3129000" />
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1768498751836</created>
|
|
||||||
<option name="number" value="00008" />
|
|
||||||
<option name="presentableId" value="LOCAL-00008" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1768498751836</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00009" summary="feat : ajout d'une gestion d'erreur au global côté front avec la lib toaster et I18n pour centraliser les messages d'erreur">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1768555180530</created>
|
|
||||||
<option name="number" value="00009" />
|
|
||||||
<option name="presentableId" value="LOCAL-00009" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1768555180530</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00010" summary="feat : ajout de l'authentification avec lexik">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1768832208350</created>
|
|
||||||
<option name="number" value="00010" />
|
|
||||||
<option name="presentableId" value="LOCAL-00010" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1768832208350</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00011" summary="feat : update du CHANGELOG.md">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1768832516587</created>
|
|
||||||
<option name="number" value="00011" />
|
|
||||||
<option name="presentableId" value="LOCAL-00011" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1768832516587</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00012" summary="fix : correction de l'accès au swagger en mode dev qui n'était plus accessible">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1768940104944</created>
|
|
||||||
<option name="number" value="00012" />
|
|
||||||
<option name="presentableId" value="LOCAL-00012" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1768940104944</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00013" summary="feat : ajout de la conf pour le déploiement en recette">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769005220331</created>
|
|
||||||
<option name="number" value="00013" />
|
|
||||||
<option name="presentableId" value="LOCAL-00013" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769005220331</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00014" summary="fix : fix de la conf pour le déploiement en recette">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769008700008</created>
|
|
||||||
<option name="number" value="00014" />
|
|
||||||
<option name="presentableId" value="LOCAL-00014" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769008700008</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00015" summary="fix : fix de la conf pour le déploiement en recette">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769014602062</created>
|
|
||||||
<option name="number" value="00015" />
|
|
||||||
<option name="presentableId" value="LOCAL-00015" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769014602062</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00016" summary="fix : migration apache vers nginx pour un déploiement plus simple">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769019284586</created>
|
|
||||||
<option name="number" value="00016" />
|
|
||||||
<option name="presentableId" value="LOCAL-00016" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769019284586</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00017" summary="fix : dernière modification pour le déploiement en recette et le changement de conf vers nginx">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769021756823</created>
|
|
||||||
<option name="number" value="00017" />
|
|
||||||
<option name="presentableId" value="LOCAL-00017" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769021756823</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00018" summary="ci : auto tag + release artefact">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769021818384</created>
|
|
||||||
<option name="number" value="00018" />
|
|
||||||
<option name="presentableId" value="LOCAL-00018" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769021818384</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00019" summary="ci : fix release artefact">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769022071620</created>
|
|
||||||
<option name="number" value="00019" />
|
|
||||||
<option name="presentableId" value="LOCAL-00019" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769022071620</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00020" summary="ci : fix release artefact">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1769024603812</created>
|
|
||||||
<option name="number" value="00020" />
|
|
||||||
<option name="presentableId" value="LOCAL-00020" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1769024603812</updated>
|
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00021" summary="ci : ajout du script et de la doc déploiement">
|
<task id="LOCAL-00021" summary="ci : ajout du script et de la doc déploiement">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
@@ -703,7 +605,119 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1770969471135</updated>
|
<updated>1770969471135</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="56" />
|
<task id="LOCAL-00056" summary="fix : corrections frontend">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772094268366</created>
|
||||||
|
<option name="number" value="00056" />
|
||||||
|
<option name="presentableId" value="LOCAL-00056" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772094268366</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00057" summary="feat : affichage et modification expédition et modification bouton valider">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772111964268</created>
|
||||||
|
<option name="number" value="00057" />
|
||||||
|
<option name="presentableId" value="LOCAL-00057" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772111964268</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00058" summary="fix : erreur customer adress et bouton valider oublie">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772112729501</created>
|
||||||
|
<option name="number" value="00058" />
|
||||||
|
<option name="presentableId" value="LOCAL-00058" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772112729502</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00059" summary="feat : changelog update">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772112812677</created>
|
||||||
|
<option name="number" value="00059" />
|
||||||
|
<option name="presentableId" value="LOCAL-00059" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772112812677</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00060" summary="feat : changelog update">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772177400063</created>
|
||||||
|
<option name="number" value="00060" />
|
||||||
|
<option name="presentableId" value="LOCAL-00060" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772177400063</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00061" summary="feat : changelog update">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772177614438</created>
|
||||||
|
<option name="number" value="00061" />
|
||||||
|
<option name="presentableId" value="LOCAL-00061" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772177614438</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00062" summary="fix : color tab">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772178540489</created>
|
||||||
|
<option name="number" value="00062" />
|
||||||
|
<option name="presentableId" value="LOCAL-00062" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772178540489</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00063" summary="feat : modification front de la page admin transporteur">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772180053740</created>
|
||||||
|
<option name="number" value="00063" />
|
||||||
|
<option name="presentableId" value="LOCAL-00063" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772180053740</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00064" summary="fix : espacement et changelog">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772180581178</created>
|
||||||
|
<option name="number" value="00064" />
|
||||||
|
<option name="presentableId" value="LOCAL-00064" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772180581178</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00065" summary="fix : espacement">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772180684250</created>
|
||||||
|
<option name="number" value="00065" />
|
||||||
|
<option name="presentableId" value="LOCAL-00065" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772180684250</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00066" summary="fix : espacement">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772180972984</created>
|
||||||
|
<option name="number" value="00066" />
|
||||||
|
<option name="presentableId" value="LOCAL-00066" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772180972984</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00067" summary="fix : text">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772182545592</created>
|
||||||
|
<option name="number" value="00067" />
|
||||||
|
<option name="presentableId" value="LOCAL-00067" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772182545592</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00068" summary="feat : front page admin bovin et changelog">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772182707441</created>
|
||||||
|
<option name="number" value="00068" />
|
||||||
|
<option name="presentableId" value="LOCAL-00068" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772182707441</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00069" summary="fix : on ne bloque plus le poids max d'une pesée">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1772447581744</created>
|
||||||
|
<option name="number" value="00069" />
|
||||||
|
<option name="presentableId" value="LOCAL-00069" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1772447581744</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="70" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -753,17 +767,6 @@
|
|||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="VcsManagerConfiguration">
|
<component name="VcsManagerConfiguration">
|
||||||
<MESSAGE value="fix : gitea workflow" />
|
|
||||||
<MESSAGE value="fix : script de déploiement" />
|
|
||||||
<MESSAGE value="feat : ajout plus d'information sur la liste des réceptions côté front sur la page d'accueil" />
|
|
||||||
<MESSAGE value="fix : redirige sur le login sur une 401 et reset du auth state + doc + timeout du toaster" />
|
|
||||||
<MESSAGE value="feat : ajout de la debug bar en mod dev" />
|
|
||||||
<MESSAGE value="feat : ajout du bundle Malio ednotif pour l'utilisation des WS" />
|
|
||||||
<MESSAGE value="fix : modification de la conf du bundle ednotif" />
|
|
||||||
<MESSAGE value="feat : update du CHANGELOG.md" />
|
|
||||||
<MESSAGE value="feat : finalisation de l'étape 1 "Réception" (formulaire)" />
|
|
||||||
<MESSAGE value="feat : ajout du numéro identification des receptions et ajustement du bon de reception" />
|
|
||||||
<MESSAGE value="feat : ajout de la partie reception des marchandises (étape 3) et modification du bon de réception" />
|
|
||||||
<MESSAGE value="feat : mise en place de composant UI pour les select, checkbox, date, text" />
|
<MESSAGE value="feat : mise en place de composant UI pour les select, checkbox, date, text" />
|
||||||
<MESSAGE value="feat : update CHANGELOG.md" />
|
<MESSAGE value="feat : update CHANGELOG.md" />
|
||||||
<MESSAGE value="feat : ajout de commentaire" />
|
<MESSAGE value="feat : ajout de commentaire" />
|
||||||
@@ -778,7 +781,18 @@
|
|||||||
<MESSAGE value="feat : lister les expeditions terminees" />
|
<MESSAGE value="feat : lister les expeditions terminees" />
|
||||||
<MESSAGE value="fix: corrections diverses" />
|
<MESSAGE value="fix: corrections diverses" />
|
||||||
<MESSAGE value="fix : corrections diverses" />
|
<MESSAGE value="fix : corrections diverses" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="fix : corrections diverses" />
|
<MESSAGE value="fix : corrections frontend" />
|
||||||
|
<MESSAGE value="feat : affichage et modification expédition et modification bouton valider" />
|
||||||
|
<MESSAGE value="fix : erreur customer adress et bouton valider oublie" />
|
||||||
|
<MESSAGE value="feat : changelog update" />
|
||||||
|
<MESSAGE value="fix : color tab" />
|
||||||
|
<MESSAGE value="feat : modification front de la page admin transporteur" />
|
||||||
|
<MESSAGE value="fix : espacement et changelog" />
|
||||||
|
<MESSAGE value="fix : espacement" />
|
||||||
|
<MESSAGE value="fix : text" />
|
||||||
|
<MESSAGE value="feat : front page admin bovin et changelog" />
|
||||||
|
<MESSAGE value="fix : on ne bloque plus le poids max d'une pesée" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="fix : on ne bloque plus le poids max d'une pesée" />
|
||||||
</component>
|
</component>
|
||||||
<component name="XDebuggerManager">
|
<component name="XDebuggerManager">
|
||||||
<breakpoint-manager>
|
<breakpoint-manager>
|
||||||
@@ -817,4 +831,4 @@
|
|||||||
<option value=".github/prompts" />
|
<option value=".github/prompts" />
|
||||||
</promptFileLocations>
|
</promptFileLocations>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
73
AGENTS.md
73
AGENTS.md
@@ -1,73 +0,0 @@
|
|||||||
# AGENTS.md
|
|
||||||
|
|
||||||
Project overview
|
|
||||||
- Symfony 8 + API Platform 4 backend, Nuxt 3 frontend in `frontend/`.
|
|
||||||
- Apache vhost serves API under `/api` and frontend from `frontend/dist`.
|
|
||||||
- API base URL on frontend uses `NUXT_PUBLIC_API_BASE` (see `frontend/.env`).
|
|
||||||
|
|
||||||
Backend conventions
|
|
||||||
- Use English for code identifiers/messages; keep “pont-bascule” as domain term.
|
|
||||||
- API Platform operations are defined on Doctrine entities.
|
|
||||||
- No custom repository classes are used (`src/Repository` removed); use default Doctrine repositories via `EntityManagerInterface`.
|
|
||||||
- Reception entity is in `src/Entity/Reception.php`, with custom weigh endpoint `/receptions/weigh`.
|
|
||||||
- Reception fields: `date_reception`, `license_plate`, `current_step` (default 0), `is_valid` (default false).
|
|
||||||
- Reception also has `identification_number` (auto `N-BR-####`), `merchandise_type`, `merchandise_detail`, `buildings` (M2M), and `pellet_buildings` (via `reception_pellet_building`).
|
|
||||||
- `date_reception` is set by the UI, stored as `DateTimeImmutable`, serialized as `Y-m-d`.
|
|
||||||
- Weight entity (`src/Entity/Weight.php`) is 1–N with Reception, each row stores `type` (`gross` or `tare`), `dsd`, `weight`, `weighed_at` (all nullable except `type`).
|
|
||||||
- Weigh endpoint `/receptions/weigh` returns `PontBasculeReading` with `dsd`, `weight`, `weighedAt` (formatted `Y-m-d`).
|
|
||||||
- Custom exception: `App\Exception\PontBasculeException` with French messages, mapped to 500 in provider.
|
|
||||||
- Parsing of pont-bascule payload is in `src/Service/PontBasculePayloadDecoder.php`.
|
|
||||||
- `config/reference.php` is auto-generated; keep it.
|
|
||||||
- Bovine storage:
|
|
||||||
- `src/Entity/Bovine.php` with fields `nationalNumber` (unique), `receivedWeight`, `arrivalDate`, and `buildingCase` (ManyToOne).
|
|
||||||
- `src/Entity/BuildingCase.php` has `bovines` (OneToMany).
|
|
||||||
- Case PDF report:
|
|
||||||
- Endpoint: `GET /building_cases/{id}/weights-report` (provider: `App\State\BuildingCaseWeightsReportProvider`).
|
|
||||||
- Template: `templates/case_weights_report.html.twig`.
|
|
||||||
- Projection logic is done in backend from `arrivalDate`; daily gain is currently fixed at `1.3 kg/day` for all races.
|
|
||||||
|
|
||||||
Frontend conventions
|
|
||||||
- Nuxt SSR disabled; Tailwind used.
|
|
||||||
- Layout in `frontend/layouts/default.vue`: max width `1050px`, header full width.
|
|
||||||
- Tailwind custom color palette is `primary` (e.g. `bg-primary-500`).
|
|
||||||
- Global font stack uses Helvetica via Tailwind (`font-sans`) and `frontend/assets/css/main.css`.
|
|
||||||
- API composable in `frontend/composables/useApi.ts` with `get/post/put/patch/delete` and default JSON/PATCH content types.
|
|
||||||
- API errors/success toasts can be customized via `toastErrorMessage`/`toastSuccessMessage` or i18n keys `toastErrorKey`/`toastSuccessKey`. Global method fallbacks use `errors.http.*` keys.
|
|
||||||
- `useApi` uses `useNuxtApp().$i18n` (not `useI18n`) to avoid setup-only constraint in service calls.
|
|
||||||
- Pinia store: `frontend/stores/reception.ts` is the source of truth for the current reception.
|
|
||||||
- Zod is used for form validation (e.g. `frontend/components/reception/reception-form.vue`); shared helpers live in `frontend/utils/zod-errors.ts`.
|
|
||||||
- Weighing logic is shared via `frontend/composables/useWeighing.ts`.
|
|
||||||
- Reception step UI uses store state (`currentStep`) in `frontend/pages/reception/[[id]].vue`.
|
|
||||||
- Step 2 uses `frontend/components/reception/reception-product-received.vue` for merchandise selection; type codes in `frontend/utils/constants.ts`.
|
|
||||||
- Active nav styles in header use `NuxtLink` with `custom` slot.
|
|
||||||
- Reusable UI components live under `frontend/components/ui/` and are auto-imported with `Ui` prefix (e.g. `UiLoadingDots`).
|
|
||||||
- Service layer lives in `frontend/services/` with typed DTOs in `frontend/services/dto/`.
|
|
||||||
- Reception service uses `receptions`, `receptions/{id}`, `receptions/weigh` and supports success/error toast keys.
|
|
||||||
- Reception receipt endpoint is `receptions/{id}/receipt` (PDF) via `frontend/composables/usePdfPrinter.ts`.
|
|
||||||
- Infrastructure case page prints the case weight report PDF from `frontend/pages/infrastructure/case.vue` using `usePdfPrinter('/building_cases/{id}/weights-report')`.
|
|
||||||
|
|
||||||
Environment & routing
|
|
||||||
- Frontend dev server: `npm run dev` in `frontend/`.
|
|
||||||
- API base for local dev: `http://localhost:8080/api` (set in `frontend/.env` via `NUXT_PUBLIC_API_BASE`).
|
|
||||||
- CORS handled by Nelmio; `.env` includes `CORS_ALLOW_ORIGIN` regex for localhost.
|
|
||||||
- Nuxt i18n locales live in `frontend/i18n/locales` (configured via `langDir: 'locales'`).
|
|
||||||
- Default locale is `fr`; translations in `frontend/i18n/locales/fr.json`.
|
|
||||||
|
|
||||||
Notes
|
|
||||||
- Do not add a GET that creates resources; use POST + PATCH.
|
|
||||||
- Keep endpoints in plural (API Platform convention).
|
|
||||||
- Seed and fixtures conventions:
|
|
||||||
- `app:seed` now seeds infrastructure (`statut`, `building_layout`, `building_case`, `building_case_position`) and bovines.
|
|
||||||
- `app:seed` uses intermediate flushes (after buildings and after infrastructure) so find queries can resolve just-created records.
|
|
||||||
- Bovine seed rows use a legacy case token mapping to building-case code (`B{building}-C{case}`) before fallback to direct id lookup.
|
|
||||||
- Fixtures include `BuildingInfrastructureFixtures` + `BovineFixtures` (via `AppFixtures` dependencies).
|
|
||||||
- New reference data added:
|
|
||||||
- Reception types (`reception_type`, fields: `label`, `code`), selectable on reception form.
|
|
||||||
- Merchandise types (`merchandise_type`, fields: `label`, `code`) and pellet types (`pellet_type`, fields: `label`, `code`).
|
|
||||||
- Buildings (`building`, fields: `label`, `code`) and reception allocations (`reception_building` M2M, `reception_pellet_building` unique on reception/pellet/building).
|
|
||||||
- Suppliers (`supplier`) with addresses (`address`, fields: `label`, `street`, `postal_code`, `city`, `country_code` ISO2), via `supplier_address` join table.
|
|
||||||
- Trucks (`truck`, field: `name`), linked to receptions.
|
|
||||||
- Carriers (`carrier`, fields: `name`, nullable `code`), Drivers (`driver`, fields: `name`, `carrier_id`), Vehicles (`vehicle`, fields: `plate`, `carrier_id`, `truck_id`) used for LIOT logic.
|
|
||||||
- Reception links: `reception_type_id`, `supplier_id`, `address_id`, `truck_id`, `carrier_id`, `driver_id`, `user_id`.
|
|
||||||
- Address exposes `fullAddress` via getter for display.
|
|
||||||
- LIOT behavior in reception form: if carrier code = `LIOT`, show driver + vehicle selects and hide manual license plate input; vehicle list filters by truck type and carrier; selected vehicle sets `license_plate`.
|
|
||||||
@@ -54,7 +54,11 @@ Ajouter dans le fichier .env du frontend
|
|||||||
* [#334] Correctifs
|
* [#334] Correctifs
|
||||||
* [#332] Refonte écran réception terminée
|
* [#332] Refonte écran réception terminée
|
||||||
* [#327] afficher/modifier écran expédition terminée
|
* [#327] afficher/modifier écran expédition terminée
|
||||||
|
* [#352] modification front admin fournisseur
|
||||||
|
* [#355] modification front admin transporteur
|
||||||
|
* [#356] front page admin bovin
|
||||||
|
* [#353] modification front admin client
|
||||||
|
* [#353] modification front admin utilisateur
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
127
CLAUDE.md
Normal file
127
CLAUDE.md
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
|
||||||
|
- **Backend:** Symfony 8 + API Platform 4 (PHP 8.4)
|
||||||
|
- **Frontend:** Nuxt 4 (Vue 3, Pinia, Tailwind, Zod) in `frontend/`
|
||||||
|
- **Infra:** Docker (PHP-FPM + Nginx), Apache vhost serves API sous `/api` et frontend depuis `frontend/dist`
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Docker
|
||||||
|
make start # Démarrer les containers
|
||||||
|
make stop # Arrêter les containers
|
||||||
|
make restart # Redémarrer les containers
|
||||||
|
make shell # Shell dans le container PHP
|
||||||
|
|
||||||
|
# Install complet
|
||||||
|
make install # composer install + migrations + build frontend
|
||||||
|
|
||||||
|
# Backend
|
||||||
|
make composer-install # Installer dépendances PHP
|
||||||
|
make migration-migrate # Lancer les migrations
|
||||||
|
make fixtures # Charger les fixtures
|
||||||
|
make cache-clear # Vider le cache Symfony
|
||||||
|
make test # Lancer les tests PHPUnit
|
||||||
|
make test FILES=tests/path/to/TestFile.php # Test spécifique
|
||||||
|
make php-cs-fixer-allow-risky FILES=src/... # Fixer le style
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
make build-nuxtJS # npm install + build:dist (dans le container)
|
||||||
|
make dev-nuxt # Serveur dev Nuxt (dans le container)
|
||||||
|
# Ou directement dans frontend/ :
|
||||||
|
cd frontend && npm run dev # Dev server (port 3000)
|
||||||
|
cd frontend && npm run build:dist # Build production
|
||||||
|
|
||||||
|
# Base de données
|
||||||
|
make db-reset # ⚠️ Supprime et recrée la BDD + migrations + fixtures
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture backend
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── ApiResource/ # Ressources API Platform custom
|
||||||
|
├── Command/ # Commandes Symfony (dont app:seed)
|
||||||
|
├── DataFixtures/ # Fixtures Doctrine
|
||||||
|
├── Dto/ # DTOs (ex: PontBasculeReading)
|
||||||
|
├── Entity/ # Entités Doctrine (= ressources API Platform)
|
||||||
|
├── Exception/ # Exceptions custom (PontBasculeException)
|
||||||
|
├── Kernel.php
|
||||||
|
├── Service/ # Services métier (PontBasculePayloadDecoder…)
|
||||||
|
└── State/ # State providers/processors API Platform
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture frontend
|
||||||
|
|
||||||
|
```
|
||||||
|
frontend/
|
||||||
|
├── components/
|
||||||
|
│ ├── ui/ # Composants réutilisables, auto-importés avec préfixe Ui (ex: UiLoadingDots)
|
||||||
|
│ └── reception/ # Composants métier réception
|
||||||
|
├── composables/ # useApi, useWeighing, usePdfPrinter, useAppVersion
|
||||||
|
├── services/ # Couche service avec DTOs typés dans services/dto/
|
||||||
|
├── stores/ # Pinia stores (reception, shipment, auth)
|
||||||
|
├── pages/ # Pages Nuxt (file-based routing)
|
||||||
|
├── layouts/ # Layout default : max-width 1050px
|
||||||
|
├── i18n/locales/ # Traductions (défaut: fr)
|
||||||
|
├── utils/ # Constants, zod-errors helpers
|
||||||
|
└── assets/css/ # Tailwind config, main.css (font Helvetica)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conventions backend
|
||||||
|
|
||||||
|
- Code en anglais ; "pont-bascule" est un terme métier conservé tel quel.
|
||||||
|
- Les opérations API Platform sont définies directement sur les entités Doctrine.
|
||||||
|
- Pas de classes Repository custom : utiliser `EntityManagerInterface` avec les repos par défaut.
|
||||||
|
- `config/reference.php` est auto-généré — ne pas modifier à la main.
|
||||||
|
- Endpoints toujours au pluriel (convention API Platform).
|
||||||
|
- Ne jamais créer de GET qui crée des ressources : utiliser POST + PATCH.
|
||||||
|
|
||||||
|
## Conventions frontend
|
||||||
|
|
||||||
|
- SSR désactivé. Tailwind avec palette custom `primary` (ex: `bg-primary-500`).
|
||||||
|
- `useApi` (`composables/useApi.ts`) : méthodes `get/post/put/patch/delete` avec content-types par défaut.
|
||||||
|
- Toasts personnalisables via `toastErrorMessage`/`toastSuccessMessage` ou clés i18n `toastErrorKey`/`toastSuccessKey`.
|
||||||
|
- Utilise `useNuxtApp().$i18n` (pas `useI18n`) pour fonctionner hors setup.
|
||||||
|
- Validation formulaires avec Zod ; helpers dans `utils/zod-errors.ts`.
|
||||||
|
- Nav active : `NuxtLink` avec slot `custom`.
|
||||||
|
- PDFs : `usePdfPrinter` (receipt réception, rapport poids cases).
|
||||||
|
|
||||||
|
## Domaine métier clé
|
||||||
|
|
||||||
|
### Réception (pesée pont-bascule)
|
||||||
|
- Entité principale `Reception` : `date_reception` (DateTimeImmutable, format `Y-m-d`), `identification_number` (auto `N-BR-####`), `current_step` (défaut 0), `is_valid` (défaut false).
|
||||||
|
- `Weight` (1-N avec Reception) : `type` (`gross`/`tare`), `dsd`, `weight`, `weighed_at`.
|
||||||
|
- Endpoint pesée : `/receptions/weigh` → `PontBasculeReading` (dsd, weight, weighedAt).
|
||||||
|
- Parsing payload pont-bascule : `Service/PontBasculePayloadDecoder.php`.
|
||||||
|
- Exception : `PontBasculeException` (messages en français, mappée 500).
|
||||||
|
- Store Pinia `reception.ts` = source de vérité pour la réception en cours.
|
||||||
|
- UI multi-étapes dans `pages/reception/[[id]].vue` basée sur `currentStep`.
|
||||||
|
|
||||||
|
### LIOT (transport)
|
||||||
|
- Si carrier code = `LIOT` : afficher sélecteurs driver + vehicle, masquer saisie plaque manuelle.
|
||||||
|
- Liste véhicules filtrée par type de camion et transporteur.
|
||||||
|
- Le véhicule sélectionné alimente `license_plate`.
|
||||||
|
|
||||||
|
### Bovins & infrastructure
|
||||||
|
- `Bovine` : `nationalNumber` (unique), `receivedWeight`, `arrivalDate`, `buildingCase` (ManyToOne).
|
||||||
|
- `BuildingCase` a `bovines` (OneToMany).
|
||||||
|
- Rapport PDF cases : `GET /building_cases/{id}/weights-report` → template Twig, projection depuis `arrivalDate`, gain journalier fixe `1.3 kg/jour`.
|
||||||
|
|
||||||
|
### Données de référence
|
||||||
|
- `ReceptionType`, `MerchandiseType`, `PelletType`, `Building`, `Supplier` (avec `Address` via join table), `Truck`, `Carrier`, `Driver`, `Vehicle`.
|
||||||
|
- `Address` expose `fullAddress` via getter.
|
||||||
|
|
||||||
|
### Seed & fixtures
|
||||||
|
- Commande `app:seed` : seed infrastructure (statut, building_layout, building_case, building_case_position) puis bovins.
|
||||||
|
- Utilise des flush intermédiaires pour que les queries find fonctionnent sur les records fraîchement créés.
|
||||||
|
- Fixtures : `BuildingInfrastructureFixtures` + `BovineFixtures` (via dépendances `AppFixtures`).
|
||||||
|
|
||||||
|
## Environnement
|
||||||
|
|
||||||
|
- API base dev : `http://localhost:8080/api` (via `NUXT_PUBLIC_API_BASE` dans `frontend/.env`)
|
||||||
|
- CORS : Nelmio, configurable via `CORS_ALLOW_ORIGIN` dans `.env`
|
||||||
|
- Locale par défaut : `fr` — traductions dans `frontend/i18n/locales/fr.json`
|
||||||
|
- Docker env : `docker/.env.docker` (défaut) avec override possible via `docker/.env.docker.local`
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
parameters:
|
parameters:
|
||||||
app.version: '0.0.62'
|
app.version: '0.0.69'
|
||||||
|
|||||||
@@ -1,23 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validateForm">
|
<form @submit.prevent="validateForm">
|
||||||
<div class="flex items-center justify-between gap-10">
|
<div class="flex items-center mb-11 justify-between relative">
|
||||||
<div>
|
<div class="flex flex-row absolute -left-[60px] ">
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
<Icon @click="goBack" name="gg:arrow-left-o" size="40" class="cursor-pointer text-primary-500"/>
|
||||||
{{ props.address ? "Modification d'une adresse" : "Ajout d'une adresse" }}
|
|
||||||
</h1>
|
|
||||||
</div>
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
<button
|
{{ props.address ? "Modification d'une adresse" : "Ajout d'une adresse" }}
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
</h1>
|
||||||
type="submit"
|
|
||||||
:disabled="isLoading"
|
|
||||||
>
|
|
||||||
<Icon :name="props.address ? '' : 'mdi:plus'" size="28" />
|
|
||||||
{{ props.address? "Valider" : "Ajouter" }}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-y-16 gap-x-12 mb-16 mt-10">
|
<div class="grid grid-cols-2 gap-y-16 gap-x-[200px] mb-16">
|
||||||
<UiTextInput id="address-label" v-model="form.label" label="Libellé" />
|
<UiTextInput id="address-label" v-model="form.label" label="Libellé" />
|
||||||
<UiTextInput id="address-street" v-model="form.street" label="Rue" />
|
<UiTextInput id="address-street" v-model="form.street" label="Rue" />
|
||||||
<UiTextInput id="address-street2" v-model="form.street2" label="Complément" />
|
<UiTextInput id="address-street2" v-model="form.street2" label="Complément" />
|
||||||
@@ -25,6 +17,15 @@
|
|||||||
<UiTextInput id="address-city" v-model="form.city" label="Ville" />
|
<UiTextInput id="address-city" v-model="form.city" label="Ville" />
|
||||||
<UiTextInput id="address-country" v-model="form.countryCode" label="Pays (code)" />
|
<UiTextInput id="address-country" v-model="form.countryCode" label="Pays (code)" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<UiButton
|
||||||
|
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
|
type="submit"
|
||||||
|
:disabled="isLoading"
|
||||||
|
>
|
||||||
|
Valider
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -53,6 +54,20 @@ const emptyForm = (): AddressPayload => ({
|
|||||||
|
|
||||||
const form = reactive<AddressPayload>(emptyForm())
|
const form = reactive<AddressPayload>(emptyForm())
|
||||||
|
|
||||||
|
const backPath = computed(() => {
|
||||||
|
if (props.type === "customer") {
|
||||||
|
const customerId = Number(route.query.customerId)
|
||||||
|
return Number.isFinite(customerId) && customerId > 0
|
||||||
|
? `/admin/customer/${customerId}`
|
||||||
|
: "/admin/customer/customer-list"
|
||||||
|
}
|
||||||
|
|
||||||
|
const supplierId = Number(route.query.supplierId)
|
||||||
|
return Number.isFinite(supplierId) && supplierId > 0
|
||||||
|
? `/admin/supplier/${supplierId}`
|
||||||
|
: "/admin/supplier/supplier-list"
|
||||||
|
})
|
||||||
|
|
||||||
const hydrateForm = (address?: AddressPayload | null) => {
|
const hydrateForm = (address?: AddressPayload | null) => {
|
||||||
const data = address ?? emptyForm()
|
const data = address ?? emptyForm()
|
||||||
form.label = data.label ?? ""
|
form.label = data.label ?? ""
|
||||||
@@ -76,6 +91,10 @@ const validateForm = () => {
|
|||||||
emit("validate", {...form})
|
emit("validate", {...form})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
router.push(backPath.value)
|
||||||
|
}
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: 'validate', form: AddressPayload): void
|
(event: 'validate', form: AddressPayload): void
|
||||||
}>()
|
}>()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
v-model="localWeight.weight"
|
v-model="localWeight.weight"
|
||||||
:disabled="!isAdmin"
|
:disabled="!isAdmin"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="48000"
|
|
||||||
wrapper-class="flex-col"
|
wrapper-class="flex-col"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
:is="'button'"
|
:is="'button'"
|
||||||
:type="type"
|
:type="type"
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
class="inline-flex items-center justify-center rounded-md"
|
class="inline-flex min-w-[194px] items-center justify-center rounded-md"
|
||||||
:class="[
|
:class="[
|
||||||
isDisabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer',
|
isDisabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer',
|
||||||
buttonClass
|
buttonClass
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<label
|
<label
|
||||||
v-if="label"
|
v-if="label"
|
||||||
:for="id"
|
:for="id"
|
||||||
class="font-bold uppercase text-xl text-primary-500"
|
class="font-bold uppercase text-xl text-primary-700"
|
||||||
:class="labelClass"
|
:class="labelClass"
|
||||||
>
|
>
|
||||||
{{ label }}
|
{{ label }}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
:maxlength="maxlength"
|
:maxlength="maxlength"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
class="border-b border-black text-xl py-[6px] bg-transparent text-primary-500"
|
class="border-b border-black text-xl py-[6px] bg-transparent text-primary-700"
|
||||||
:class="[
|
:class="[
|
||||||
isEmpty ? 'text-neutral-400' : 'text-black',
|
isEmpty ? 'text-neutral-400' : 'text-black',
|
||||||
disabled ? 'cursor-not-allowed' : 'cursor-text',
|
disabled ? 'cursor-not-allowed' : 'cursor-text',
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type {Ref} from 'vue'
|
|
||||||
import {computed, ref} from 'vue'
|
import {computed, ref} from 'vue'
|
||||||
import type {ReceptionData, ReceptionPayload, WeightEntryData} from '~/services/dto/reception-data'
|
import type {WeightEntryData} from '~/services/dto/reception-data'
|
||||||
import type {WeightData} from '~/services/dto/weight-data'
|
import type {WeightData} from '~/services/dto/weight-data'
|
||||||
import {getWeight} from '~/services/reception'
|
import {getWeight} from '~/services/reception'
|
||||||
import {getWeightShipment} from '~/services/shipment'
|
import {getWeightShipment} from '~/services/shipment'
|
||||||
|
|||||||
@@ -82,7 +82,10 @@
|
|||||||
"list": "Impossible de récupérer la liste des camions."
|
"list": "Impossible de récupérer la liste des camions."
|
||||||
},
|
},
|
||||||
"bovin": {
|
"bovin": {
|
||||||
"list": "Impossible de récupérer la liste des races de bovins."
|
"list": "Impossible de récupérer la liste des races de bovins.",
|
||||||
|
"fetch": "Impossible de récupérer le type bovin.",
|
||||||
|
"create": "Impossible de créer le type bovin.",
|
||||||
|
"update": "Impossible de mettre à jour le type bovin."
|
||||||
},
|
},
|
||||||
"carrier": {
|
"carrier": {
|
||||||
"list": "Impossible de récupérer la liste des transporteurs.",
|
"list": "Impossible de récupérer la liste des transporteurs.",
|
||||||
@@ -133,6 +136,10 @@
|
|||||||
"update": "Transporteur mis à jour",
|
"update": "Transporteur mis à jour",
|
||||||
"create": "Transporteur créé"
|
"create": "Transporteur créé"
|
||||||
},
|
},
|
||||||
|
"bovin": {
|
||||||
|
"update": "Type bovin mis à jour avec succès.",
|
||||||
|
"create": "Type bovin créé avec succès."
|
||||||
|
},
|
||||||
"weight": {
|
"weight": {
|
||||||
"update": "Pesée mis à jour"
|
"update": "Pesée mis à jour"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<NuxtLink
|
<NuxtLink
|
||||||
v-if="auth.isAdmin"
|
v-if="auth.isAdmin"
|
||||||
to="/admin/bovin/list"
|
to="/admin/bovin/bovin-list"
|
||||||
custom
|
custom
|
||||||
v-slot="{ href, navigate }"
|
v-slot="{ href, navigate }"
|
||||||
>
|
>
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
<NuxtLink v-if="auth.isAdmin" to="/admin/customer/customer-list" @click="closeMenu">
|
<NuxtLink v-if="auth.isAdmin" to="/admin/customer/customer-list" @click="closeMenu">
|
||||||
Clients
|
Clients
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<NuxtLink v-if="auth.isAdmin" to="/admin/bovin/list" @click="closeMenu">
|
<NuxtLink v-if="auth.isAdmin" to="/admin/bovin/bovin-list" @click="closeMenu">
|
||||||
Bovins
|
Bovins
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -1,24 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validate">
|
<form @submit.prevent="validate">
|
||||||
<div class="text-primary-500 flex items-center justify-between">
|
<div class="flex items-center justify-between relative">
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
<div class="flex flex-row absolute -left-[60px]">
|
||||||
{{ route.params.id ? 'Modifier bovin' : 'Ajout bovin' }}
|
<Icon
|
||||||
|
@click="router.push('/admin/bovin/bovin-list')"
|
||||||
|
name="gg:arrow-left-o"
|
||||||
|
size="40"
|
||||||
|
class="cursor-pointer text-primary-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
|
{{ route.params.id ? 'Modifications du type bovin' : 'Ajout d\'un type bovin' }}
|
||||||
</h1>
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-2 items-start pt-7 mb-11 gap-x-[200px]">
|
||||||
|
<UiTextInput label="Nom du bovin" id="bovin-label" v-model="form.label" />
|
||||||
|
<UiTextInput label="Code bovin" id="code-id" v-model="form.code" />
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
<UiButton
|
<UiButton
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="isLoading || isHydrating"
|
:disabled="isLoading || isHydrating"
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
class="inline-flex items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
>
|
>
|
||||||
<Icon :name="isEdit ? '' : 'mdi:plus'" size="28" />
|
Valider
|
||||||
{{ isEdit ? 'Valider' : 'Ajouter' }}
|
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 py-12">
|
|
||||||
<UiTextInput label="Nom du bovin" id="bovin-label" v-model="form.label" />
|
|
||||||
<UiTextInput label="Code bovin" id="code-id" v-model="form.code" />
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -29,6 +37,8 @@ const router = useRouter()
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isHydrating = ref(false)
|
const isHydrating = ref(false)
|
||||||
|
const idBovin = computed(() => resolveId(route.params.id))
|
||||||
|
const isEdit = computed(() => idBovin.value !== null)
|
||||||
|
|
||||||
function resolveId(param: unknown) {
|
function resolveId(param: unknown) {
|
||||||
const idStr = Array.isArray(param) ? param[0] : param
|
const idStr = Array.isArray(param) ? param[0] : param
|
||||||
@@ -37,9 +47,6 @@ function resolveId(param: unknown) {
|
|||||||
return Number.isFinite(id) ? id : null
|
return Number.isFinite(id) ? id : null
|
||||||
}
|
}
|
||||||
|
|
||||||
const idBovin = computed(() => resolveId(route.params.id))
|
|
||||||
const isEdit = computed(() => idBovin.value !== null)
|
|
||||||
|
|
||||||
const form = reactive<BovinFormData>({
|
const form = reactive<BovinFormData>({
|
||||||
label: '',
|
label: '',
|
||||||
code: ''
|
code: ''
|
||||||
@@ -92,7 +99,6 @@ async function validate() {
|
|||||||
} else {
|
} else {
|
||||||
await createBovin(basePayload)
|
await createBovin(basePayload)
|
||||||
}
|
}
|
||||||
await navigate()
|
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
67
frontend/pages/admin/bovin/bovin-list.vue
Normal file
67
frontend/pages/admin/bovin/bovin-list.vue
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex items-center justify-between ">
|
||||||
|
<h1 class="text-4xl font-bold uppercase text-primary-500">Liste des types bovins</h1>
|
||||||
|
</div>
|
||||||
|
<div class="mt-7 border border-slate-200 mb-11 ">
|
||||||
|
<div class="grid grid-cols-2 gap-4 text-primary-700 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
|
||||||
|
<div>Nom</div>
|
||||||
|
<div>Code</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!auth.isAdmin" class="px-4 py-6 text-slate-400">
|
||||||
|
Accès réservé aux administrateurs.
|
||||||
|
</div>
|
||||||
|
<div v-else-if="bovinList.length === 0" class="px-4 py-6 text-slate-400">
|
||||||
|
Aucun type de bovin.
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<div
|
||||||
|
v-for="bovin in bovinList"
|
||||||
|
:key="bovin.id"
|
||||||
|
class="grid grid-cols-2 text-primary-700 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
@click="goToBovin(bovin.id)"
|
||||||
|
@keydown.enter="goToBovin(bovin.id)"
|
||||||
|
>
|
||||||
|
<div>{{ bovin.label }}</div>
|
||||||
|
<div>{{ bovin.code }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<NuxtLink
|
||||||
|
to="/admin/bovin"
|
||||||
|
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
||||||
|
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
||||||
|
@click="handleAddClick"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getBovineTypeList } from "~/services/bovine-type"
|
||||||
|
import type { BovineTypeData } from "~/services/dto/bovine-type-data"
|
||||||
|
import { useAuthStore } from "~/stores/auth"
|
||||||
|
|
||||||
|
const bovinList = ref<BovineTypeData[]>([])
|
||||||
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
|
|
||||||
|
const goToBovin = (id: number) => {
|
||||||
|
if (!auth.isAdmin) return
|
||||||
|
router.push(`/admin/bovin/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddClick = (event: Event) => {
|
||||||
|
if (auth.isAdmin) return
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
if (!auth.isAdmin) return
|
||||||
|
bovinList.value = await getBovineTypeList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<h1 class="text-3xl font-bold text-primary-500 uppercase">Liste des types bovins</h1>
|
|
||||||
<NuxtLink
|
|
||||||
to="/admin/bovin"
|
|
||||||
class="inline-flex items-center justify-center
|
|
||||||
text-xl text-white uppercase
|
|
||||||
bg-primary-500 h-[50px] px-8 rounded
|
|
||||||
hover:opacity-80 gap-2"
|
|
||||||
@click="handleAddClick"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
|
||||||
<div v-if="auth.isAdmin" class="mt-6 border border-slate-200 mb-16">
|
|
||||||
<div class="max-h-96 overflow-y-auto">
|
|
||||||
<div
|
|
||||||
class="sticky
|
|
||||||
grid grid-cols-2 gap-4
|
|
||||||
bg-slate-100 px-4 py-3
|
|
||||||
font-semibold uppercase
|
|
||||||
tracking-wide"
|
|
||||||
>
|
|
||||||
<div class="col-span-1">Nom</div>
|
|
||||||
<div class="col-span-1">Code</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="bovinList.length === 0" class="px-4 py-6 text-slate-400">
|
|
||||||
Aucun type de bovin.
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<div
|
|
||||||
v-for="bovin in bovinList"
|
|
||||||
:key="bovin.id"
|
|
||||||
class="grid grid-cols-2 border-t gap-4 px-4 py-2 hover:bg-slate-50 cursor-pointer"
|
|
||||||
@click="goToBovin(bovin.id)"
|
|
||||||
>
|
|
||||||
<div class="col-span-1">{{ bovin.label }}</div>
|
|
||||||
<div class="col-span-1">{{ bovin.code }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-else class="mt-6 border border-slate-200 mb-16 px-4 py-6 text-slate-400">
|
|
||||||
Accès réservé aux administrateurs.
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { getBovineTypeList } from "~/services/bovine-type"
|
|
||||||
import type { BovineTypeData } from "~/services/dto/bovine-type-data"
|
|
||||||
import { useAuthStore } from "~/stores/auth"
|
|
||||||
|
|
||||||
const bovinList = ref<BovineTypeData[]>([])
|
|
||||||
const router = useRouter()
|
|
||||||
const auth = useAuthStore()
|
|
||||||
|
|
||||||
const goToBovin = (id: number) => {
|
|
||||||
if (!auth.isAdmin) return
|
|
||||||
router.push(`/admin/bovin/${id}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleAddClick = (event: Event) => {
|
|
||||||
if (auth.isAdmin) return
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
if (!auth.isAdmin) return
|
|
||||||
bovinList.value = await getBovineTypeList()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
@@ -1,32 +1,41 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validate">
|
<form @submit.prevent="validate">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between relative">
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
<div class="flex flex-row absolute -left-[60px]">
|
||||||
{{ route.params.id ? 'Modifier transporteur' : 'Ajout transporteur' }}
|
<Icon
|
||||||
</h1>
|
@click="router.push('/admin/carrier/carrier-list')"
|
||||||
|
name="gg:arrow-left-o"
|
||||||
|
size="40"
|
||||||
|
class="cursor-pointer text-primary-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
|
{{ route.params.id ? 'Modification du transporteur' : 'Ajout d\'un transporteur' }}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
<UiButton
|
<div class="grid grid-cols-2 items-start pt-7 mb-11 gap-x-[200px]">
|
||||||
type="submit"
|
<UiTextInput
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2 justify-self-end"
|
label="Nom du transporteur"
|
||||||
>
|
id="carrier-name"
|
||||||
Valider
|
v-model="form.name"
|
||||||
</UiButton>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2 items-start gap-y-8 gap-x-40 py-12">
|
<UiTextInput
|
||||||
<UiTextInput
|
label="Code transporteur"
|
||||||
label = "nom du fournisseur"
|
|
||||||
id="carrier-name"
|
|
||||||
v-model="form.name"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<UiTextInput
|
|
||||||
label = "code fournisseur"
|
|
||||||
id="code-id"
|
id="code-id"
|
||||||
v-model="form.code"
|
v-model="form.code"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<UiButton
|
||||||
|
type="submit"
|
||||||
|
class="inline-flex items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
|
>
|
||||||
|
Valider
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
@@ -92,11 +101,10 @@ async function validate() {
|
|||||||
|
|
||||||
if(idCarrier.value){
|
if(idCarrier.value){
|
||||||
await updateCarrier(idCarrier.value, basePayload)
|
await updateCarrier(idCarrier.value, basePayload)
|
||||||
navigate()
|
|
||||||
return
|
return
|
||||||
|
}else{
|
||||||
|
await createCarrier(basePayload)
|
||||||
}
|
}
|
||||||
await createCarrier(basePayload)
|
|
||||||
navigate()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigate(){
|
function navigate(){
|
||||||
|
|||||||
@@ -1,25 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="flex items-center justify-between ">
|
<div class="flex items-center justify-between ">
|
||||||
<h1 class="text-3xl font-bold uppercase text-primary-500">listes des transporteurs</h1>
|
<h1 class="text-4xl font-bold uppercase text-primary-500">listes des transporteurs</h1>
|
||||||
<NuxtLink
|
|
||||||
to="/admin/carrier"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 border border-slate-200 mb-16 ">
|
<div class="mt-7 border border-slate-200 mb-11 ">
|
||||||
<div class="grid grid-cols-2 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
|
<div class="grid grid-cols-2 gap-4 text-primary-700 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
|
||||||
<div>Label</div>
|
<div>Label</div>
|
||||||
<div>Code</div>
|
<div>Code</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-for="carrier in carrierList"
|
v-for="carrier in carrierList"
|
||||||
:key="carrier.id"
|
:key="carrier.id"
|
||||||
class="grid grid-cols-2 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
class="grid grid-cols-2 text-primary-700 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="goToCarrier(carrier.id)"
|
@click="goToCarrier(carrier.id)"
|
||||||
@@ -29,6 +22,15 @@
|
|||||||
<div>{{ carrier.code }}</div>
|
<div>{{ carrier.code }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<NuxtLink
|
||||||
|
to="/admin/carrier"
|
||||||
|
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validate">
|
<form @submit.prevent="validate">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center relative">
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
<div class="flex flex-row absolute -left-[60px] ">
|
||||||
{{ customerId ? "Modifications du client" : "Ajout d'un client" }}
|
<Icon @click="router.push('/admin/customer/customer-list')" name="gg:arrow-left-o" size="40" class="cursor-pointer text-primary-500"/>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
|
{{ customerId ? "Modification du client" : "Ajout d'un client" }}
|
||||||
</h1>
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
||||||
|
<UiTextInput id="customer-name" v-model="form.name" label="Nom du client" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
<UiTextInput id="customer-phone" v-model="form.phone" label="Téléphone" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
<UiTextInput id="customer-email" v-model="form.email" label="Email" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
<UiButton
|
<UiButton
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="isLoading || !auth.isAdmin"
|
:disabled="isLoading || !auth.isAdmin"
|
||||||
>
|
>
|
||||||
@@ -15,35 +25,19 @@
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-y-8 gap-x-80 mb-10 py-12">
|
<div class="flex items-center justify-between mb-7">
|
||||||
<UiTextInput id="customer-name" v-model="form.name" label="Nom du client" :disabled="!auth.isAdmin"/>
|
<h2 class="text-3xl text-primary-500 font-bold uppercase">Adresses du client</h2>
|
||||||
<UiTextInput id="customer-phone" v-model="form.phone" label="Téléphone" :disabled="!auth.isAdmin"/>
|
|
||||||
<UiTextInput id="customer-email" v-model="form.email" label="Email" :disabled="!auth.isAdmin"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="overflow-x-auto mb-11 text-primary-700">
|
||||||
<div class="mx-24 mb-4 py-6 border-t border-black"></div>
|
<table class="w-full border-collapse text-primary-700">
|
||||||
<div class="flex items-center justify-between mb-4">
|
|
||||||
<h2 class="text-3xl font-bold uppercase">Adresses client</h2>
|
|
||||||
<UiButton
|
|
||||||
type="button"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
:disabled="customerId === null || !auth.isAdmin"
|
|
||||||
@click="goToAddAddress"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</UiButton>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-x-auto mb-10">
|
|
||||||
<table class="w-full border-collapse">
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-left border-b border-gray-200">
|
<tr class="text-left border bg-slate-100 border-gray-200">
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Libellé</th>
|
<th class="py-3 px-4 text-sm uppercase">Libellé</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Rue</th>
|
<th class="py-3 px-4 text-sm uppercase">Rue</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Complément</th>
|
<th class="py-3 px-4 text-sm uppercase">Complément</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Code postal</th>
|
<th class="py-3 px-4 text-sm uppercase">Code postal</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Ville</th>
|
<th class="py-3 px-4 text-sm uppercase">Ville</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Pays</th>
|
<th class="py-3 px-4 text-sm uppercase">Pays</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -58,21 +52,32 @@
|
|||||||
<tr
|
<tr
|
||||||
v-for="(address, index) in form.addresses"
|
v-for="(address, index) in form.addresses"
|
||||||
:key="address.id ?? index"
|
:key="address.id ?? index"
|
||||||
class="border-b border-gray-100 hover:bg-slate-50"
|
class="border border-gray-100 hover:bg-slate-50"
|
||||||
:class="auth.isAdmin ? 'cursor-pointer' : 'cursor-not-allowed opacity-60'"
|
:class="auth.isAdmin ? 'cursor-pointer' : 'cursor-not-allowed opacity-60'"
|
||||||
@click="goToEditAddress(address.id ?? null)"
|
@click="goToEditAddress(address.id ?? null)"
|
||||||
>
|
>
|
||||||
<td class="py-3 pr-4">{{ address.label || "—" }}</td>
|
<td class="py-3 px-4">{{ address.label || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.street || "—" }}</td>
|
<td class="py-3 px-4">{{ address.street || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.street2 || "—" }}</td>
|
<td class="py-3 px-4">{{ address.street2 || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.postalCode || "—" }}</td>
|
<td class="py-3 px-4">{{ address.postalCode || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.city || "—" }}</td>
|
<td class="py-3 px-4">{{ address.city || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.countryCode || "—" }}</td>
|
<td class="py-3 px-4">{{ address.countryCode || "—" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<UiButton
|
||||||
|
type="button"
|
||||||
|
class="inline-flex items-center justify-center text-xl gap-2 text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
|
:disabled="customerId === null || !auth.isAdmin"
|
||||||
|
@click="goToAddAddress"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,10 @@ const addressId = computed(() => (route.query.addressId !== undefined ? Number(r
|
|||||||
const address = ref<AddressData | null>(null)
|
const address = ref<AddressData | null>(null)
|
||||||
|
|
||||||
const validate = async (payload: AddressPayload) => {
|
const validate = async (payload: AddressPayload) => {
|
||||||
try {
|
if (addressId.value !== null) {
|
||||||
if (addressId.value !== null) {
|
await updateAddress(addressId.value, payload)
|
||||||
await updateAddress(addressId.value, payload)
|
} else {
|
||||||
} else {
|
await addAddress(payload)
|
||||||
await addAddress(payload)
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
await router.push("/admin/customer/" + customerId.value)
|
await router.push("/admin/customer/" + customerId.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h1 class="text-3xl font-bold uppercase text-primary-500">Liste des Clients</h1>
|
<h1 class="text-4xl font-bold uppercase text-primary-500">Liste des clients</h1>
|
||||||
<NuxtLink
|
|
||||||
to="/admin/customer"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
|
||||||
@click="handleAddClick"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="auth.isAdmin" class="mt-6 border border-slate-200 mb-16">
|
<div v-if="auth.isAdmin" class="mt-7 border border-slate-200 mb-11">
|
||||||
<div class="max-h-96 overflow-y-auto">
|
<div class="max-h-96 overflow-y-auto">
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 grid grid-cols-8 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"
|
class="sticky text-primary-700 top-0 z-10 grid grid-cols-8 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"
|
||||||
>
|
>
|
||||||
<div>Nom</div>
|
<div>Nom</div>
|
||||||
<div>Téléphone</div>
|
<div>Téléphone</div>
|
||||||
@@ -34,7 +25,7 @@
|
|||||||
<div v-for="customer in customerList" :key="customer.id">
|
<div v-for="customer in customerList" :key="customer.id">
|
||||||
<div
|
<div
|
||||||
v-if="!customer.addresses || customer.addresses.length === 0"
|
v-if="!customer.addresses || customer.addresses.length === 0"
|
||||||
class="grid grid-cols-8 border-t gap-4 px-4 py-2 hover:bg-slate-50 cursor-pointer"
|
class="grid text-primary-700 grid-cols-8 border-t gap-4 px-4 py-2 hover:bg-slate-50 cursor-pointer"
|
||||||
@click="goToCustomer(customer.id)"
|
@click="goToCustomer(customer.id)"
|
||||||
>
|
>
|
||||||
<div class="truncate">{{ customer.name || "—" }}</div>
|
<div class="truncate">{{ customer.name || "—" }}</div>
|
||||||
@@ -51,7 +42,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(address, idx) in customer.addresses"
|
v-for="(address, idx) in customer.addresses"
|
||||||
:key="address.id ?? `${customer.id}-${idx}-${address.street}-${address.postalCode}`"
|
:key="address.id ?? `${customer.id}-${idx}-${address.street}-${address.postalCode}`"
|
||||||
class="grid grid-cols-8 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
class="grid grid-cols-8 text-primary-700 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
||||||
:class="idx > 0 ? 'pl-4 border-l-4 border-l-slate-200 bg-slate-50' : ''"
|
:class="idx > 0 ? 'pl-4 border-l-4 border-l-slate-200 bg-slate-50' : ''"
|
||||||
@click="goToCustomer(customer.id)"
|
@click="goToCustomer(customer.id)"
|
||||||
>
|
>
|
||||||
@@ -70,7 +61,7 @@
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-8 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
class="grid grid-cols-8 text-primary-700 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
||||||
@click="goToCustomer(customer.id)"
|
@click="goToCustomer(customer.id)"
|
||||||
>
|
>
|
||||||
<div class="truncate">{{ customer.name || "—" }}</div>
|
<div class="truncate">{{ customer.name || "—" }}</div>
|
||||||
@@ -84,9 +75,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="mt-6 border border-slate-200 mb-16 px-4 py-6 text-slate-400">
|
<div v-else class="mt-7 border border-slate-200 mb-11 px-4 py-6 text-slate-400">
|
||||||
Accès réservé aux administrateurs.
|
Accès réservé aux administrateurs.
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<NuxtLink
|
||||||
|
to="/admin/customer"
|
||||||
|
class="inline-flex items-center mb-16 justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
||||||
|
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
||||||
|
@click="handleAddClick"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validate">
|
<form @submit.prevent="validate">
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
|
||||||
{{ supplierId ? "Modifications du fournisseur" : "Ajout d'un fournisseur" }}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<div class="flex flex-row absolute -left-[60px] ">
|
||||||
|
<Icon @click="router.push('/admin/supplier/supplier-list')" name="gg:arrow-left-o" size="40" class="cursor-pointer text-primary-500"/>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
|
{{ supplierId ? "Modification du fournisseur" : "Ajout d'un fournisseur" }}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
||||||
|
<UiTextInput id="supplier-name" v-model="form.name" label="Nom du fournisseur" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
<UiTextInput id="supplier-email" v-model="form.email" label="Email" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
<UiTextInput id="supplier-phone" v-model="form.phone" label="Téléphone" :disabled="!auth.isAdmin" wrapper-class="w-[280px]"/>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
<UiButton
|
<UiButton
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
type="submit"
|
type="submit"
|
||||||
:disabled="isLoading || !auth.isAdmin"
|
:disabled="isLoading || !auth.isAdmin"
|
||||||
>
|
>
|
||||||
@@ -15,35 +26,19 @@
|
|||||||
</UiButton>
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-y-8 gap-x-80 mb-10 py-12">
|
<div class="flex items-center justify-between mb-7">
|
||||||
<UiTextInput id="supplier-name" v-model="form.name" label="Nom du fournisseur" :disabled="!auth.isAdmin"/>
|
<h2 class="text-3xl text-primary-500 font-bold uppercase">Adresses du fournisseur</h2>
|
||||||
<UiTextInput id="supplier-email" v-model="form.email" label="Email" :disabled="!auth.isAdmin"/>
|
|
||||||
<UiTextInput id="supplier-phone" v-model="form.phone" label="Téléphone" :disabled="!auth.isAdmin"/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="overflow-x-auto mb-11 text-primary-700">
|
||||||
<div class="mx-24 mb-4 py-6 border-t border-black"></div>
|
|
||||||
<div class="flex items-center justify-between mb-4">
|
|
||||||
<h2 class="text-3xl font-bold uppercase">Adresses fournisseur</h2>
|
|
||||||
<UiButton
|
|
||||||
type="button"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
:disabled="supplierId === null || !auth.isAdmin"
|
|
||||||
@click="goToAddAddress"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</UiButton>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-x-auto mb-10">
|
|
||||||
<table class="w-full border-collapse">
|
<table class="w-full border-collapse">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-left border-b border-gray-200">
|
<tr class="text-left border bg-slate-100 border-gray-200">
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Libellé</th>
|
<th class="py-3 px-4 text-sm uppercase">Libellé</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Rue</th>
|
<th class="py-3 px-4 text-sm uppercase">Rue</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Complément</th>
|
<th class="py-3 px-4 text-sm uppercase">Complément</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Code postal</th>
|
<th class="py-3 px-4 text-sm uppercase">Code postal</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Ville</th>
|
<th class="py-3 px-4 text-sm uppercase">Ville</th>
|
||||||
<th class="py-3 pr-4 text-sm uppercase">Pays</th>
|
<th class="py-3 px-4 text-sm uppercase">Pays</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -58,21 +53,32 @@
|
|||||||
<tr
|
<tr
|
||||||
v-for="(address, index) in form.addresses"
|
v-for="(address, index) in form.addresses"
|
||||||
:key="address.id ?? index"
|
:key="address.id ?? index"
|
||||||
class="border-b border-gray-100 hover:bg-slate-50"
|
class="border border-gray-100 hover:bg-slate-50"
|
||||||
:class="auth.isAdmin ? 'cursor-pointer' : 'cursor-not-allowed opacity-60'"
|
:class="auth.isAdmin ? 'cursor-pointer' : 'cursor-not-allowed opacity-60'"
|
||||||
@click="goToEditAddress(address.id ?? null)"
|
@click="goToEditAddress(address.id ?? null)"
|
||||||
>
|
>
|
||||||
<td class="py-3 pr-4">{{ address.label || "—" }}</td>
|
<td class="py-3 px-4">{{ address.label || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.street || "—" }}</td>
|
<td class="py-3 px-4">{{ address.street || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.street2 || "—" }}</td>
|
<td class="py-3 px-4">{{ address.street2 || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.postalCode || "—" }}</td>
|
<td class="py-3 px-4">{{ address.postalCode || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.city || "—" }}</td>
|
<td class="py-3 px-4">{{ address.city || "—" }}</td>
|
||||||
<td class="py-3 pr-4">{{ address.countryCode || "—" }}</td>
|
<td class="py-3 px-4">{{ address.countryCode || "—" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<UiButton
|
||||||
|
type="button"
|
||||||
|
class="inline-flex items-center justify-center text-xl gap-2 text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
|
:disabled="supplierId === null || !auth.isAdmin"
|
||||||
|
@click="goToAddAddress"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</UiButton>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,12 @@ const addressId = computed(() => { return route.query.addressId !== undefined ?
|
|||||||
const address = ref<AddressData|null>(null)
|
const address = ref<AddressData|null>(null)
|
||||||
|
|
||||||
const validate = async (address: AddressPayload) => {
|
const validate = async (address: AddressPayload) => {
|
||||||
try {
|
|
||||||
if (addressId.value !== null) {
|
if (addressId.value !== null) {
|
||||||
await updateAddress(addressId.value, address)
|
await updateAddress(addressId.value, address)
|
||||||
} else {
|
} else {
|
||||||
await addAddress(address)
|
await addAddress(address)
|
||||||
|
await router.push('/admin/supplier/' + supplierId.value)
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
await router.push('/admin/supplier/' + supplierId.value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const addAddress = async (address: AddressPayload) => {
|
const addAddress = async (address: AddressPayload) => {
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h1 class="text-3xl font-bold uppercase text-primary-500">Liste des fournisseurs</h1>
|
<h1 class="text-4xl font-bold uppercase text-primary-500">Liste des fournisseurs</h1>
|
||||||
<NuxtLink
|
|
||||||
to="/admin/supplier"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
|
||||||
@click="handleAddClick"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="auth.isAdmin" class="mt-6 border border-slate-200 mb-16">
|
<div v-if="auth.isAdmin" class="mt-7 border border-slate-200 mb-11">
|
||||||
<div class="max-h-96 overflow-y-auto">
|
<div class="max-h-96 overflow-y-auto">
|
||||||
<div
|
<div
|
||||||
class="sticky top-0 z-10 grid grid-cols-7 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"
|
class="sticky text-primary-700 top-0 z-10 grid grid-cols-7 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide"
|
||||||
>
|
>
|
||||||
<div>Nom</div>
|
<div>Nom</div>
|
||||||
<div>Mail</div>
|
<div>Mail</div>
|
||||||
@@ -33,7 +24,7 @@
|
|||||||
<div v-for="supplier in supplierList" :key="supplier.id">
|
<div v-for="supplier in supplierList" :key="supplier.id">
|
||||||
<div
|
<div
|
||||||
v-if="!supplier.addresses || supplier.addresses.length === 0"
|
v-if="!supplier.addresses || supplier.addresses.length === 0"
|
||||||
class="grid grid-cols-7 border-t gap-4 px-4 py-2 hover:bg-slate-50 cursor-pointer"
|
class="grid text-primary-700 grid-cols-7 border-t gap-4 px-4 py-2 hover:bg-slate-50 cursor-pointer"
|
||||||
@click="goToSupplier(supplier.id)"
|
@click="goToSupplier(supplier.id)"
|
||||||
>
|
>
|
||||||
<div class="truncate">{{ supplier.name }}</div>
|
<div class="truncate">{{ supplier.name }}</div>
|
||||||
@@ -49,7 +40,7 @@
|
|||||||
<div
|
<div
|
||||||
v-for="(address, idx) in supplier.addresses"
|
v-for="(address, idx) in supplier.addresses"
|
||||||
:key="address.id ?? `${supplier.id}-${idx}-${address.street}-${address.postalCode}`"
|
:key="address.id ?? `${supplier.id}-${idx}-${address.street}-${address.postalCode}`"
|
||||||
class="grid grid-cols-7 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
class="grid grid-cols-7 text-primary-700 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
||||||
:class="idx > 0 ? 'pl-4 border-l-4 border-l-slate-200 bg-slate-50' : ''"
|
:class="idx > 0 ? 'pl-4 border-l-4 border-l-slate-200 bg-slate-50' : ''"
|
||||||
@click="goToSupplier(supplier.id)"
|
@click="goToSupplier(supplier.id)"
|
||||||
>
|
>
|
||||||
@@ -67,7 +58,7 @@
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-7 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
class="grid grid-cols-7 text-primary-700 hover:bg-slate-50 border-t gap-4 px-4 py-2 cursor-pointer"
|
||||||
@click="goToSupplier(supplier.id)"
|
@click="goToSupplier(supplier.id)"
|
||||||
>
|
>
|
||||||
<div class="truncate">{{ supplier.name }}</div>
|
<div class="truncate">{{ supplier.name }}</div>
|
||||||
@@ -80,9 +71,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="mt-6 border border-slate-200 mb-16 px-4 py-6 text-slate-400">
|
<div v-else class="mt-7 border border-slate-200 mb-11 px-4 py-6 text-slate-400">
|
||||||
Accès réservé aux administrateurs.
|
Accès réservé aux administrateurs.
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<NuxtLink
|
||||||
|
to="/admin/supplier"
|
||||||
|
class="inline-flex items-center mb-16 justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
||||||
|
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
||||||
|
@click="handleAddClick"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|||||||
@@ -1,51 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.prevent="validate">
|
<form @submit.prevent="validate">
|
||||||
<div
|
<div class="flex items-center relative">
|
||||||
class="flex items-center justify-between gap-10">
|
<div class="flex flex-row absolute -left-[60px]">
|
||||||
<h1 class="text-3xl font-bold uppercase">
|
<Icon
|
||||||
{{ userId ? "Modifications de l'utilisateur" : "Ajout d'un utilisateur" }}
|
@click="router.push('/admin/user/list')"
|
||||||
|
name="gg:arrow-left-o"
|
||||||
|
size="40"
|
||||||
|
class="cursor-pointer text-primary-500"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h1 class="text-3xl text-primary-500 font-bold uppercase">
|
||||||
|
{{ userId ? "Modification de l'utilisateur" : "Ajout d'un utilisateur" }}
|
||||||
</h1>
|
</h1>
|
||||||
<UiButton
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
type="submit"
|
|
||||||
>
|
|
||||||
<Icon :name="userId ? '' : 'mdi:plus'" size="28" />
|
|
||||||
{{ userId ? 'Valider' : 'Ajouter' }}
|
|
||||||
</UiButton>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-y-16 gap-x-40 py-12">
|
<div class="flex flex-cols-3 justify-between mb-11 pt-7">
|
||||||
<UiTextInput
|
<UiTextInput
|
||||||
id="user-name"
|
id="user-name"
|
||||||
v-model="form.username"
|
v-model="form.username"
|
||||||
label="Nom de l'utilisateur"
|
label="Nom de l'utilisateur"
|
||||||
|
:disabled="!auth.isAdmin"
|
||||||
|
wrapper-class="w-[280px]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UiSelect
|
<UiSelect
|
||||||
id="user-role"
|
id="user-role"
|
||||||
v-model="form.role"
|
v-model="form.role"
|
||||||
label="Rôle de l'utilisateur"
|
label="Role de l'utilisateur"
|
||||||
:options="ROLE"
|
:options="ROLE"
|
||||||
|
:disabled="!auth.isAdmin"
|
||||||
|
wrapper-class="w-[280px]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UiTextInput
|
<UiTextInput
|
||||||
id="user-password"
|
id="user-password"
|
||||||
v-model="form.password"
|
v-model="form.password"
|
||||||
label="Mot de passe"
|
label="Mot de passe"
|
||||||
type="password"
|
type="password"
|
||||||
|
:disabled="!auth.isAdmin"
|
||||||
|
wrapper-class="w-[280px]"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<UiButton
|
||||||
|
class="inline-flex mb-28 items-center justify-center text-xl min-w-[194px] text-white uppercase bg-primary-500 h-[50px] rounded hover:opacity-80 justify-self-end"
|
||||||
|
type="submit"
|
||||||
|
:disabled="isLoading || isHydrating || !auth.isAdmin"
|
||||||
|
>
|
||||||
|
<Icon :name="userId ? '' : 'mdi:plus'" size="28" />
|
||||||
|
{{ userId ? 'Valider' : 'Ajouter' }}
|
||||||
|
</UiButton>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {computed, reactive, ref, watch} from 'vue'
|
import { computed, reactive, ref, watch } from 'vue'
|
||||||
import {ROLE} from '~/utils/constants'
|
import { ROLE } from '~/utils/constants'
|
||||||
import {createUser, updateUser, getUser} from '~/services/auth'
|
import { createUser, updateUser, getUser } from '~/services/auth'
|
||||||
import type {UserData, UserFormData, UserPayload} from '~/services/dto/user-data'
|
import type { UserData, UserFormData, UserPayload } from '~/services/dto/user-data'
|
||||||
|
import { useAuthStore } from '~/stores/auth'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
const userId = computed(() => resolveUserId(route.params.id))
|
const userId = computed(() => resolveUserId(route.params.id))
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isHydrating = ref(false)
|
const isHydrating = ref(false)
|
||||||
@@ -59,7 +78,6 @@ const resolveUserId = (param: unknown) => {
|
|||||||
return Number.isFinite(id) ? id : null
|
return Number.isFinite(id) ? id : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const form = reactive<UserFormData>({
|
const form = reactive<UserFormData>({
|
||||||
username: '',
|
username: '',
|
||||||
password: '',
|
password: '',
|
||||||
@@ -73,8 +91,8 @@ const hydrateFromUser = (user: UserData | null) => {
|
|||||||
isHydrating.value = true
|
isHydrating.value = true
|
||||||
form.username = user.username ?? ''
|
form.username = user.username ?? ''
|
||||||
const roles = user.roles ?? []
|
const roles = user.roles ?? []
|
||||||
const hasAdmin = roles.includes("ROLE_ADMIN")
|
const hasAdmin = roles.includes('ROLE_ADMIN')
|
||||||
form.role = hasAdmin ? "ROLE_ADMIN" : "ROLE_USER"
|
form.role = hasAdmin ? 'ROLE_ADMIN' : 'ROLE_USER'
|
||||||
form.password = ''
|
form.password = ''
|
||||||
isHydrating.value = false
|
isHydrating.value = false
|
||||||
}
|
}
|
||||||
@@ -93,10 +111,11 @@ watch(
|
|||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{immediate: true}
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
async function validate() {
|
async function validate() {
|
||||||
|
if (!auth.isAdmin) return
|
||||||
|
|
||||||
const normalizedUsername = form.username.trim()
|
const normalizedUsername = form.username.trim()
|
||||||
const normalizedRole = form.role.trim()
|
const normalizedRole = form.role.trim()
|
||||||
@@ -112,13 +131,12 @@ async function validate() {
|
|||||||
|
|
||||||
if (userId.value) {
|
if (userId.value) {
|
||||||
await updateUser(userId.value, basePayload)
|
await updateUser(userId.value, basePayload)
|
||||||
await router.push(`/admin/user/list/`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const created = await createUser(basePayload)
|
const created = await createUser(basePayload)
|
||||||
if (created) {
|
if (created) {
|
||||||
await router.push(`/admin/user/list/`)
|
await router.push('/admin/user/list')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,58 +1,72 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h1 class="text-3xl font-bold uppercase text-primary-500">Liste des utilisateurs</h1>
|
<h1 class="text-4xl font-bold uppercase text-primary-500">Liste des utilisateurs</h1>
|
||||||
<NuxtLink
|
|
||||||
to="/admin/user"
|
|
||||||
class="inline-flex items-center justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
|
||||||
>
|
|
||||||
<Icon name="mdi:plus" size="28" />
|
|
||||||
Ajouter
|
|
||||||
</NuxtLink>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div v-if="auth.isAdmin" class="mt-7 border border-slate-200 mb-11">
|
||||||
<div class="mt-6 border border-slate-200 mb-16 ">
|
<div class="grid grid-cols-2 text-primary-700 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
|
||||||
<div class="grid grid-cols-3 gap-4 bg-slate-100 px-4 py-3 text-sm font-semibold uppercase tracking-wide">
|
<div>Utilisateur</div>
|
||||||
<div>Username</div>
|
<div>Role</div>
|
||||||
<div>Role</div>
|
</div>
|
||||||
</div>
|
<div v-if="userList.length === 0" class="px-4 py-6 text-slate-400">
|
||||||
|
Aucun utilisateur.
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
v-for="user in userList"
|
v-for="user in userList"
|
||||||
:key="user.id"
|
:key="user.id"
|
||||||
class="grid grid-cols-3 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t items-center"
|
class="grid grid-cols-2 text-primary-700 gap-4 px-4 py-3 text-sm hover:bg-slate-50 cursor-pointer border-t border-slate-200 items-center"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@click="goToUser(user.id)"
|
@click="goToUser(user.id)"
|
||||||
|
@keydown.enter="goToUser(user.id)"
|
||||||
>
|
>
|
||||||
<div>
|
<div>{{ user.username }}</div>
|
||||||
{{ user.username }}
|
<div>{{ getRoleLabels(user.roles) }}</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{{ getRoleLabels(user.roles) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-else class="mt-7 border border-slate-200 mb-11 px-4 py-6 text-slate-400">
|
||||||
|
Acces reserve aux administrateurs.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-center items-center">
|
||||||
|
<NuxtLink
|
||||||
|
to="/admin/user"
|
||||||
|
class="inline-flex items-center mb-16 justify-center text-xl text-white uppercase bg-primary-500 h-[50px] px-8 rounded hover:opacity-80 gap-2"
|
||||||
|
:class="auth.isAdmin ? '' : 'cursor-not-allowed opacity-60'"
|
||||||
|
@click="handleAddClick"
|
||||||
|
>
|
||||||
|
<Icon name="mdi:plus" size="28" />
|
||||||
|
Ajouter
|
||||||
|
</NuxtLink>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {UserData} from "~/services/dto/user-data";
|
import type { UserData } from "~/services/dto/user-data"
|
||||||
import {getAdminUsers} from "~/services/auth";
|
import { getAdminUsers } from "~/services/auth"
|
||||||
import {ROLE} from "~/utils/constants";
|
import { ROLE } from "~/utils/constants"
|
||||||
|
import { useAuthStore } from "~/stores/auth"
|
||||||
|
|
||||||
const userList = ref<UserData[]>([])
|
const userList = ref<UserData[]>([])
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const auth = useAuthStore()
|
||||||
const roleLabelByValue = new Map(ROLE.map((role) => [role.value, role.label]))
|
const roleLabelByValue = new Map(ROLE.map((role) => [role.value, role.label]))
|
||||||
|
|
||||||
const goToUser = (id: number) => {
|
const goToUser = (id: number) => {
|
||||||
|
if (!auth.isAdmin) return
|
||||||
router.push(`/admin/user/${id}`)
|
router.push(`/admin/user/${id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAddClick = (event: Event) => {
|
||||||
|
if (auth.isAdmin) return
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
|
||||||
const getRoleLabels = (roles?: string[]) => {
|
const getRoleLabels = (roles?: string[]) => {
|
||||||
if (!roles || roles.length === 0) {
|
if (!roles || roles.length === 0) {
|
||||||
return ' ---'
|
return '---'
|
||||||
}
|
}
|
||||||
|
|
||||||
return roles
|
return roles
|
||||||
@@ -61,6 +75,7 @@ const getRoleLabels = (roles?: string[]) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
if (!auth.isAdmin) return
|
||||||
userList.value = await getAdminUsers()
|
userList.value = await getAdminUsers()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,19 +24,27 @@ export async function getBovineTypeList(): Promise<BovineTypeData[]> {
|
|||||||
|
|
||||||
export async function getBovin(id: number): Promise<BovineTypeData> {
|
export async function getBovin(id: number): Promise<BovineTypeData> {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
const response = await api.get<BovineTypeData>(`bovine_types/${id}`)
|
const response = await api.get<BovineTypeData>(`bovine_types/${id}`, {}, {
|
||||||
|
toastErrorKey: 'errors.bovin.fetch'
|
||||||
|
})
|
||||||
return mapToBovineTypeData(response)
|
return mapToBovineTypeData(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createBovin(payload: BovinPayload = {}): Promise<BovineTypeData> {
|
export async function createBovin(payload: BovinPayload = {}): Promise<BovineTypeData> {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
const response = await api.post<BovineTypeData>('bovine_types', toBovineTypePayload(payload))
|
const response = await api.post<BovineTypeData>('bovine_types', toBovineTypePayload(payload), {
|
||||||
|
toastErrorKey: 'errors.bovin.create',
|
||||||
|
toastSuccessKey: 'success.bovin.create'
|
||||||
|
})
|
||||||
return mapToBovineTypeData(response)
|
return mapToBovineTypeData(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateBovin(id: number, payload: BovinPayload = {}): Promise<BovineTypeData> {
|
export async function updateBovin(id: number, payload: BovinPayload = {}): Promise<BovineTypeData> {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
const response = await api.patch<BovineTypeData>(`bovine_types/${id}`, toBovineTypePayload(payload))
|
const response = await api.patch<BovineTypeData>(`bovine_types/${id}`, toBovineTypePayload(payload), {
|
||||||
|
toastErrorKey: 'errors.bovin.update',
|
||||||
|
toastSuccessKey: 'success.bovin.update'
|
||||||
|
})
|
||||||
return mapToBovineTypeData(response)
|
return mapToBovineTypeData(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -748,6 +748,36 @@ class SeedCommand extends Command
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'EARL DE LA MENAUDIERE',
|
||||||
|
'email' => 'frederic.doussineau@orange.fr',
|
||||||
|
'phone' => '0675446004',
|
||||||
|
'addresses' => [
|
||||||
|
[
|
||||||
|
'label' => 'EARL DE LA MENAUDIERE',
|
||||||
|
'street' => '1 la menaudière',
|
||||||
|
'street2' => null,
|
||||||
|
'postalCode' => '86450',
|
||||||
|
'city' => 'LEIGNE LES BOIS ',
|
||||||
|
'countryCode' => 'FR',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'SARL ERBS',
|
||||||
|
'email' => 'touillet.jacques@yahoo.fr',
|
||||||
|
'phone' => '0675030304',
|
||||||
|
'addresses' => [
|
||||||
|
[
|
||||||
|
'label' => 'SARL ERBS',
|
||||||
|
'street' => 'les rodières ',
|
||||||
|
'street2' => null,
|
||||||
|
'postalCode' => '86230',
|
||||||
|
'city' => 'Sérigny',
|
||||||
|
'countryCode' => 'FR',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($suppliers as $supplierData) {
|
foreach ($suppliers as $supplierData) {
|
||||||
|
|||||||
@@ -311,6 +311,36 @@ class ReferenceFixtures extends Fixture
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'name' => 'EARL DE LA MENAUDIERE',
|
||||||
|
'email' => 'frederic.doussineau@orange.fr',
|
||||||
|
'phone' => '0675446004',
|
||||||
|
'addresses' => [
|
||||||
|
[
|
||||||
|
'label' => 'EARL DE LA MENAUDIERE',
|
||||||
|
'street' => '1 la menaudière',
|
||||||
|
'street2' => null,
|
||||||
|
'postalCode' => '86450',
|
||||||
|
'city' => 'LEIGNE LES BOIS ',
|
||||||
|
'countryCode' => 'FR',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'name' => 'SARL ERBS',
|
||||||
|
'email' => 'touillet.jacques@yahoo.fr',
|
||||||
|
'phone' => '0675030304',
|
||||||
|
'addresses' => [
|
||||||
|
[
|
||||||
|
'label' => 'SARL ERBS',
|
||||||
|
'street' => 'les rodières ',
|
||||||
|
'street2' => null,
|
||||||
|
'postalCode' => '86230',
|
||||||
|
'city' => 'Sérigny',
|
||||||
|
'countryCode' => 'FR',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($suppliers as $supplierData) {
|
foreach ($suppliers as $supplierData) {
|
||||||
|
|||||||
Reference in New Issue
Block a user