feat: add src/store/cmsStore.ts

This commit is contained in:
cupadev-admin 2026-03-09 14:28:42 +00:00
parent f96dfd8002
commit 9703fe4ad9
1 changed files with 251 additions and 0 deletions

251
src/store/cmsStore.ts Normal file
View File

@ -0,0 +1,251 @@
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { v4 as uuidv4 } from 'uuid'
import { Post, Page, GalleryImage, NavItem, SiteSettings, Category } from '@/types'
interface CMSState {
posts: Post[]
pages: Page[]
gallery: GalleryImage[]
navItems: NavItem[]
categories: Category[]
settings: SiteSettings
// Posts
addPost: (post: Omit<Post, 'id' | 'createdAt' | 'updatedAt' | 'views'>) => Post
updatePost: (id: string, data: Partial<Post>) => void
deletePost: (id: string) => void
getPost: (id: string) => Post | undefined
// Pages
addPage: (page: Omit<Page, 'id' | 'createdAt' | 'updatedAt'>) => Page
updatePage: (id: string, data: Partial<Page>) => void
deletePage: (id: string) => void
getPage: (id: string) => Page | undefined
// Gallery
addImage: (image: Omit<GalleryImage, 'id' | 'uploadedAt'>) => void
deleteImage: (id: string) => void
updateImage: (id: string, data: Partial<GalleryImage>) => void
// Navigation
addNavItem: (item: Omit<NavItem, 'id'>) => void
updateNavItem: (id: string, data: Partial<NavItem>) => void
deleteNavItem: (id: string) => void
reorderNavItems: (items: NavItem[]) => void
// Categories
addCategory: (cat: Omit<Category, 'id'>) => void
updateCategory: (id: string, data: Partial<Category>) => void
deleteCategory: (id: string) => void
// Settings
updateSettings: (data: Partial<SiteSettings>) => void
}
const now = () => new Date().toISOString()
const DEMO_POSTS: Post[] = [
{
id: '1',
title: 'Bienvenue sur mon blog',
slug: 'bienvenue-sur-mon-blog',
content: '<h2>Bonjour tout le monde !</h2><p>Ceci est mon premier article de blog. Je suis ravi de partager mes pensées et expériences avec vous.</p><p>Ce CMS vous permet de gérer facilement vos articles, pages, galerie et navigation.</p>',
excerpt: 'Mon premier article de blog pour inaugurer ce CMS personnel.',
status: 'published',
category: 'Général',
tags: ['bienvenue', 'premier article'],
author: 'admin',
createdAt: new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(),
updatedAt: new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(),
publishedAt: new Date(Date.now() - 7 * 24 * 3600 * 1000).toISOString(),
views: 142,
},
{
id: '2',
title: 'Guide de démarrage rapide',
slug: 'guide-demarrage-rapide',
content: '<h2>Premiers pas avec le CMS</h2><p>Ce guide vous explique comment utiliser toutes les fonctionnalités du CMS.</p><ul><li>Créer des articles</li><li>Gérer les pages</li><li>Organiser la galerie</li><li>Configurer la navigation</li></ul>',
excerpt: 'Apprenez à utiliser toutes les fonctionnalités du CMS en quelques minutes.',
status: 'published',
category: 'Tutoriel',
tags: ['guide', 'démarrage', 'tutoriel'],
author: 'admin',
createdAt: new Date(Date.now() - 3 * 24 * 3600 * 1000).toISOString(),
updatedAt: new Date(Date.now() - 3 * 24 * 3600 * 1000).toISOString(),
publishedAt: new Date(Date.now() - 3 * 24 * 3600 * 1000).toISOString(),
views: 89,
},
{
id: '3',
title: 'Article en brouillon',
slug: 'article-en-brouillon',
content: '<p>Cet article est en cours de rédaction...</p>',
excerpt: 'Un article non publié.',
status: 'draft',
category: 'Général',
tags: ['brouillon'],
author: 'editor',
createdAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString(),
updatedAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString(),
views: 0,
},
]
const DEMO_PAGES: Page[] = [
{
id: '1',
title: 'À propos',
slug: 'a-propos',
content: '<h2>Qui suis-je ?</h2><p>Bienvenue sur ma page à propos. Je suis un développeur passionné par les nouvelles technologies.</p>',
status: 'published',
template: 'default',
createdAt: new Date(Date.now() - 14 * 24 * 3600 * 1000).toISOString(),
updatedAt: new Date(Date.now() - 14 * 24 * 3600 * 1000).toISOString(),
},
{
id: '2',
title: 'Contact',
slug: 'contact',
content: '<h2>Me contacter</h2><p>N\'hésitez pas à me contacter pour toute question.</p>',
status: 'published',
template: 'default',
createdAt: new Date(Date.now() - 10 * 24 * 3600 * 1000).toISOString(),
updatedAt: new Date(Date.now() - 10 * 24 * 3600 * 1000).toISOString(),
},
]
const DEMO_NAV: NavItem[] = [
{ id: '1', label: 'Accueil', href: '/', order: 0, isExternal: false },
{ id: '2', label: 'Blog', href: '/blog', order: 1, isExternal: false },
{ id: '3', label: 'À propos', href: '/a-propos', order: 2, isExternal: false },
{ id: '4', label: 'Contact', href: '/contact', order: 3, isExternal: false },
]
const DEMO_CATEGORIES: Category[] = [
{ id: '1', name: 'Général', slug: 'general', color: '#6366f1' },
{ id: '2', name: 'Tutoriel', slug: 'tutoriel', color: '#10b981' },
{ id: '3', name: 'Actualité', slug: 'actualite', color: '#f59e0b' },
{ id: '4', name: 'Projet', slug: 'projet', color: '#ef4444' },
]
const DEFAULT_SETTINGS: SiteSettings = {
siteName: 'Mon Blog',
siteDescription: 'Un blog personnel propulsé par le CMS',
siteUrl: 'https://monblog.com',
primaryColor: '#6366f1',
postsPerPage: 10,
allowComments: true,
maintenanceMode: false,
socialLinks: {
twitter: '',
github: '',
linkedin: '',
},
}
export const useCMSStore = create<CMSState>()(
persist(
(set, get) => ({
posts: DEMO_POSTS,
pages: DEMO_PAGES,
gallery: [],
navItems: DEMO_NAV,
categories: DEMO_CATEGORIES,
settings: DEFAULT_SETTINGS,
// Posts
addPost: (postData) => {
const post: Post = {
...postData,
id: uuidv4(),
createdAt: now(),
updatedAt: now(),
views: 0,
}
set((s) => ({ posts: [post, ...s.posts] }))
return post
},
updatePost: (id, data) =>
set((s) => ({
posts: s.posts.map((p) =>
p.id === id ? { ...p, ...data, updatedAt: now() } : p
),
})),
deletePost: (id) =>
set((s) => ({ posts: s.posts.filter((p) => p.id !== id) })),
getPost: (id) => get().posts.find((p) => p.id === id),
// Pages
addPage: (pageData) => {
const page: Page = {
...pageData,
id: uuidv4(),
createdAt: now(),
updatedAt: now(),
}
set((s) => ({ pages: [page, ...s.pages] }))
return page
},
updatePage: (id, data) =>
set((s) => ({
pages: s.pages.map((p) =>
p.id === id ? { ...p, ...data, updatedAt: now() } : p
),
})),
deletePage: (id) =>
set((s) => ({ pages: s.pages.filter((p) => p.id !== id) })),
getPage: (id) => get().pages.find((p) => p.id === id),
// Gallery
addImage: (imgData) => {
const image: GalleryImage = {
...imgData,
id: uuidv4(),
uploadedAt: now(),
}
set((s) => ({ gallery: [image, ...s.gallery] }))
},
deleteImage: (id) =>
set((s) => ({ gallery: s.gallery.filter((i) => i.id !== id) })),
updateImage: (id, data) =>
set((s) => ({
gallery: s.gallery.map((i) => (i.id === id ? { ...i, ...data } : i)),
})),
// Navigation
addNavItem: (itemData) => {
const item: NavItem = { ...itemData, id: uuidv4() }
set((s) => ({ navItems: [...s.navItems, item] }))
},
updateNavItem: (id, data) =>
set((s) => ({
navItems: s.navItems.map((i) => (i.id === id ? { ...i, ...data } : i)),
})),
deleteNavItem: (id) =>
set((s) => ({ navItems: s.navItems.filter((i) => i.id !== id) })),
reorderNavItems: (items) => set({ navItems: items }),
// Categories
addCategory: (catData) => {
const cat: Category = { ...catData, id: uuidv4() }
set((s) => ({ categories: [...s.categories, cat] }))
},
updateCategory: (id, data) =>
set((s) => ({
categories: s.categories.map((c) =>
c.id === id ? { ...c, ...data } : c
),
})),
deleteCategory: (id) =>
set((s) => ({ categories: s.categories.filter((c) => c.id !== id) })),
// Settings
updateSettings: (data) =>
set((s) => ({ settings: { ...s.settings, ...data } })),
}),
{
name: 'cms-data',
}
)
)