From 30b7697c644a1ee2d398a6545032ca64d8fe6724 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 30 Jan 2026 11:27:27 +0100 Subject: [PATCH] Ajout masquage de projets pour utilisateurs Pochet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend : - Blueprint pochet : champ hiddenProjects - Route API toggle-hidden-project.php - Controller site.php : retourne hiddenProjects + uuid dans projects Frontend : - Store user : hiddenProjects, visibleProjects, toggleHiddenProject() - Store projects : filtrage automatique des projets masqués - Store api : fonction toggleHiddenProject() - Account.vue : section projets avec cartes horizontales + boutons toggle - Affichage pour Pochet (avec toggle) et Client (sans toggle) - Section client masquée pour Pochet Co-Authored-By: Claude Sonnet 4.5 --- public/site/blueprints/users/pochet.yml | 5 + public/site/config/config.php | 1 + .../config/routes/toggle-hidden-project.php | 61 +++++++++ public/site/controllers/site.php | 9 ++ src/stores/api.js | 27 ++++ src/stores/projects.js | 22 +++- src/stores/user.js | 27 ++++ src/views/Account.vue | 116 +++++++++++++++++- 8 files changed, 263 insertions(+), 5 deletions(-) create mode 100644 public/site/config/routes/toggle-hidden-project.php diff --git a/public/site/blueprints/users/pochet.yml b/public/site/blueprints/users/pochet.yml index bd66784..2030b05 100644 --- a/public/site/blueprints/users/pochet.yml +++ b/public/site/blueprints/users/pochet.yml @@ -19,3 +19,8 @@ fields: type: pages query: page('projects').children width: 3/4 + hiddenProjects: + label: Projets masqués + type: pages + query: page('projects').children + width: 3/4 diff --git a/public/site/config/config.php b/public/site/config/config.php index 97ceb2c..779ca22 100644 --- a/public/site/config/config.php +++ b/public/site/config/config.php @@ -31,6 +31,7 @@ return [ require(__DIR__ . '/routes/logout.php'), require(__DIR__ . '/routes/login.php'), require(__DIR__ . '/routes/toggle-favorite.php'), + require(__DIR__ . '/routes/toggle-hidden-project.php'), require(__DIR__ . '/routes/upload-images.php'), require(__DIR__ . '/routes/save-page.php'), require(__DIR__ . '/routes/save-file.php'), diff --git a/public/site/config/routes/toggle-hidden-project.php b/public/site/config/routes/toggle-hidden-project.php new file mode 100644 index 0000000..9106983 --- /dev/null +++ b/public/site/config/routes/toggle-hidden-project.php @@ -0,0 +1,61 @@ + '/toggle-hidden-project.json', + 'method' => 'POST', + 'action' => function() { + $json = file_get_contents("php://input"); + $data = json_decode($json); + + try { + $user = kirby()->user(); + $projectUuid = $data->projectUuid; + + // Récupérer les projets masqués actuels + $hiddenProjects = $user->hiddenProjects()->toPages(); + $hiddenProjectsArray = []; + + foreach ($hiddenProjects as $project) { + $hiddenProjectsArray[] = 'page://' . $project->uuid(); + } + + // Toggle: ajouter ou retirer le projet + $projectPage = Find::page($projectUuid); + $projectRef = 'page://' . $projectPage->uuid(); + + $index = array_search($projectRef, $hiddenProjectsArray); + + if ($index !== false) { + // Projet déjà masqué, on le retire + unset($hiddenProjectsArray[$index]); + $action = 'shown'; + } else { + // Projet non masqué, on l'ajoute + $hiddenProjectsArray[] = $projectRef; + $action = 'hidden'; + } + + // Réindexer le tableau + $hiddenProjectsArray = array_values($hiddenProjectsArray); + + // Encoder en YAML pour Kirby + $yaml = Data::encode($hiddenProjectsArray, 'yaml'); + + // Mettre à jour l'utilisateur + $user->update([ + 'hiddenProjects' => $yaml + ]); + + return [ + 'status' => 'success', + 'action' => $action, + 'hiddenProjects' => $hiddenProjectsArray + ]; + } catch (\Throwable $th) { + return [ + 'status' => 'error', + 'message' => 'Impossible de modifier les projets masqués : ' . $th->getMessage() . ' in file ' . $th->getFile() . ' line ' . $th->getLine() + ]; + } + } +]; diff --git a/public/site/controllers/site.php b/public/site/controllers/site.php index c5a36fb..a0e7261 100644 --- a/public/site/controllers/site.php +++ b/public/site/controllers/site.php @@ -33,9 +33,18 @@ return function ($page, $kirby, $site) { "title" => (string) $project->title(), "uri" => (string) $project->uri(), "step" => (string) $project->getStepLabel(), + "uuid" => (string) $project->uuid(), ]; })->data; } + + if ($kirby->user()->hiddenProjects()->exists() && $kirby->user()->hiddenProjects()->isNotEmpty()) { + $userData['hiddenProjects'] = $kirby->user()->hiddenProjects()->toPages()->map(function ($project) { + return (string) $project->uuid(); + })->data; + } else { + $userData['hiddenProjects'] = []; + } } diff --git a/src/stores/api.js b/src/stores/api.js index cbffdd8..d1506de 100644 --- a/src/stores/api.js +++ b/src/stores/api.js @@ -289,6 +289,32 @@ export const useApiStore = defineStore("api", () => { } } + async function toggleHiddenProject(projectUuid) { + const headers = { + method: "POST", + body: JSON.stringify({ projectUuid }), + }; + + try { + const response = await fetch("/toggle-hidden-project.json", headers); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + const data = await response.json(); + + if (data.status === "success") { + userStore.toggleHiddenProject(projectUuid); + console.log("Projet masqué/affiché avec succès."); + return data; + } else { + throw new Error(data.message); + } + } catch (error) { + console.error("Erreur lors du toggle du projet masqué:", error); + throw error; + } + } + return { fetchData, fetchRoute, @@ -299,6 +325,7 @@ export const useApiStore = defineStore("api", () => { // Nouvelles fonctions markNotificationRead, markAllNotificationsRead, + toggleHiddenProject, // Anciennes fonctions (rétro-compatibilité) readNotification, readAllNotifications, diff --git a/src/stores/projects.js b/src/stores/projects.js index c372c63..870a543 100644 --- a/src/stores/projects.js +++ b/src/stores/projects.js @@ -1,5 +1,6 @@ import { defineStore } from 'pinia'; import { useApiStore } from './api.js'; +import { useUserStore } from './user.js'; import { ref, computed } from 'vue'; export const useProjectsStore = defineStore('projects', () => { @@ -7,25 +8,40 @@ export const useProjectsStore = defineStore('projects', () => { const projects = ref(null); const currentProjects = computed(() => { + const userStore = useUserStore(); + const hiddenProjectUuids = userStore.hiddenProjects || []; return ( projects.value - ?.filter((project) => project.status === 'listed') + ?.filter((project) => + project.status === 'listed' && + !hiddenProjectUuids.includes(project.uuid) + ) .sort((a, b) => new Date(b.modified) - new Date(a.modified)) ?? [] ); }); const draftProjects = computed(() => { + const userStore = useUserStore(); + const hiddenProjectUuids = userStore.hiddenProjects || []; return ( projects.value - ?.filter((project) => project.status === 'draft') + ?.filter((project) => + project.status === 'draft' && + !hiddenProjectUuids.includes(project.uuid) + ) .sort((a, b) => new Date(b.modified) - new Date(a.modified)) ?? [] ); }); const archivedProjects = computed(() => { + const userStore = useUserStore(); + const hiddenProjectUuids = userStore.hiddenProjects || []; return ( projects.value - ?.filter((project) => project.status === 'unlisted') + ?.filter((project) => + project.status === 'unlisted' && + !hiddenProjectUuids.includes(project.uuid) + ) .sort((a, b) => new Date(b.modified) - new Date(a.modified)) ?? [] ); }); diff --git a/src/stores/user.js b/src/stores/user.js index b3404df..eaf2957 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -87,13 +87,40 @@ export const useUserStore = defineStore('user', () => { return user.value.uuid === comment.author.uuid; } + const hiddenProjects = computed(() => { + return user.value?.hiddenProjects || []; + }); + + const visibleProjects = computed(() => { + if (!user.value?.projects) return []; + const projectsArray = Array.isArray(user.value.projects) + ? user.value.projects + : Object.values(user.value.projects); + return projectsArray.filter( + (project) => !hiddenProjects.value.includes(project.uuid) + ); + }); + + function toggleHiddenProject(projectUuid) { + if (!user.value) return; + const index = user.value.hiddenProjects.indexOf(projectUuid); + if (index > -1) { + user.value.hiddenProjects.splice(index, 1); + } else { + user.value.hiddenProjects.push(projectUuid); + } + } + return { user, isLogged, notifications, + hiddenProjects, + visibleProjects, // Nouvelles fonctions markNotificationRead, markAllNotificationsRead, + toggleHiddenProject, // Anciennes fonctions (rétro-compatibilité) readNotification, readAllNotifications, diff --git a/src/views/Account.vue b/src/views/Account.vue index d9cc2fa..a347040 100644 --- a/src/views/Account.vue +++ b/src/views/Account.vue @@ -198,6 +198,7 @@
@@ -219,7 +220,90 @@
+

+ {{ user.role === 'pochet' ? 'Projets managés' : 'Mes projets' }} +

+ +
+
+ +
+

{{ project.title }}

+

{{ project.step }}

+
+
+ + +
+
+ +
@@ -233,9 +317,37 @@