fix: apply designer agent improvements to src/store/useStore.ts
This commit is contained in:
parent
a755ed776d
commit
e2501b3004
|
|
@ -1,391 +1,161 @@
|
||||||
import { create } from 'zustand';
|
import { create } from 'zustand'
|
||||||
import { persist } from 'zustand/middleware';
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import type { Post, Page, GalleryImage, NavItem, SiteSettings } from '@/types'
|
||||||
import type { Page, Post, GalleryItem, NavItem, SiteSettings } from '@/types';
|
|
||||||
|
|
||||||
interface CMSState {
|
const now = () => new Date().toISOString()
|
||||||
// Auth
|
|
||||||
isAuthenticated: boolean;
|
|
||||||
currentUser: { username: string; email: string; role: string } | null;
|
|
||||||
login: (username: string, password: string) => boolean;
|
|
||||||
logout: () => void;
|
|
||||||
|
|
||||||
// Pages
|
const DEMO_POSTS: Post[] = [
|
||||||
pages: Page[];
|
|
||||||
addPage: (page: Omit<Page, 'id' | 'createdAt' | 'updatedAt'>) => Page;
|
|
||||||
updatePage: (id: string, data: Partial<Page>) => void;
|
|
||||||
deletePage: (id: string) => void;
|
|
||||||
getPageBySlug: (slug: string) => Page | undefined;
|
|
||||||
getPageById: (id: string) => Page | undefined;
|
|
||||||
|
|
||||||
// Posts
|
|
||||||
posts: Post[];
|
|
||||||
addPost: (post: Omit<Post, 'id' | 'createdAt' | 'updatedAt'>) => Post;
|
|
||||||
updatePost: (id: string, data: Partial<Post>) => void;
|
|
||||||
deletePost: (id: string) => void;
|
|
||||||
getPostBySlug: (slug: string) => Post | undefined;
|
|
||||||
getPostById: (id: string) => Post | undefined;
|
|
||||||
|
|
||||||
// Gallery
|
|
||||||
gallery: GalleryItem[];
|
|
||||||
addGalleryItem: (item: Omit<GalleryItem, 'id' | 'createdAt' | 'updatedAt'>) => GalleryItem;
|
|
||||||
updateGalleryItem: (id: string, data: Partial<GalleryItem>) => void;
|
|
||||||
deleteGalleryItem: (id: string) => void;
|
|
||||||
reorderGallery: (items: GalleryItem[]) => void;
|
|
||||||
|
|
||||||
// Navigation
|
|
||||||
navigation: NavItem[];
|
|
||||||
addNavItem: (item: Omit<NavItem, 'id'>) => void;
|
|
||||||
updateNavItem: (id: string, data: Partial<NavItem>) => void;
|
|
||||||
deleteNavItem: (id: string) => void;
|
|
||||||
reorderNav: (items: NavItem[]) => void;
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
settings: SiteSettings;
|
|
||||||
updateSettings: (data: Partial<SiteSettings>) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultSettings: SiteSettings = {
|
|
||||||
siteName: 'Musée & Blog',
|
|
||||||
tagline: 'Art, Culture & Découvertes',
|
|
||||||
description: 'Un espace dédié à l\'art, à la culture et aux découvertes.',
|
|
||||||
primaryColor: '#1a1a2e',
|
|
||||||
accentColor: '#a08660',
|
|
||||||
footerText: '© 2024 Musée & Blog. Tous droits réservés.',
|
|
||||||
socialLinks: {},
|
|
||||||
contactEmail: 'contact@musee-blog.fr',
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultPages: Page[] = [
|
|
||||||
{
|
{
|
||||||
id: 'home',
|
id: '1',
|
||||||
title: 'Accueil',
|
title: 'Getting Started with Next.js 14',
|
||||||
slug: '',
|
slug: 'getting-started-nextjs-14',
|
||||||
content: '<h1>Bienvenue au Musée & Blog</h1><p>Explorez notre collection unique d\'œuvres d\'art et découvrez nos articles passionnants sur l\'art et la culture.</p>',
|
excerpt: 'A comprehensive guide to building modern web applications with Next.js 14 and the App Router.',
|
||||||
excerpt: 'Bienvenue sur notre site dédié à l\'art et à la culture.',
|
content: '<p>Next.js 14 introduces groundbreaking features...</p>',
|
||||||
type: 'home',
|
|
||||||
status: 'published',
|
status: 'published',
|
||||||
featuredImage: 'https://images.unsplash.com/photo-1518998053901-5348d3961a04?w=1200',
|
tags: ['Next.js', 'React', 'Web Dev'],
|
||||||
order: 0,
|
createdAt: '2024-01-15T10:00:00Z',
|
||||||
createdAt: new Date().toISOString(),
|
updatedAt: '2024-01-15T10:00:00Z',
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'about',
|
id: '2',
|
||||||
title: 'À propos',
|
title: 'Mastering Tailwind CSS',
|
||||||
slug: 'a-propos',
|
slug: 'mastering-tailwind-css',
|
||||||
content: '<h2>Notre Mission</h2><p>Nous sommes dédiés à la promotion de l\'art et de la culture à travers notre plateforme unique qui combine blog et musée virtuel.</p><h2>Notre Histoire</h2><p>Fondé en 2024, notre espace culturel numérique rassemble passionnés d\'art, artistes et curieux du monde entier.</p>',
|
excerpt: 'Deep dive into advanced Tailwind CSS techniques for building beautiful UIs.',
|
||||||
excerpt: 'Découvrez notre mission et notre histoire.',
|
content: '<p>Tailwind CSS has revolutionized how we write CSS...</p>',
|
||||||
type: 'page',
|
status: 'published',
|
||||||
|
tags: ['CSS', 'Tailwind', 'Design'],
|
||||||
|
createdAt: '2024-01-20T10:00:00Z',
|
||||||
|
updatedAt: '2024-01-20T10:00:00Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
title: 'TypeScript Best Practices',
|
||||||
|
slug: 'typescript-best-practices',
|
||||||
|
excerpt: 'Essential TypeScript patterns and practices for scalable applications.',
|
||||||
|
content: '<p>TypeScript has become the standard for large-scale applications...</p>',
|
||||||
|
status: 'draft',
|
||||||
|
tags: ['TypeScript', 'JavaScript'],
|
||||||
|
createdAt: '2024-01-25T10:00:00Z',
|
||||||
|
updatedAt: '2024-01-25T10:00:00Z',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const DEMO_PAGES: Page[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
title: 'About',
|
||||||
|
slug: 'about',
|
||||||
|
content: '<p>Welcome to my personal website...</p>',
|
||||||
status: 'published',
|
status: 'published',
|
||||||
order: 1,
|
order: 1,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: '2024-01-01T10:00:00Z',
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: '2024-01-01T10:00:00Z',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'contact',
|
id: '2',
|
||||||
title: 'Contact',
|
title: 'Contact',
|
||||||
slug: 'contact',
|
slug: 'contact',
|
||||||
content: '<h2>Contactez-nous</h2><p>Pour toute question ou collaboration, n\'hésitez pas à nous contacter.</p>',
|
content: '<p>Get in touch with me...</p>',
|
||||||
excerpt: 'Prenez contact avec nous.',
|
|
||||||
type: 'contact',
|
|
||||||
status: 'published',
|
status: 'published',
|
||||||
order: 4,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const defaultPosts: Post[] = [
|
|
||||||
{
|
|
||||||
id: 'post-1',
|
|
||||||
title: 'L\'impressionnisme : Une révolution artistique',
|
|
||||||
slug: 'impressionnisme-revolution-artistique',
|
|
||||||
content: '<p>L\'impressionnisme est un mouvement pictural né en France au XIXe siècle qui révolutionna la peinture traditionnelle...</p><h2>Les Origines</h2><p>Le mouvement impressionniste est né d\'un groupe de peintres parisiens dans les années 1860...</p>',
|
|
||||||
excerpt: 'Découvrez comment l\'impressionnisme a transformé le monde de l\'art au XIXe siècle.',
|
|
||||||
category: 'article',
|
|
||||||
tags: ['impressionnisme', 'peinture', 'histoire de l\'art'],
|
|
||||||
status: 'published',
|
|
||||||
featuredImage: 'https://images.unsplash.com/photo-1541367777708-7905fe3296c0?w=800',
|
|
||||||
author: 'Admin',
|
|
||||||
publishedAt: new Date().toISOString(),
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'post-2',
|
|
||||||
title: 'Exposition : Les Maîtres de la Lumière',
|
|
||||||
slug: 'exposition-maitres-lumiere',
|
|
||||||
content: '<p>Notre nouvelle exposition temporaire met en lumière les artistes qui ont su capturer et sublimer la lumière dans leurs œuvres...</p>',
|
|
||||||
excerpt: 'Une exposition exceptionnelle dédiée aux maîtres de la lumière dans l\'art.',
|
|
||||||
category: 'exhibit',
|
|
||||||
tags: ['exposition', 'lumière', 'peinture'],
|
|
||||||
status: 'published',
|
|
||||||
featuredImage: 'https://images.unsplash.com/photo-1578662996442-48f60103fc96?w=800',
|
|
||||||
author: 'Admin',
|
|
||||||
publishedAt: new Date().toISOString(),
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'post-3',
|
|
||||||
title: 'Vernissage : Art Contemporain 2024',
|
|
||||||
slug: 'vernissage-art-contemporain-2024',
|
|
||||||
content: '<p>Rejoignez-nous pour le vernissage de notre exposition d\'art contemporain qui réunit des artistes émergents et confirmés...</p>',
|
|
||||||
excerpt: 'Vernissage de notre exposition annuelle d\'art contemporain.',
|
|
||||||
category: 'event',
|
|
||||||
tags: ['vernissage', 'art contemporain', 'événement'],
|
|
||||||
status: 'published',
|
|
||||||
featuredImage: 'https://images.unsplash.com/photo-1531058020387-3be344556be6?w=800',
|
|
||||||
author: 'Admin',
|
|
||||||
publishedAt: new Date().toISOString(),
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const defaultGallery: GalleryItem[] = [
|
|
||||||
{
|
|
||||||
id: 'g-1',
|
|
||||||
title: 'Harmonie en Bleu',
|
|
||||||
description: 'Une œuvre abstraite explorant les nuances du bleu et la profondeur de l\'océan.',
|
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1578301978693-85fa9c0320b9?w=800',
|
|
||||||
artist: 'Marie Dupont',
|
|
||||||
year: '2023',
|
|
||||||
medium: 'Huile sur toile',
|
|
||||||
dimensions: '120 × 90 cm',
|
|
||||||
category: 'Peinture',
|
|
||||||
tags: ['abstrait', 'bleu', 'contemporain'],
|
|
||||||
order: 0,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'g-2',
|
|
||||||
title: 'Portrait d\'Automne',
|
|
||||||
description: 'Un portrait saisissant capturant la mélancolie de la saison automnale.',
|
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1549490349-8643362247b5?w=800',
|
|
||||||
artist: 'Jean-Pierre Martin',
|
|
||||||
year: '2022',
|
|
||||||
medium: 'Aquarelle',
|
|
||||||
dimensions: '60 × 80 cm',
|
|
||||||
category: 'Peinture',
|
|
||||||
tags: ['portrait', 'automne', 'aquarelle'],
|
|
||||||
order: 1,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'g-3',
|
|
||||||
title: 'Architecture Urbaine',
|
|
||||||
description: 'Photographie artistique explorant les lignes et formes de l\'architecture moderne.',
|
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1486325212027-8081e485255e?w=800',
|
|
||||||
artist: 'Sophie Lambert',
|
|
||||||
year: '2024',
|
|
||||||
medium: 'Photographie numérique',
|
|
||||||
dimensions: '100 × 150 cm',
|
|
||||||
category: 'Photographie',
|
|
||||||
tags: ['architecture', 'urbain', 'photographie'],
|
|
||||||
order: 2,
|
order: 2,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: '2024-01-01T10:00:00Z',
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: '2024-01-01T10:00:00Z',
|
||||||
},
|
},
|
||||||
{
|
]
|
||||||
id: 'g-4',
|
|
||||||
title: 'La Danse des Formes',
|
const DEMO_NAV: NavItem[] = [
|
||||||
description: 'Sculpture abstraite jouant avec l\'équilibre et le mouvement.',
|
{ id: '1', label: 'Home', href: '/', order: 1 },
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1561839561-b13bcfe95249?w=800',
|
{ id: '2', label: 'Blog', href: '/blog', order: 2 },
|
||||||
artist: 'Pierre Moreau',
|
{ id: '3', label: 'About', href: '/about', order: 3 },
|
||||||
year: '2021',
|
{ id: '4', label: 'Contact', href: '/contact', order: 4 },
|
||||||
medium: 'Bronze',
|
]
|
||||||
dimensions: '45 × 30 × 25 cm',
|
|
||||||
category: 'Sculpture',
|
const DEMO_GALLERY: GalleryImage[] = [
|
||||||
tags: ['sculpture', 'abstrait', 'bronze'],
|
{ id: '1', url: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800', alt: 'Mountain landscape', caption: 'Alps at sunset', createdAt: now() },
|
||||||
order: 3,
|
{ id: '2', url: 'https://images.unsplash.com/photo-1469474968028-56623f02e42e?w=800', alt: 'Forest path', caption: 'Morning mist', createdAt: now() },
|
||||||
createdAt: new Date().toISOString(),
|
{ id: '3', url: 'https://images.unsplash.com/photo-1519681393784-d120267933ba?w=800', alt: 'Starry night', caption: 'Night sky', createdAt: now() },
|
||||||
updatedAt: new Date().toISOString(),
|
]
|
||||||
|
|
||||||
|
interface StoreState {
|
||||||
|
posts: Post[]
|
||||||
|
pages: Page[]
|
||||||
|
gallery: GalleryImage[]
|
||||||
|
navItems: NavItem[]
|
||||||
|
settings: SiteSettings
|
||||||
|
|
||||||
|
// Posts
|
||||||
|
addPost: (post: Omit<Post, 'id' | 'createdAt' | 'updatedAt'>) => Post
|
||||||
|
updatePost: (id: string, data: Partial<Post>) => void
|
||||||
|
deletePost: (id: string) => void
|
||||||
|
|
||||||
|
// Pages
|
||||||
|
addPage: (page: Omit<Page, 'id' | 'createdAt' | 'updatedAt'>) => Page
|
||||||
|
updatePage: (id: string, data: Partial<Page>) => void
|
||||||
|
deletePage: (id: string) => void
|
||||||
|
|
||||||
|
// Gallery
|
||||||
|
addImage: (image: Omit<GalleryImage, 'id' | 'createdAt'>) => 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
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
updateSettings: (data: Partial<SiteSettings>) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useStore = create<StoreState>((set, get) => ({
|
||||||
|
posts: DEMO_POSTS,
|
||||||
|
pages: DEMO_PAGES,
|
||||||
|
gallery: DEMO_GALLERY,
|
||||||
|
navItems: DEMO_NAV,
|
||||||
|
settings: {
|
||||||
|
siteName: 'My Personal CMS',
|
||||||
|
siteDescription: 'A beautiful personal website built with Next.js',
|
||||||
|
socialLinks: {},
|
||||||
|
seoDefaults: { title: 'My Site', description: 'Welcome to my personal site' },
|
||||||
|
theme: { primaryColor: '#3b82f6', accentColor: '#8b5cf6', darkMode: false },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'g-5',
|
addPost: (data) => {
|
||||||
title: 'Jardin Secret',
|
const post: Post = { ...data, id: uuidv4(), createdAt: now(), updatedAt: now() }
|
||||||
description: 'Une composition florale aux teintes pastel évoquant la sérénité d\'un jardin caché.',
|
set((s) => ({ posts: [post, ...s.posts] }))
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1416879595882-3373a0480b5b?w=800',
|
return post
|
||||||
artist: 'Isabelle Chen',
|
|
||||||
year: '2023',
|
|
||||||
medium: 'Acrylique sur toile',
|
|
||||||
dimensions: '80 × 80 cm',
|
|
||||||
category: 'Peinture',
|
|
||||||
tags: ['floral', 'pastel', 'jardin'],
|
|
||||||
order: 4,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
},
|
||||||
{
|
updatePost: (id, data) =>
|
||||||
id: 'g-6',
|
set((s) => ({
|
||||||
title: 'Lumière du Nord',
|
posts: s.posts.map((p) => (p.id === id ? { ...p, ...data, updatedAt: now() } : p)),
|
||||||
description: 'Paysage nordique baigné d\'une lumière spectrale et mystérieuse.',
|
})),
|
||||||
imageUrl: 'https://images.unsplash.com/photo-1531366936337-7c912a4589a7?w=800',
|
deletePost: (id) => set((s) => ({ posts: s.posts.filter((p) => p.id !== id) })),
|
||||||
artist: 'Erik Andersen',
|
|
||||||
year: '2024',
|
addPage: (data) => {
|
||||||
medium: 'Photographie',
|
const page: Page = { ...data, id: uuidv4(), createdAt: now(), updatedAt: now() }
|
||||||
dimensions: '120 × 80 cm',
|
set((s) => ({ pages: [page, ...s.pages] }))
|
||||||
category: 'Photographie',
|
return page
|
||||||
tags: ['paysage', 'lumière', 'nord'],
|
|
||||||
order: 5,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
},
|
},
|
||||||
];
|
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) })),
|
||||||
|
|
||||||
const defaultNav: NavItem[] = [
|
addImage: (data) =>
|
||||||
{ id: 'nav-1', label: 'Accueil', url: '/', target: '_self', order: 0 },
|
set((s) => ({ gallery: [{ ...data, id: uuidv4(), createdAt: now() }, ...s.gallery] })),
|
||||||
{ id: 'nav-2', label: 'Musée', url: '/galerie', target: '_self', order: 1 },
|
deleteImage: (id) => set((s) => ({ gallery: s.gallery.filter((i) => i.id !== id) })),
|
||||||
{ id: 'nav-3', label: 'Blog', url: '/blog', target: '_self', order: 2 },
|
updateImage: (id, data) =>
|
||||||
{ id: 'nav-4', label: 'À propos', url: '/a-propos', target: '_self', order: 3 },
|
set((s) => ({ gallery: s.gallery.map((i) => (i.id === id ? { ...i, ...data } : i)) })),
|
||||||
{ id: 'nav-5', label: 'Contact', url: '/contact', target: '_self', order: 4 },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const useStore = create<CMSState>()(
|
addNavItem: (data) =>
|
||||||
persist(
|
set((s) => ({ navItems: [...s.navItems, { ...data, id: uuidv4() }] })),
|
||||||
(set, get) => ({
|
updateNavItem: (id, data) =>
|
||||||
isAuthenticated: false,
|
set((s) => ({ navItems: s.navItems.map((n) => (n.id === id ? { ...n, ...data } : n)) })),
|
||||||
currentUser: null,
|
deleteNavItem: (id) => set((s) => ({ navItems: s.navItems.filter((n) => n.id !== id) })),
|
||||||
|
reorderNavItems: (items) => set({ navItems: items }),
|
||||||
|
|
||||||
login: (username, password) => {
|
updateSettings: (data) =>
|
||||||
if (username === 'admin' && password === 'admin123') {
|
set((s) => ({ settings: { ...s.settings, ...data } })),
|
||||||
set({
|
}))
|
||||||
isAuthenticated: true,
|
|
||||||
currentUser: { username: 'admin', email: 'admin@cms.fr', role: 'admin' },
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
logout: () => set({ isAuthenticated: false, currentUser: null }),
|
|
||||||
|
|
||||||
pages: defaultPages,
|
|
||||||
|
|
||||||
addPage: (pageData) => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
const page: Page = {
|
|
||||||
...pageData,
|
|
||||||
id: uuidv4(),
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now,
|
|
||||||
};
|
|
||||||
set((state) => ({ pages: [...state.pages, page] }));
|
|
||||||
return page;
|
|
||||||
},
|
|
||||||
|
|
||||||
updatePage: (id, data) => {
|
|
||||||
set((state) => ({
|
|
||||||
pages: state.pages.map((p) =>
|
|
||||||
p.id === id ? { ...p, ...data, updatedAt: new Date().toISOString() } : p
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
deletePage: (id) => {
|
|
||||||
set((state) => ({ pages: state.pages.filter((p) => p.id !== id) }));
|
|
||||||
},
|
|
||||||
|
|
||||||
getPageBySlug: (slug) => get().pages.find((p) => p.slug === slug),
|
|
||||||
getPageById: (id) => get().pages.find((p) => p.id === id),
|
|
||||||
|
|
||||||
posts: defaultPosts,
|
|
||||||
|
|
||||||
addPost: (postData) => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
const post: Post = {
|
|
||||||
...postData,
|
|
||||||
id: uuidv4(),
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now,
|
|
||||||
};
|
|
||||||
set((state) => ({ posts: [...state.posts, post] }));
|
|
||||||
return post;
|
|
||||||
},
|
|
||||||
|
|
||||||
updatePost: (id, data) => {
|
|
||||||
set((state) => ({
|
|
||||||
posts: state.posts.map((p) =>
|
|
||||||
p.id === id ? { ...p, ...data, updatedAt: new Date().toISOString() } : p
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
deletePost: (id) => {
|
|
||||||
set((state) => ({ posts: state.posts.filter((p) => p.id !== id) }));
|
|
||||||
},
|
|
||||||
|
|
||||||
getPostBySlug: (slug) => get().posts.find((p) => p.slug === slug),
|
|
||||||
getPostById: (id) => get().posts.find((p) => p.id === id),
|
|
||||||
|
|
||||||
gallery: defaultGallery,
|
|
||||||
|
|
||||||
addGalleryItem: (itemData) => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
const item: GalleryItem = {
|
|
||||||
...itemData,
|
|
||||||
id: uuidv4(),
|
|
||||||
createdAt: now,
|
|
||||||
updatedAt: now,
|
|
||||||
};
|
|
||||||
set((state) => ({ gallery: [...state.gallery, item] }));
|
|
||||||
return item;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateGalleryItem: (id, data) => {
|
|
||||||
set((state) => ({
|
|
||||||
gallery: state.gallery.map((g) =>
|
|
||||||
g.id === id ? { ...g, ...data, updatedAt: new Date().toISOString() } : g
|
|
||||||
),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteGalleryItem: (id) => {
|
|
||||||
set((state) => ({ gallery: state.gallery.filter((g) => g.id !== id) }));
|
|
||||||
},
|
|
||||||
|
|
||||||
reorderGallery: (items) => set({ gallery: items }),
|
|
||||||
|
|
||||||
navigation: defaultNav,
|
|
||||||
|
|
||||||
addNavItem: (itemData) => {
|
|
||||||
const item: NavItem = { ...itemData, id: uuidv4() };
|
|
||||||
set((state) => ({ navigation: [...state.navigation, item] }));
|
|
||||||
},
|
|
||||||
|
|
||||||
updateNavItem: (id, data) => {
|
|
||||||
set((state) => ({
|
|
||||||
navigation: state.navigation.map((n) => (n.id === id ? { ...n, ...data } : n)),
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
deleteNavItem: (id) => {
|
|
||||||
set((state) => ({ navigation: state.navigation.filter((n) => n.id !== id) }));
|
|
||||||
},
|
|
||||||
|
|
||||||
reorderNav: (items) => set({ navigation: items }),
|
|
||||||
|
|
||||||
settings: defaultSettings,
|
|
||||||
|
|
||||||
updateSettings: (data) => {
|
|
||||||
set((state) => ({ settings: { ...state.settings, ...data } }));
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
name: 'cms-storage',
|
|
||||||
partialize: (state) => ({
|
|
||||||
pages: state.pages,
|
|
||||||
posts: state.posts,
|
|
||||||
gallery: state.gallery,
|
|
||||||
navigation: state.navigation,
|
|
||||||
settings: state.settings,
|
|
||||||
isAuthenticated: state.isAuthenticated,
|
|
||||||
currentUser: state.currentUser,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue