Add Puck site builder with preview and draft functionality
Frontend:
- Add comprehensive Puck component library (Layout, Content, Booking, Contact)
- Add Services component with usePublicServices hook integration
- Add 150+ icons to IconList component organized by category
- Add preview modal with viewport toggles (desktop/tablet/mobile)
- Add draft save/discard functionality with localStorage persistence
- Add draft status indicator in PageEditor toolbar
- Fix useSites hooks to use correct API URLs (/pages/{id}/)
Backend:
- Add SiteConfig model for theme, header, footer configuration
- Add Page SEO fields (meta_title, meta_description, og_image, etc.)
- Add puck_data validation for component structure
- Add create_missing_sites management command
- Fix PageViewSet to use EntitlementService for permissions
- Add comprehensive tests for site builder functionality
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ export const usePage = (pageId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['page', pageId],
|
||||
queryFn: async () => {
|
||||
const response = await api.get(`/sites/me/pages/${pageId}/`);
|
||||
const response = await api.get(`/pages/${pageId}/`);
|
||||
return response.data;
|
||||
},
|
||||
enabled: !!pageId,
|
||||
@@ -36,7 +36,7 @@ export const useUpdatePage = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ id, data }: { id: string; data: any }) => {
|
||||
const response = await api.patch(`/sites/me/pages/${id}/`, data);
|
||||
const response = await api.patch(`/pages/${id}/`, data);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: (data, variables) => {
|
||||
@@ -63,7 +63,7 @@ export const useDeletePage = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (id: string) => {
|
||||
await api.delete(`/sites/me/pages/${id}/`);
|
||||
await api.delete(`/pages/${id}/`);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['pages'] });
|
||||
@@ -81,3 +81,41 @@ export const usePublicPage = () => {
|
||||
retry: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useSiteConfig = () => {
|
||||
return useQuery({
|
||||
queryKey: ['siteConfig'],
|
||||
queryFn: async () => {
|
||||
const response = await api.get('/sites/me/config/');
|
||||
return response.data;
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateSiteConfig = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (data: {
|
||||
theme?: Record<string, unknown>;
|
||||
header?: Record<string, unknown>;
|
||||
footer?: Record<string, unknown>;
|
||||
}) => {
|
||||
const response = await api.patch('/sites/me/config/', data);
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['siteConfig'] });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const usePublicSiteConfig = () => {
|
||||
return useQuery({
|
||||
queryKey: ['publicSiteConfig'],
|
||||
queryFn: async () => {
|
||||
const response = await api.get('/public/site-config/');
|
||||
return response.data;
|
||||
},
|
||||
retry: false,
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user