Fix UI Admin menu desa
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -15,7 +15,7 @@ function Page() {
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
// Load data
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
const id = params?.id as string;
|
||||
@@ -25,9 +25,12 @@ function Page() {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await lambangState.findUnique.load(id);
|
||||
if (data) {
|
||||
try {
|
||||
const data = await lambangState.findUnique.load(id);
|
||||
lambangState.update.initialize(data);
|
||||
} catch (error) {
|
||||
console.error("Error loading lambang:", error);
|
||||
toast.error("Gagal memuat data lambang desa");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,19 +38,21 @@ function Page() {
|
||||
|
||||
return () => {
|
||||
lambangState.update.reset();
|
||||
lambangState.findUnique.reset(); // opsional: reset juga data lama
|
||||
lambangState.findUnique.reset();
|
||||
};
|
||||
}, [params?.id, router]);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isSubmitting || !lambangState.update.form.judul.trim()) {
|
||||
toast.error("Judul wajib diisi");
|
||||
return;
|
||||
}
|
||||
setIsSubmitting(true)
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const success = await lambangState.update.submit()
|
||||
const success = await lambangState.update.submit();
|
||||
|
||||
if (success) {
|
||||
toast.success("Data berhasil disimpan");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
@@ -58,17 +63,12 @@ function Page() {
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
router.back()
|
||||
}
|
||||
const handleBack = () => router.back();
|
||||
|
||||
if (
|
||||
lambangState.findUnique.loading ||
|
||||
!lambangState.findUnique.data ||
|
||||
lambangState.update.loading
|
||||
) {
|
||||
// Loading state
|
||||
if (lambangState.findUnique.loading || lambangState.update.loading) {
|
||||
return (
|
||||
<Box>
|
||||
<Center h={400}>
|
||||
@@ -77,45 +77,73 @@ function Page() {
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={'xs'}>
|
||||
<Group>
|
||||
|
||||
// Error state
|
||||
if (lambangState.findUnique.error) {
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<Button variant="subtle" onClick={handleBack}>
|
||||
<IconArrowBack color={colors['blue-button']} size={20} />
|
||||
</Button>
|
||||
<Alert icon={<IconAlertCircle size={16} />} color="red">
|
||||
<Text fw="bold">Error</Text>
|
||||
<Text>{lambangState.findUnique.error}</Text>
|
||||
</Alert>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">Edit Lambang Desa</Title>
|
||||
</Group>
|
||||
<Paper bg={colors['white-1']} p={'xs'} w={{ base: '100%', md: '50%' }}>
|
||||
<Stack gap={'xs'}>
|
||||
|
||||
<Paper w={{ base: "100%", md: "50%" }} bg={colors['white-1']} p="md" radius="md" shadow="sm" style={{ border: '1px solid #e0e0e0' }}>
|
||||
<Stack gap="xs">
|
||||
<Title order={3}>Edit Lambang Desa</Title>
|
||||
|
||||
{/* Judul */}
|
||||
<TextInput
|
||||
label={<Text fw="bold">Judul</Text>}
|
||||
placeholder="Judul lambang"
|
||||
value={lambangState.update.form.judul}
|
||||
onChange={(e) => lambangState.update.form.judul = e.currentTarget.value}
|
||||
error={!lambangState.update.form.judul && "Judul wajib diisi"}
|
||||
/>
|
||||
|
||||
{/* Deskripsi */}
|
||||
<Box>
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title order={3}>Edit Lambang Desa</Title>
|
||||
<TextInput
|
||||
label={<Text fz={"md"} fw={"bold"}>Judul</Text>}
|
||||
placeholder="Judul"
|
||||
value={lambangState.update.form.judul}
|
||||
onChange={(e) => lambangState.update.form.judul = e.currentTarget.value}
|
||||
error={!lambangState.update.form.judul && "Judul wajib diisi"}
|
||||
/>
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={lambangState.update.form.deskripsi}
|
||||
onChange={(val) => lambangState.update.form.deskripsi = val}
|
||||
/>
|
||||
</Box>
|
||||
<Group>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={lambangState.update.form.deskripsi}
|
||||
onChange={(val) => lambangState.update.form.deskripsi = val}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Buttons */}
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
loading={isSubmitting || lambangState.update.loading}
|
||||
disabled={!lambangState.update.form.judul}
|
||||
>
|
||||
{isSubmitting ? 'Menyimpan...' : 'Simpan Perubahan'}
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" onClick={handleBack} disabled={isSubmitting || lambangState.update.loading}>
|
||||
Batal
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
||||
@@ -5,38 +5,40 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
import { Box, Button, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title, Tooltip, Center, Alert } from '@mantine/core';
|
||||
import { Dropzone } from '@mantine/dropzone';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
|
||||
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconAlertCircle } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function Page() {
|
||||
const maskotState = useProxy(stateProfileDesa.maskotDesa)
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
|
||||
const [images, setImages] = useState<
|
||||
Array<{ file: File; preview: string; label: string }>
|
||||
>([]);
|
||||
const maskotState = useProxy(stateProfileDesa.maskotDesa);
|
||||
const router = useRouter();
|
||||
const params = useParams();
|
||||
|
||||
const [images, setImages] = useState<Array<{ file: File | null; preview: string; label: string }>>([]);
|
||||
const [formData, setFormData] = useState({
|
||||
judul: maskotState.update.form.judul || '',
|
||||
deskripsi: maskotState.update.form.deskripsi || '',
|
||||
images: [] as Array<{ label: string; imageId: string }>
|
||||
})
|
||||
judul: '',
|
||||
deskripsi: '',
|
||||
images: [] as Array<{ label: string; imageId: string }>,
|
||||
});
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
// Load data
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) return;
|
||||
if (!id) {
|
||||
toast.error("ID tidak valid");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await maskotState.findUnique.load(id);
|
||||
if (data) {
|
||||
// 🔥 INI YANG KURANG!
|
||||
maskotState.update.initialize(data);
|
||||
|
||||
setFormData({
|
||||
@@ -57,28 +59,39 @@ function Page() {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading berita:", error);
|
||||
toast.error("Gagal memuat data berita");
|
||||
console.error("Error loading maskot:", error);
|
||||
toast.error("Gagal memuat data maskot");
|
||||
}
|
||||
};
|
||||
|
||||
loadData();
|
||||
}, [params?.id]);
|
||||
|
||||
return () => {
|
||||
maskotState.update.reset();
|
||||
maskotState.findUnique.reset();
|
||||
};
|
||||
}, [params?.id, router]);
|
||||
|
||||
const handleBack = () => {
|
||||
router.back()
|
||||
}
|
||||
const handleBack = () => router.back();
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isSubmitting || !formData.judul.trim()) {
|
||||
toast.error("Judul wajib diisi");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const uploadedImages = [];
|
||||
|
||||
// Upload semua gambar baru
|
||||
for (const img of images) {
|
||||
if (!img.file || !(img.file instanceof File)) {
|
||||
toast.error("File tidak valid untuk di-upload");
|
||||
continue; // atau return kalau kamu mau hentikan semua
|
||||
if (!img.file) {
|
||||
// Kalau gambar lama, skip upload
|
||||
if (!img.preview) continue;
|
||||
uploadedImages.push({ imageId: '', label: img.label });
|
||||
continue;
|
||||
}
|
||||
|
||||
const res = await ApiFetch.api.fileStorage.create.post({
|
||||
@@ -92,10 +105,7 @@ function Page() {
|
||||
return;
|
||||
}
|
||||
|
||||
uploadedImages.push({
|
||||
imageId: uploaded.id,
|
||||
label: img.label || 'main',
|
||||
});
|
||||
uploadedImages.push({ imageId: uploaded.id, label: img.label || 'main' });
|
||||
}
|
||||
|
||||
// Update ke global state
|
||||
@@ -109,130 +119,159 @@ function Page() {
|
||||
toast.success("Maskot berhasil diperbarui!");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error update maskot:", error);
|
||||
toast.error("Gagal update maskot");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={'xs'}>
|
||||
<Group>
|
||||
// Loading state
|
||||
if (maskotState.findUnique.loading || maskotState.update.loading) {
|
||||
return (
|
||||
<Box>
|
||||
<Center h={400}>
|
||||
<Text>Memuat data...</Text>
|
||||
</Center>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
// Error state
|
||||
if (maskotState.findUnique.error) {
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<Button variant="subtle" onClick={handleBack}>
|
||||
<IconArrowBack color={colors['blue-button']} size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
<Paper bg={colors['white-1']} p={'xs'} w={{ base: '100%', md: '100%' }}>
|
||||
<Stack gap={'xs'}>
|
||||
<Box>
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title order={3}>Edit Maskot Desa</Title>
|
||||
<TextInput
|
||||
w={{ base: '100%', md: '50%' }}
|
||||
label={<Text fz={"md"} fw={"bold"}>Judul</Text>}
|
||||
placeholder="Masukkan judul"
|
||||
value={formData.judul}
|
||||
onChange={(val) => setFormData({ ...formData, judul: val.currentTarget.value })}
|
||||
/>
|
||||
<Box w={{ base: '100%', md: '50%' }}>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={formData.deskripsi}
|
||||
onChange={(val) => setFormData({ ...formData, deskripsi: val })}
|
||||
/>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Gambar</Text>
|
||||
<Box w={{ base: '100%', md: '50%' }}>
|
||||
<Dropzone
|
||||
onDrop={(files) => {
|
||||
const newImages = files.map((file) => ({
|
||||
file,
|
||||
preview: URL.createObjectURL(file),
|
||||
label: '',
|
||||
}));
|
||||
setImages((prev) => [...prev, ...newImages]);
|
||||
}}
|
||||
>
|
||||
<Group justify="center" gap="xl" mih={220} style={{ pointerEvents: 'none' }}>
|
||||
<Dropzone.Accept>
|
||||
<IconUpload size={52} color="var(--mantine-color-blue-6)" stroke={1.5} />
|
||||
</Dropzone.Accept>
|
||||
<Dropzone.Reject>
|
||||
<IconX size={52} color="var(--mantine-color-red-6)" stroke={1.5} />
|
||||
</Dropzone.Reject>
|
||||
<Dropzone.Idle>
|
||||
<IconPhoto size={52} color="var(--mantine-color-dimmed)" stroke={1.5} />
|
||||
</Dropzone.Idle>
|
||||
<Alert icon={<IconAlertCircle size={16} />} color="red">
|
||||
<Text fw="bold">Error</Text>
|
||||
<Text>{maskotState.findUnique.error}</Text>
|
||||
</Alert>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
<div>
|
||||
<Text size="xl" inline>
|
||||
Drag images here or click to select files
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" inline mt={7}>
|
||||
Attach as many files as you like, each file should not exceed 5mb
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Dropzone>
|
||||
</Box>
|
||||
</Box>
|
||||
<SimpleGrid cols={{ base: 2, md: 4 }} >
|
||||
{images.map((img, index) => (
|
||||
<Box key={index} mb="md">
|
||||
<Paper p="sm" radius="md" withBorder style={{ position: 'relative', maxWidth: 300 }}>
|
||||
<Stack gap={'xs'}>
|
||||
<Group>
|
||||
<Button
|
||||
size="xs"
|
||||
color="red"
|
||||
variant="light"
|
||||
onClick={() => {
|
||||
const updated = [...images];
|
||||
updated.splice(index, 1);
|
||||
setImages(updated);
|
||||
}}
|
||||
>
|
||||
Hapus
|
||||
</Button>
|
||||
</Group>
|
||||
<Image
|
||||
src={img.preview}
|
||||
alt={`Preview ${index}`}
|
||||
width={280}
|
||||
height={180}
|
||||
fit="cover"
|
||||
radius="sm"
|
||||
/>
|
||||
<TextInput
|
||||
label={`Label Gambar ${index + 1}`}
|
||||
placeholder="Contoh: Logo, Maskot, Dll"
|
||||
value={img.label}
|
||||
onChange={(e) => {
|
||||
const updated = [...images];
|
||||
updated[index].label = e.currentTarget.value;
|
||||
setImages(updated);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
<Group>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">Edit Maskot Desa</Title>
|
||||
</Group>
|
||||
|
||||
<Paper w={{ base: "100%", md: "50%" }} bg={colors['white-1']} p="md" radius="md" shadow="sm" style={{ border: '1px solid #e0e0e0' }}>
|
||||
<Stack gap="xs">
|
||||
<Title order={3}>Edit Maskot Desa</Title>
|
||||
|
||||
{/* Judul */}
|
||||
<TextInput
|
||||
label={<Text fw="bold">Judul</Text>}
|
||||
placeholder="Masukkan judul maskot"
|
||||
value={formData.judul}
|
||||
onChange={(e) => setFormData({ ...formData, judul: e.currentTarget.value })}
|
||||
error={!formData.judul && "Judul wajib diisi"}
|
||||
/>
|
||||
|
||||
{/* Deskripsi */}
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={formData.deskripsi}
|
||||
onChange={(val) => setFormData({ ...formData, deskripsi: val })}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Upload Gambar */}
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Gambar</Text>
|
||||
<Dropzone
|
||||
onDrop={(files) => {
|
||||
const newImages = files.map((file) => ({
|
||||
file,
|
||||
preview: URL.createObjectURL(file),
|
||||
label: '',
|
||||
}));
|
||||
setImages((prev) => [...prev, ...newImages]);
|
||||
}}
|
||||
>
|
||||
<Group justify="center" gap="xl" mih={220} style={{ pointerEvents: 'none' }}>
|
||||
<Dropzone.Accept><IconUpload size={52} color="var(--mantine-color-blue-6)" stroke={1.5} /></Dropzone.Accept>
|
||||
<Dropzone.Reject><IconX size={52} color="var(--mantine-color-red-6)" stroke={1.5} /></Dropzone.Reject>
|
||||
<Dropzone.Idle><IconPhoto size={52} color="var(--mantine-color-dimmed)" stroke={1.5} /></Dropzone.Idle>
|
||||
<div>
|
||||
<Text size="xl" inline>Drag images here or click to select files</Text>
|
||||
<Text size="sm" c="dimmed" inline mt={7}>Attach as many files as you like, each file max 5mb</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Dropzone>
|
||||
</Box>
|
||||
|
||||
{/* Preview Gambar */}
|
||||
<SimpleGrid cols={{ base: 2, md: 4 }}>
|
||||
{images.map((img, index) => (
|
||||
<Box key={index} mb="md">
|
||||
<Paper p="sm" radius="md" withBorder style={{ position: 'relative', maxWidth: 300 }}>
|
||||
<Stack gap="xs">
|
||||
<Group justify="space-between">
|
||||
<Button
|
||||
size="xs"
|
||||
color="red"
|
||||
variant="light"
|
||||
onClick={() => {
|
||||
const updated = [...images];
|
||||
updated.splice(index, 1);
|
||||
setImages(updated);
|
||||
}}
|
||||
>
|
||||
Hapus
|
||||
</Button>
|
||||
</Group>
|
||||
<Image
|
||||
src={img.preview}
|
||||
alt={`Preview ${index}`}
|
||||
width={280}
|
||||
height={180}
|
||||
fit="cover"
|
||||
radius="sm"
|
||||
/>
|
||||
<TextInput
|
||||
label={`Label Gambar ${index + 1}`}
|
||||
placeholder="Contoh: Logo, Maskot, Dll"
|
||||
value={img.label}
|
||||
onChange={(e) => {
|
||||
const updated = [...images];
|
||||
updated[index].label = e.currentTarget.value;
|
||||
setImages(updated);
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
{/* Buttons */}
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
loading={isSubmitting || maskotState.update.loading}
|
||||
disabled={!formData.judul}
|
||||
>
|
||||
{isSubmitting ? 'Menyimpan...' : 'Simpan Perubahan'}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleBack} disabled={isSubmitting || maskotState.update.loading}>
|
||||
Batal
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
@@ -16,6 +16,7 @@ function Page() {
|
||||
const params = useParams()
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
// Load data
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
const id = params?.id as string;
|
||||
@@ -25,9 +26,14 @@ function Page() {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await sejarahState.findUnique.load(id);
|
||||
if (data) {
|
||||
sejarahState.update.initialize(data);
|
||||
try {
|
||||
const data = await sejarahState.findUnique.load(id);
|
||||
if (data) {
|
||||
sejarahState.update.initialize(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error loading sejarah:", error);
|
||||
toast.error("Gagal memuat data sejarah desa");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,19 +41,19 @@ function Page() {
|
||||
|
||||
return () => {
|
||||
sejarahState.update.reset();
|
||||
sejarahState.findUnique.reset(); // opsional: reset juga data lama
|
||||
sejarahState.findUnique.reset();
|
||||
};
|
||||
}, [params?.id, router]);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isSubmitting || !sejarahState.update.form.judul.trim()) {
|
||||
toast.error("Judul wajib diisi");
|
||||
return;
|
||||
}
|
||||
setIsSubmitting(true)
|
||||
|
||||
setIsSubmitting(true);
|
||||
try {
|
||||
const success = await sejarahState.update.submit()
|
||||
const success = await sejarahState.update.submit();
|
||||
if (success) {
|
||||
toast.success("Data berhasil disimpan");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
@@ -58,17 +64,12 @@ function Page() {
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
router.back()
|
||||
}
|
||||
const handleBack = () => router.back();
|
||||
|
||||
if (
|
||||
sejarahState.findUnique.loading ||
|
||||
!sejarahState.findUnique.data ||
|
||||
sejarahState.update.loading
|
||||
) {
|
||||
// Loading state
|
||||
if (sejarahState.findUnique.loading || sejarahState.update.loading) {
|
||||
return (
|
||||
<Box>
|
||||
<Center h={400}>
|
||||
@@ -77,45 +78,73 @@ function Page() {
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={'xs'}>
|
||||
<Group>
|
||||
|
||||
// Error state
|
||||
if (sejarahState.findUnique.error) {
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<Button variant="subtle" onClick={handleBack}>
|
||||
<IconArrowBack color={colors['blue-button']} size={20} />
|
||||
</Button>
|
||||
<Alert icon={<IconAlertCircle size={16} />} color="red">
|
||||
<Text fw="bold">Error</Text>
|
||||
<Text>{sejarahState.findUnique.error}</Text>
|
||||
</Alert>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">Edit Sejarah Desa</Title>
|
||||
</Group>
|
||||
<Paper bg={colors['white-1']} p={'xs'} w={{ base: '100%', md: '50%' }}>
|
||||
<Stack gap={'xs'}>
|
||||
|
||||
<Paper w={{ base: "100%", md: "50%" }} bg={colors['white-1']} p="md" radius="md" shadow="sm" style={{ border: '1px solid #e0e0e0' }}>
|
||||
<Stack gap="xs">
|
||||
<Title order={3}>Edit Sejarah Desa</Title>
|
||||
|
||||
{/* Judul */}
|
||||
<TextInput
|
||||
label={<Text fw="bold">Judul</Text>}
|
||||
placeholder="Judul sejarah"
|
||||
value={sejarahState.update.form.judul}
|
||||
onChange={(e) => sejarahState.update.form.judul = e.currentTarget.value}
|
||||
error={!sejarahState.update.form.judul && "Judul wajib diisi"}
|
||||
/>
|
||||
|
||||
{/* Deskripsi */}
|
||||
<Box>
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title order={3}>Edit Sejarah Desa</Title>
|
||||
<TextInput
|
||||
label={<Text fz={"md"} fw={"bold"}>Judul</Text>}
|
||||
placeholder="Judul"
|
||||
value={sejarahState.update.form.judul}
|
||||
onChange={(e) => sejarahState.update.form.judul = e.currentTarget.value}
|
||||
error={!sejarahState.update.form.judul && "Judul wajib diisi"}
|
||||
/>
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={sejarahState.update.form.deskripsi}
|
||||
onChange={(val) => sejarahState.update.form.deskripsi = val}
|
||||
/>
|
||||
</Box>
|
||||
<Group>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Text fz={"md"} fw={"bold"}>Deskripsi</Text>
|
||||
<EditEditor
|
||||
value={sejarahState.update.form.deskripsi}
|
||||
onChange={(val) => sejarahState.update.form.deskripsi = val}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Buttons */}
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
loading={isSubmitting || sejarahState.update.loading}
|
||||
disabled={!sejarahState.update.form.judul}
|
||||
>
|
||||
{isSubmitting ? 'Menyimpan...' : 'Simpan Perubahan'}
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" onClick={handleBack} disabled={isSubmitting || sejarahState.update.loading}>
|
||||
Batal
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
|
||||
@@ -3,122 +3,153 @@
|
||||
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Center, Group, Paper, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconArrowBack } from '@tabler/icons-react';
|
||||
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
|
||||
import { useParams, useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
|
||||
function Page() {
|
||||
const visiMisiState = useProxy(stateProfileDesa.visiMisiDesa)
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
const visiMisiState = useProxy(stateProfileDesa.visiMisiDesa)
|
||||
const router = useRouter()
|
||||
const params = useParams()
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) {
|
||||
toast.error("ID tidak valid");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
return;
|
||||
}
|
||||
// Load data
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
const id = params?.id as string;
|
||||
if (!id) {
|
||||
toast.error("ID tidak valid");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await visiMisiState.findUnique.load(id);
|
||||
if (data) {
|
||||
visiMisiState.update.initialize(data);
|
||||
}
|
||||
try {
|
||||
const data = await visiMisiState.findUnique.load(id);
|
||||
visiMisiState.update.initialize(data);
|
||||
} catch (error) {
|
||||
console.error("Error loading visi misi:", error);
|
||||
toast.error("Gagal memuat data visi misi desa");
|
||||
}
|
||||
};
|
||||
|
||||
loadData();
|
||||
|
||||
return () => {
|
||||
visiMisiState.update.reset();
|
||||
visiMisiState.findUnique.reset();
|
||||
};
|
||||
}, [params?.id, router]);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isSubmitting || !visiMisiState.update.form.visi.trim()) {
|
||||
toast.error("Visi wajib diisi");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
try {
|
||||
const success = await visiMisiState.update.submit();
|
||||
|
||||
if (success) {
|
||||
toast.success("Data berhasil disimpan");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error update visi misi desa:", error);
|
||||
toast.error("Terjadi kesalahan saat update visi misi desa");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadData();
|
||||
const handleBack = () => router.back();
|
||||
|
||||
return () => {
|
||||
visiMisiState.update.reset();
|
||||
visiMisiState.findUnique.reset(); // opsional: reset juga data lama
|
||||
};
|
||||
}, [params?.id, router]);
|
||||
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isSubmitting || !visiMisiState.update.form.visi.trim()) {
|
||||
toast.error("Visi wajib diisi");
|
||||
return;
|
||||
}
|
||||
setIsSubmitting(true)
|
||||
try {
|
||||
const success = await visiMisiState.update.submit()
|
||||
if (success) {
|
||||
toast.success("Data berhasil disimpan");
|
||||
router.push("/admin/desa/profile/profile-desa");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error update sejarah desa:", error);
|
||||
toast.error("Terjadi kesalahan saat update sejarah desa");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
if (
|
||||
visiMisiState.findUnique.loading ||
|
||||
!visiMisiState.findUnique.data ||
|
||||
visiMisiState.update.loading
|
||||
) {
|
||||
return (
|
||||
<Box>
|
||||
<Center h={400}>
|
||||
<Text>Memuat data...</Text>
|
||||
</Center>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={'xs'}>
|
||||
<Group>
|
||||
<Button variant="subtle" onClick={handleBack}>
|
||||
<IconArrowBack color={colors['blue-button']} size={20} />
|
||||
</Button>
|
||||
</Group>
|
||||
<Paper bg={colors['white-1']} p={'xs'} w={{ base: '100%', md: '50%' }}>
|
||||
<Stack gap={'xs'}>
|
||||
// Loading state
|
||||
if (visiMisiState.findUnique.loading || visiMisiState.update.loading) {
|
||||
return (
|
||||
<Box>
|
||||
<Box>
|
||||
<Stack>
|
||||
<Title order={3}>Edit Visi Misi Desa</Title>
|
||||
<Text fz={"md"} fw={"bold"}>Visi</Text>
|
||||
<EditEditor
|
||||
value={visiMisiState.update.form.visi}
|
||||
onChange={(val) => visiMisiState.update.form.visi = val}
|
||||
/>
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Misi</Text>
|
||||
<EditEditor
|
||||
value={visiMisiState.update.form.misi}
|
||||
onChange={(val) => visiMisiState.update.form.misi = val}
|
||||
/>
|
||||
</Box>
|
||||
<Group>
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Center h={400}>
|
||||
<Text>Memuat data...</Text>
|
||||
</Center>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
// Error state
|
||||
if (visiMisiState.findUnique.error) {
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="md">
|
||||
<Button variant="subtle" onClick={handleBack}>
|
||||
<IconArrowBack color={colors['blue-button']} size={20} />
|
||||
</Button>
|
||||
<Alert icon={<IconAlertCircle size={16} />} color="red">
|
||||
<Text fw="bold">Error</Text>
|
||||
<Text>{visiMisiState.findUnique.error}</Text>
|
||||
</Alert>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap="xs">
|
||||
<Group mb="md">
|
||||
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
|
||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Title order={4} ml="sm" c="dark">Edit Visi Misi Desa</Title>
|
||||
</Group>
|
||||
|
||||
<Paper w={{ base: "100%", md: "50%" }} bg={colors['white-1']} p="md" radius="md" shadow="sm" style={{ border: '1px solid #e0e0e0' }}>
|
||||
<Stack gap="xs">
|
||||
<Title order={3}>Edit Visi Misi Desa</Title>
|
||||
|
||||
{/* Visi */}
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Visi</Text>
|
||||
<EditEditor
|
||||
value={visiMisiState.update.form.visi}
|
||||
onChange={(val) => visiMisiState.update.form.visi = val}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Misi */}
|
||||
<Box>
|
||||
<Text fz={"md"} fw={"bold"}>Misi</Text>
|
||||
<EditEditor
|
||||
value={visiMisiState.update.form.misi}
|
||||
onChange={(val) => visiMisiState.update.form.misi = val}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Buttons */}
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={handleSubmit}
|
||||
loading={isSubmitting || visiMisiState.update.loading}
|
||||
disabled={!visiMisiState.update.form.visi}
|
||||
>
|
||||
{isSubmitting ? 'Menyimpan...' : 'Simpan Perubahan'}
|
||||
</Button>
|
||||
|
||||
<Button variant="outline" onClick={handleBack} disabled={isSubmitting || visiMisiState.update.loading}>
|
||||
Batal
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Card, Center, Grid, GridCol, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
|
||||
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||
import { useSnapshot } from 'valtio';
|
||||
import stateProfileDesa from '../../../_state/desa/profile';
|
||||
import { useEffect } from 'react';
|
||||
@@ -12,7 +12,6 @@ function Page() {
|
||||
const router = useRouter();
|
||||
const snap = useSnapshot(stateProfileDesa);
|
||||
|
||||
// Panggil load data sekali saat komponen mount
|
||||
useEffect(() => {
|
||||
stateProfileDesa.sejarahDesa.findUnique.load("edit");
|
||||
stateProfileDesa.visiMisiDesa.findUnique.load("edit");
|
||||
@@ -26,142 +25,219 @@ function Page() {
|
||||
const maskot = snap.maskotDesa.findUnique.data;
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"lg"}>
|
||||
<Title order={2}>Preview Profile Desa</Title>
|
||||
<Paper bg={colors['white-1']} p="lg" radius="md" shadow="sm">
|
||||
<Stack gap="lg">
|
||||
<Title order={2} c={colors['blue-button']}>Preview Profile Desa</Title>
|
||||
|
||||
{/* Sejarah Desa */}
|
||||
{sejarah && (
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"md"} bg={colors['BG-trans']}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={2}>Preview Sejarah Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Button bg={colors['blue-button']} onClick={() => router.push(`/admin/desa/profile/profile-desa/${sejarah.id}/sejarah_desa`)}>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box pb={30}>
|
||||
<Paper p="xl" bg={'white'} withBorder radius="md" shadow="xs">
|
||||
<Grid align="center">
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={3} c={colors['blue-button']}>Preview Sejarah Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Sejarah Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
leftSection={<IconEdit size={18} stroke={2} />}
|
||||
radius="md"
|
||||
onClick={() => router.push(`/admin/desa/profile/profile-desa/${sejarah.id}/sejarah_desa`)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
<Box px={{ base: 0, md: 50 }} py="xl">
|
||||
<Paper bg={colors['white-1']} withBorder radius="md" shadow="xs" p="lg">
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
<Image src="/darmasaba-icon.png" w={{ base: 150, md: 250 }} alt="Logo Desa" />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>{sejarah.judul}</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: sejarah.deskripsi }} />
|
||||
</Paper>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py="md"
|
||||
px="sm"
|
||||
radius="md"
|
||||
style={{ mt: -30, boxShadow: '0 4px 20px rgba(0,0,0,0.15)' }}
|
||||
>
|
||||
<Text ta="center" c={colors['white-1']} fw="bolder" fz={{ base: "1.2rem", md: "1.6rem" }}>
|
||||
{sejarah.judul}
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
<Divider my="md" color={colors['blue-button']} />
|
||||
<Text fz={{ base: "md", md: "h3" }} ta="justify" dangerouslySetInnerHTML={{ __html: sejarah.deskripsi }} />
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
{/* Visi Misi Desa */}
|
||||
{visiMisi && (
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"md"} bg={colors['BG-trans']}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={2}>Preview Visi Misi Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Button onClick={() => router.push(`/admin/desa/profile/profile-desa/${visiMisi.id}/visi_misi_desa`)} bg={colors['blue-button']}>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box pb={30}>
|
||||
<Paper p="xl" bg={'white'} withBorder radius="md" shadow="xs">
|
||||
<Grid align="center">
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={3} c={colors['blue-button']}>Preview Visi Misi Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Visi Misi Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
leftSection={<IconEdit size={18} stroke={2} />}
|
||||
radius="md"
|
||||
onClick={() => router.push(`/admin/desa/profile/profile-desa/${visiMisi.id}/visi_misi_desa`)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
<Box px={{ base: 0, md: 50 }} py="xl">
|
||||
<Paper bg={colors['white-1']} withBorder radius="md" shadow="xs" p="lg">
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
<Image src="/darmasaba-icon.png" w={{ base: 150, md: 250 }} alt="Logo Desa" />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Visi Misi Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text fw={"bold"} fz={{ base: "lg", md: "h2" }}>Visi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: visiMisi.visi }} />
|
||||
<Text fw={"bold"} fz={{ base: "lg", md: "h2" }}>Misi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: visiMisi.misi }} />
|
||||
</Paper>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py="md"
|
||||
px="sm"
|
||||
radius="md"
|
||||
style={{ mt: -30, boxShadow: '0 4px 20px rgba(0,0,0,0.15)' }}
|
||||
>
|
||||
<Text ta="center" c={colors['white-1']} fw="bolder" fz={{ base: "1.2rem", md: "1.6rem" }}>
|
||||
Visi Misi Desa
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
<Divider my="md" color={colors['blue-button']} />
|
||||
<Text fw="bold" fz={{ base: "lg", md: "h2" }}>Visi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta="justify" dangerouslySetInnerHTML={{ __html: visiMisi.visi }} />
|
||||
<Text fw="bold" fz={{ base: "lg", md: "h2" }}>Misi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta="justify" dangerouslySetInnerHTML={{ __html: visiMisi.misi }} />
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
{/* Lambang Desa */}
|
||||
{lambang && (
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"md"} bg={colors['BG-trans']}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={2}>Preview Lambang Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Button onClick={() => router.push(`/admin/desa/profile/profile-desa/${lambang.id}/lambang_desa`)} bg={colors['blue-button']}>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box pb={30}>
|
||||
<Paper p="xl" bg={'white'} withBorder radius="md" shadow="xs">
|
||||
<Grid align="center">
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={3} c={colors['blue-button']}>Preview Lambang Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Lambang Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
leftSection={<IconEdit size={18} stroke={2} />}
|
||||
radius="md"
|
||||
onClick={() => router.push(`/admin/desa/profile/profile-desa/${lambang.id}/lambang_desa`)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
<Box px={{ base: 0, md: 50 }} py="xl">
|
||||
<Paper bg={colors['white-1']} withBorder radius="md" shadow="xs" p="lg">
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
<Image src="/darmasaba-icon.png" w={{ base: 150, md: 250 }} alt="Logo Desa" />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Lambang Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: lambang.deskripsi }} />
|
||||
</Paper>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py="md"
|
||||
px="sm"
|
||||
radius="md"
|
||||
style={{ mt: -30, boxShadow: '0 4px 20px rgba(0,0,0,0.15)' }}
|
||||
>
|
||||
<Text ta="center" c={colors['white-1']} fw="bolder" fz={{ base: "1.2rem", md: "1.6rem" }}>
|
||||
Lambang Desa
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
<Divider my="md" color={colors['blue-button']} />
|
||||
<Text fz={{ base: "md", md: "h3" }} ta="justify" dangerouslySetInnerHTML={{ __html: lambang.deskripsi }} />
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
|
||||
{/* Maskot Desa */}
|
||||
{maskot && (
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"md"} bg={colors['BG-trans']}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={2}>Preview Maskot Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Button onClick={() => router.push(`/admin/desa/profile/profile-desa/${maskot.id}/maskot_desa`)} bg={colors['blue-button']}>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
<Box pb={30}>
|
||||
<Paper p="xl" bg={'white'} withBorder radius="md" shadow="xs">
|
||||
<Grid align="center">
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={3} c={colors['blue-button']}>Preview Maskot Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Tooltip label="Edit Maskot Desa" withArrow>
|
||||
<Button
|
||||
c="green"
|
||||
variant="light"
|
||||
leftSection={<IconEdit size={18} stroke={2} />}
|
||||
radius="md"
|
||||
onClick={() => router.push(`/admin/desa/profile/profile-desa/${maskot.id}/maskot_desa`)}
|
||||
>
|
||||
Edit
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
|
||||
<Box px={{ base: 0, md: 50 }} py="xl">
|
||||
<Paper bg={colors['white-1']} withBorder radius="md" shadow="xs" p="lg">
|
||||
<Stack gap={0}>
|
||||
<Center>
|
||||
<Image src={"/pudak-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
<Image src="/pudak-icon.png" w={{ base: 150, md: 250 }} alt="Maskot Desa" />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Maskot Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: maskot.deskripsi }} />
|
||||
<Group wrap="wrap" gap="md">
|
||||
{maskot.images.map((img, index) => (
|
||||
<Card key={index} p="xs" w={220}>
|
||||
<Image
|
||||
src={img.image.link}
|
||||
alt={img.label}
|
||||
w={200}
|
||||
h={200}
|
||||
fit="cover"
|
||||
radius="md"
|
||||
style={{ border: '1px solid #ccc', objectFit: 'cover' }}
|
||||
/>
|
||||
<Paper
|
||||
bg={colors['blue-button']}
|
||||
py="md"
|
||||
px="sm"
|
||||
radius="md"
|
||||
style={{ mt: -30, boxShadow: '0 4px 20px rgba(0,0,0,0.15)' }}
|
||||
>
|
||||
<Text ta="center" c={colors['white-1']} fw="bolder" fz={{ base: "1.2rem", md: "1.6rem" }}>
|
||||
Maskot Desa
|
||||
</Text>
|
||||
</Paper>
|
||||
</Stack>
|
||||
<Divider my="md" color={colors['blue-button']} />
|
||||
<Text fz={{ base: "md", md: "h3" }} ta="justify" dangerouslySetInnerHTML={{ __html: maskot.deskripsi }} />
|
||||
<Stack mt="md" gap="sm">
|
||||
<SimpleGrid cols={{ base: 2, md: 4 }} spacing="md">
|
||||
{maskot.images.map((img, idx) => (
|
||||
<Card withBorder key={idx} p="xs" w={{ base: '100%', md: 180 }}>
|
||||
<Center>
|
||||
<Image
|
||||
src={img.image.link}
|
||||
alt={img.label}
|
||||
w={150}
|
||||
h={150}
|
||||
fit="cover"
|
||||
radius="md"
|
||||
style={{ border: '1px solid #ccc' }}
|
||||
/>
|
||||
</Center>
|
||||
<Text ta="center" mt="xs" fw="bold">{img.label}</Text>
|
||||
</Card>
|
||||
))}
|
||||
</Group>
|
||||
</Paper>
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
Reference in New Issue
Block a user