project creation request form working

This commit is contained in:
isUnknown 2025-01-23 15:31:15 +01:00
parent 6c84f723f7
commit c750001a2c
14 changed files with 194 additions and 89 deletions

View file

@ -14,6 +14,15 @@ tabs:
columns:
- width: 1/1
fields:
isClientRequest:
type: hidden
default: "false"
requestDetails:
label: Demande client
type: textarea
disabled: true
when:
isClientRequest: "true"
currentStep:
label: Étape en cours
type: radio

View file

@ -1,40 +1,34 @@
title: Site
title: Projets
tabs:
dashboard:
label: Dashboard
icon: dashboard
contentTab:
label: Contenu
columns:
- width: 1/1
sections:
drafts:
extends: sections/projects
headline: Brouillons
status: draft
- width: 1/1
sections:
listed:
extends: sections/projects
headline: Projets en cours
headline: En cours
query: user.currentProjects
sortBy: modified desc
- width: 1/1
sections:
unlisted:
extends: sections/projects
headline: Projets archivés
headline: Archivés
query: user.archivedProjects
sortBy: modified desc
settings:
label: Paramètres
label: Réglages
icon: cog
columns:
- width: 1/1
sections:
settings:
label: Paramètres
type: fields
fields:
description:
label: Description
type: text
max: 160
help: Description en une phrase du service
moodboardTags:
label: Tags des images de Brief client
help: Ensemble des tags dimages disponibles lors de la création du Brief client
type: tags
fields:
clientBriefImageTags:
label: Tags des images ajoutées aux briefs
type: tags

View file

@ -1,11 +0,0 @@
title: Client
description: Ne peut pas accéder au Panel, peut accéder aux Projets auxquels il est assigné côté front.
permissions:
access:
panel: false
fields:
projects:
label: Projets
type: pages
query: page('projects').children

View file

@ -1,21 +0,0 @@
title: Interne Pochet
description: Peux accéder au Panel mais pas aux Utilisateurs, peut accéder aux Projets auxquels il est assigné par un Admin.
home: /panel/pages/projects
permissions:
access:
users: false
fields:
job:
label: Métier
type: select
options:
- Project Manager
- Sales Manager
default: Project Panager
width: 1/4
projects:
label: Projets
type: pages
query: page('projects').children
width: 3/4

View file

@ -5,7 +5,18 @@ permissions:
panel: false
fields:
client:
type: pages
multiple: false
query: site.find("clients").childrenAndDrafts
subpages: false
image:
query: page.logo.toFile
layout: cardlets
required: true
width: 1/3
projects:
label: Projets
type: pages
query: page('projects').children
width: 2/3

View file

@ -28,6 +28,7 @@ return [
require(__DIR__ . '/routes/remove-file.php'),
require(__DIR__ . '/routes/upload-pdf.php'),
require(__DIR__ . '/routes/validate-brief.php'),
require(__DIR__ . '/routes/request-project-creation.php'),
],
'hooks' => [
'page.create:after' => require_once(__DIR__ . '/hooks/create-steps.php'),

View file

@ -0,0 +1,37 @@
<?php
return [
'pattern' => 'request-project-creation.json',
'method' => 'POST',
'action' => function () {
$json = file_get_contents('php://input');
$data = json_decode($json);
$client = kirby()->user()->client()->toPage()->uuid();
$projectData = [
"slug" => esc(Str::slug($data->title)),
"template" => "project",
"content" => [
"title" => esc($data->title),
"requestDetails" => esc("Demande de " . kirby()->user()->name() . " (" . kirby()->user()->email() . ") : \n\n" . $data->details),
"client" => [$client],
"isClientRequest" => "true",
"isDTLEnabled" => esc($data->isDTLEnabled)
]
];
$projects = page("projects");
try {
$projects->createChild($projectData);
return [
"status" => "success",
];
} catch (\Throwable $th) {
return [
"status" => "error",
"message" => $th->getMessage() . " in " . $th->getFile() . " line " . $th->getLine()
];
}
}
];

View file

@ -4,28 +4,12 @@
<Menu />
<RouterView />
</div>
<DTLPanel v-if="isDTLPanelOpen" @close="isDTLPanelOpen = false" />
<DTLButton
v-if="page?.designToLight?.length > 0"
@click="openDTLPanel($event)"
/>
</template>
<script setup>
import { storeToRefs } from "pinia";
import Menu from "./components/Menu.vue";
import { usePageStore } from "./stores/page";
import DTLButton from "./components/design-to-light/DTLButton.vue";
import DTLPanel from "./components/design-to-light/DTLPanel.vue";
import { ref } from "vue";
const { page } = storeToRefs(usePageStore());
const isDTLPanelOpen = ref(false);
// Functions
function openDTLPanel(event) {
isDTLPanelOpen.value = true;
event.stopImmediatePropagation();
}
</script>

View file

@ -1,11 +0,0 @@
<template>
<button :data-size="size">Label</button>
</template>
<script setup>
const { size } = defineProps({
size: String,
});
</script>
<style scoped></style>

View file

@ -0,0 +1,11 @@
<template>
<button class="btn">Demander la création d'un projet</button>
</template>
<style scoped>
button {
position: fixed;
bottom: 0;
right: 0;
}
</style>

View file

@ -0,0 +1,61 @@
<template>
<form @submit.prevent="handleSubmit">
<input type="text" v-model="title" placeholder="Nom du projet" required />
<textarea
name="details"
v-model="details"
cols="30"
rows="10"
placeholder="Détails du projet"
required
></textarea>
<input type="checkbox" v-model="isDTLEnabled" />
<button type="submit">Soumettre</button>
</form>
</template>
<script setup>
import { ref } from "vue";
import { useApiStore } from "../stores/api";
const title = ref("");
const details = ref("");
const isDTLEnabled = ref(false);
const api = useApiStore();
async function handleSubmit() {
const formData = {
title: title.value,
details: details.value,
isDTLEnabled: isDTLEnabled.value,
};
const response = await api.requestProjectCreation(formData);
}
</script>
<style scoped>
form {
position: fixed;
top: 0;
bottom: 0;
z-index: 999;
background-color: #000;
color: #fff;
}
button {
color: #fff;
}
input,
textarea {
background-color: #fff;
color: #000;
}
input[type="checkbox"] {
width: 1rem;
height: 1rem;
}
</style>

View file

@ -75,6 +75,28 @@ export const useApiStore = defineStore("api", () => {
}
}
async function requestProjectCreation(data) {
const headers = {
method: "POST",
body: JSON.stringify(data),
};
try {
const response = await fetch("/request-project-creation.json", headers);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error(
"Une erreur s'est produite lors de l'ajout du commentaire :",
error
);
throw error;
}
}
async function updateComment(comment) {
const headers = {
method: "POST",
@ -144,12 +166,6 @@ export const useApiStore = defineStore("api", () => {
}
}
/**
*
* @param {string} comment
* @param {string} projectId UUID or URI
* @returns status with message if error
*/
async function readNotification(notificationId, projectId) {
const headers = {
method: "POST",
@ -233,5 +249,6 @@ export const useApiStore = defineStore("api", () => {
readNotification,
readAllNotifications,
validateBrief,
requestProjectCreation,
};
});

View file

@ -1,9 +1,16 @@
<template>
<main class="flex flex-col" style="--row-gap: var(--space-32)">
<Projects />
<ProjectRequestDialog v-if="isProjectRequestDialogOpen" />
<ProjectRequestButton @click="isProjectRequestDialogOpen = true" />
</main>
</template>
<script setup>
import Projects from "../components/Projects.vue";
import ProjectRequestButton from "../components/ProjectRequestButton.vue";
import ProjectRequestDialog from "../components/ProjectRequestDialog.vue";
import { ref } from "vue";
const isProjectRequestDialogOpen = ref(false);
</script>

View file

@ -7,6 +7,12 @@
<div class="kanban">
<ProjectStep v-for="step in page.steps" :key="step" :step="step" />
</div>
<DTLPanel v-if="isDTLPanelOpen" @close="isDTLPanelOpen = false" />
<DTLButton
v-if="page?.designToLight?.length > 0"
@click="openDTLPanel($event)"
/>
</main>
</template>
@ -16,9 +22,11 @@ import Header from "../components/project/Header.vue";
import DialogWrapper from "../components/project/DialogWrapper.vue";
import { usePageStore } from "../stores/page";
import { storeToRefs } from "pinia";
import { watch } from "vue";
import { watch, ref } from "vue";
import { useDialogStore } from "../stores/dialog";
import { useRoute } from "vue-router";
import DTLButton from "../components/design-to-light/DTLButton.vue";
import DTLPanel from "../components/design-to-light/DTLPanel.vue";
const { page } = storeToRefs(usePageStore());
const dialog = useDialogStore();
@ -29,6 +37,8 @@ if (route.query.dialog) {
openDialog(route.query.dialog);
}
const isDTLPanelOpen = ref(false);
watch(
() => route.query.dialog,
(targetStepSlug) => {
@ -43,10 +53,16 @@ watch(
}
);
// Functions
function openDialog(targetStepSlug) {
const targetStep = page.value.steps.find(
(step) => step.slug === targetStepSlug
);
dialog.content = targetStep;
}
function openDTLPanel(event) {
isDTLPanelOpen.value = true;
event.stopImmediatePropagation();
}
</script>