Files
test_polis/laravel/resources/js/pages/welcome.tsx
2026-02-04 23:23:42 +07:00

132 lines
4.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Link } from '@inertiajs/react';
import React, { useEffect, useState } from 'react';
import Heading from '@/components/heading';
import { Card } from '@/components/ui/card';
import * as Dialog from '@/components/ui/dialog'; // твои Radix Dialog-компоненты
interface Article {
id: number;
title: string;
content_short: string;
created_at: string;
comments_count: number;
}
export default function Welcome() {
const [articles, setArticles] = useState<Article[]>([]);
const [loading, setLoading] = useState(false);
const [isOpen, setIsOpen] = useState(false);
const [form, setForm] = useState({ title: '', content: '' });
useEffect(() => {
fetch('/api/articles')
.then((res) => res.json())
.then((data) => setArticles(data.data || data))
.catch(console.error);
}, []);
const submitArticle = async () => {
if (!form.title || !form.content) return;
setLoading(true);
try {
const res = await fetch('/api/articles', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(form),
});
if (!res.ok) return;
const json = await res.json();
const newArticle = json.data || json;
setArticles([newArticle, ...articles]);
setForm({ title: '', content: '' });
setIsOpen(false);
} catch (e) {
console.error(e);
} finally {
setLoading(false);
}
};
return (
<div className="space-y-6 p-6">
<Heading
title="Список статей"
description="Последние новости и статьи"
/>
<Dialog.Dialog open={isOpen} onOpenChange={setIsOpen}>
<Dialog.DialogTrigger>
<button className="rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700">
Добавить статью
</button>
</Dialog.DialogTrigger>
<Dialog.DialogContent>
<Dialog.DialogHeader>
<Dialog.DialogTitle>Новая статья</Dialog.DialogTitle>
</Dialog.DialogHeader>
<div className="space-y-2">
<input
type="text"
placeholder="Заголовок"
className="w-full border p-2"
value={form.title}
onChange={(e) =>
setForm({ ...form, title: e.target.value })
}
/>
<textarea
placeholder="Содержание"
className="w-full border p-2"
value={form.content}
onChange={(e) =>
setForm({ ...form, content: e.target.value })
}
/>
</div>
<Dialog.DialogFooter>
<button
onClick={submitArticle}
disabled={loading}
className="rounded bg-black px-4 py-2 text-white"
>
{loading ? 'Сохранение…' : 'Сохранить'}
</button>
</Dialog.DialogFooter>
</Dialog.DialogContent>
</Dialog.Dialog>
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
{articles.map((article) => (
<Link
key={article.id}
href={`/articles/${article.id}`}
className="block"
>
<Card className="p-4 transition hover:shadow">
<h2 className="text-xl font-semibold">
{article.title}
</h2>
<p className="text-sm text-gray-500">
{article.created_at}
</p>
<p className="mt-2">{article.content_short}</p>
<p className="mt-2 text-sm text-gray-400">
Комментарии: {article.comments_count}
</p>
</Card>
</Link>
))}
</div>
</div>
);
}