feat: add src/store/cmsStore.ts
This commit is contained in:
parent
f96dfd8002
commit
9703fe4ad9
|
|
@ -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',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue