turash/bugulma/frontend/pages/admin/ContentPageEditPage.tsx

177 lines
6.4 KiB
TypeScript

import { Button, Card, CardContent, CardHeader, CardTitle, FormField, Input, Label, Switch } from '@/components/ui';
import { Text } from '@/components/ui/Typography.tsx';
import Textarea from '@/components/ui/Textarea.tsx';
import { usePage, useUpdatePage, useCreatePage, usePublishPage } from '@/hooks/api/useAdminAPI.ts';
import { useTranslation } from '@/hooks/useI18n.tsx';
import { ArrowLeft, Save, Eye } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import type { CreatePageRequest, UpdatePageRequest } from '@/services/admin-api.ts';
const ContentPageEditPage = () => {
const { t } = useTranslation();
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const isNew = id === 'new';
const { data: page, isLoading } = usePage(isNew ? null : id);
const { mutate: updatePage, isPending: isUpdating } = useUpdatePage();
const { mutate: createPage, isPending: isCreating } = useCreatePage();
const { mutate: publishPage, isPending: isPublishing } = usePublishPage();
const [formData, setFormData] = useState<CreatePageRequest>({
slug: '',
title: '',
content: '',
status: 'draft',
visibility: 'public',
});
useEffect(() => {
if (page && !isNew) {
setFormData({
slug: page.slug,
title: page.title,
content: page.content || '',
status: page.status,
visibility: page.visibility,
});
}
}, [page, isNew]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (isNew) {
createPage(formData, {
onSuccess: (newPage) => {
navigate(`/admin/content/pages/${newPage.id}/edit`);
},
});
} else if (id) {
updatePage(
{
id,
request: formData as UpdatePageRequest,
},
{
onSuccess: () => {
// Show success message
},
}
);
}
};
const handlePublish = () => {
if (id && page?.status !== 'published') {
publishPage(id, {
onSuccess: () => {
// Show success message
},
});
}
};
return (
<div className="space-y-6">
<Button variant="ghost" onClick={() => navigate('/admin/content/pages')}>
<ArrowLeft className="h-4 w-4 mr-2" />
{t('adminPage.content.pages.backToList') || 'Back to Pages'}
</Button>
<form onSubmit={handleSubmit}>
<Card>
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>{isNew ? (t('adminPage.content.pages.newPage') || 'New Page') : (t('adminPage.content.pages.editPage') || 'Edit Page')}</CardTitle>
{!isNew && page?.status !== 'published' && (
<Button type="button" onClick={handlePublish} disabled={isPublishing}>
{isPublishing ? (t('adminPage.content.pages.publishing') || 'Publishing...') : (t('adminPage.content.pages.publish') || 'Publish')}
</Button>
)}
{!isNew && page?.slug && (
<Button
type="button"
variant="outline"
onClick={() => window.open(`/${page.slug}`, '_blank')}
>
<Eye className="h-4 w-4 mr-2" />
{t('adminPage.content.pages.preview') || 'Preview'}
</Button>
)}
</div>
</CardHeader>
<CardContent className="space-y-6">
<FormField>
<Label>{t('adminPage.content.pages.slug') || 'Slug'}</Label>
<Input
value={formData.slug}
onChange={(e) => setFormData({ ...formData, slug: e.target.value })}
placeholder="about-us"
required
disabled={!isNew}
/>
<Text variant="muted" className="text-sm">
{t('adminPage.content.pages.slugHint') || 'URL-friendly identifier (e.g., about-us, contact)'}
</Text>
</FormField>
<FormField>
<Label>{t('adminPage.content.pages.title') || 'Title'}</Label>
<Input
value={formData.title}
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
required
/>
</FormField>
<FormField>
<Label>{t('adminPage.content.pages.content') || 'Content'}</Label>
<Textarea
className="min-h-[300px]"
value={formData.content}
onChange={(e) => setFormData({ ...formData, content: e.target.value })}
placeholder={t('adminPage.content.pages.contentPlaceholder') || 'Enter page content (HTML or Markdown)...'}
/>
<Text variant="muted" className="text-sm">
{t('adminPage.content.pages.contentHint') || 'Supports HTML and Markdown formatting'}
</Text>
</FormField>
<FormField>
<div className="flex items-center justify-between">
<Label>{t('adminPage.content.pages.status') || 'Status'}</Label>
<div className="flex items-center gap-2">
<span className="text-sm text-muted-foreground">
{formData.status === 'published' ? (t('adminPage.content.pages.published') || 'Published') : (t('adminPage.content.pages.draft') || 'Draft')}
</span>
<Switch
checked={formData.status === 'published'}
onCheckedChange={(checked) =>
setFormData({ ...formData, status: checked ? 'published' : 'draft' })
}
/>
</div>
</div>
</FormField>
<div className="flex justify-end gap-4">
<Button type="button" variant="outline" onClick={() => navigate('/admin/content/pages')}>
{t('adminPage.content.pages.cancel') || 'Cancel'}
</Button>
<Button type="submit" disabled={isUpdating || isCreating}>
<Save className="h-4 w-4 mr-2" />
{isUpdating || isCreating ? (t('adminPage.content.pages.saving') || 'Saving...') : (t('adminPage.content.pages.save') || 'Save')}
</Button>
</div>
</CardContent>
</Card>
</form>
</div>
);
};
export default ContentPageEditPage;