feat: implement help page with equal height cards
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
453
Dashboard-MD/BANTUAN.md
Normal file
453
Dashboard-MD/BANTUAN.md
Normal file
@@ -0,0 +1,453 @@
|
||||
Design Contract – Halaman Bantuan / Support Center
|
||||
|
||||
Dokumen ini adalah kontrak desain UI/UX untuk halaman Bantuan / Support Center.
|
||||
Implementasi tidak dapat dilanjutkan tanpa mengikuti spesifikasi ini secara konsisten.
|
||||
|
||||
1. Tujuan Halaman
|
||||
|
||||
Halaman Bantuan bertujuan untuk:
|
||||
|
||||
Memberikan akses cepat ke panduan & dokumentasi
|
||||
|
||||
Menyediakan video tutorial
|
||||
|
||||
Menjawab pertanyaan umum (FAQ)
|
||||
|
||||
Menyediakan kontak support
|
||||
|
||||
Menyediakan virtual assistant (chat)
|
||||
|
||||
Menampilkan statistik kredibilitas platform
|
||||
|
||||
2. Struktur Layout Keseluruhan
|
||||
Layout Grid
|
||||
|
||||
Menggunakan 3-column responsive grid.
|
||||
|
||||
Desktop (≥ 1200px)
|
||||
|
||||
Grid: 3 columns
|
||||
|
||||
Gap: 32px
|
||||
|
||||
Container max-width: 1200px – 1320px
|
||||
|
||||
Center aligned
|
||||
|
||||
Tablet (768px – 1199px)
|
||||
|
||||
Grid: 2 columns
|
||||
|
||||
Gap: 24px
|
||||
|
||||
Mobile (< 768px)
|
||||
|
||||
Grid: 1 column
|
||||
|
||||
Gap: 16px
|
||||
|
||||
Card full width
|
||||
|
||||
3. Struktur Komponen UI
|
||||
3.1 Card Utama (Reusable Component)
|
||||
|
||||
Semua section menggunakan komponen dasar:
|
||||
|
||||
Card
|
||||
├── Icon Container
|
||||
├── Title
|
||||
├── List / Content
|
||||
|
||||
Spesifikasi Card
|
||||
|
||||
Border radius: 16px
|
||||
|
||||
Padding: 24px
|
||||
|
||||
Shadow:
|
||||
|
||||
Light: soft shadow
|
||||
|
||||
Dark: subtle glow / low-opacity shadow
|
||||
|
||||
Transition hover: 0.2s ease
|
||||
|
||||
Hover effect:
|
||||
|
||||
Slight lift (translateY(-2px))
|
||||
|
||||
Elevation shadow increase
|
||||
|
||||
4. Daftar Komponen
|
||||
4.1 Panduan Memulai
|
||||
|
||||
Isi:
|
||||
|
||||
Cara Login
|
||||
|
||||
Navigasi Dashboard
|
||||
|
||||
Fitur Dasar
|
||||
|
||||
Tips & Trik
|
||||
|
||||
Interaksi:
|
||||
|
||||
Klik item → navigasi ke halaman detail
|
||||
|
||||
Cursor pointer
|
||||
|
||||
Hover underline atau highlight
|
||||
|
||||
4.2 Video Tutorial
|
||||
|
||||
Isi:
|
||||
|
||||
Dashboard Overview
|
||||
|
||||
Analisis Data
|
||||
|
||||
Membuat Laporan
|
||||
|
||||
Export Data
|
||||
|
||||
Interaksi:
|
||||
|
||||
Klik → buka modal video atau halaman video
|
||||
|
||||
Bisa tambahkan icon play kecil di tiap item
|
||||
|
||||
4.3 FAQ
|
||||
|
||||
Isi:
|
||||
|
||||
Masalah Login
|
||||
|
||||
Reset Password
|
||||
|
||||
Akses Data
|
||||
|
||||
Laporan Error
|
||||
|
||||
Interaksi:
|
||||
|
||||
Accordion expand/collapse
|
||||
|
||||
Animasi height smooth (200–300ms)
|
||||
|
||||
4.4 Hubungi Support
|
||||
|
||||
Isi:
|
||||
|
||||
Email
|
||||
|
||||
WhatsApp
|
||||
|
||||
Jam Kerja
|
||||
|
||||
Waktu Respon
|
||||
|
||||
Interaksi:
|
||||
|
||||
Email → mailto link
|
||||
|
||||
WhatsApp → wa.me link
|
||||
|
||||
Jam kerja non-clickable
|
||||
|
||||
4.5 Dokumentasi
|
||||
|
||||
Isi:
|
||||
|
||||
API Reference
|
||||
|
||||
Integrasi Sistem
|
||||
|
||||
Format Data
|
||||
|
||||
Best Practices
|
||||
|
||||
Interaksi:
|
||||
|
||||
Klik → navigasi dokumentasi
|
||||
|
||||
4.6 Jenna – Virtual Assistant
|
||||
|
||||
Komponen:
|
||||
|
||||
Chat Container
|
||||
├── Header Title
|
||||
├── Chat Message Area
|
||||
├── Input Field
|
||||
└── Send Button
|
||||
|
||||
|
||||
Spesifikasi:
|
||||
|
||||
Tinggi tetap (±300–350px)
|
||||
|
||||
Scrollable message container
|
||||
|
||||
Input rounded
|
||||
|
||||
Send button icon (arrow)
|
||||
|
||||
Interaksi:
|
||||
|
||||
Enter → kirim pesan
|
||||
|
||||
Klik send → kirim pesan
|
||||
|
||||
Auto-scroll ke pesan terakhir
|
||||
|
||||
Disabled state saat loading
|
||||
|
||||
4.7 Statistik Section
|
||||
|
||||
3 Card horizontal:
|
||||
|
||||
150+ Artikel Panduan
|
||||
|
||||
50+ Video Tutorial
|
||||
|
||||
24/7 Support Aktif
|
||||
|
||||
Spesifikasi:
|
||||
|
||||
Center aligned text
|
||||
|
||||
Angka besar (font-size 32–40px)
|
||||
|
||||
Subtext kecil opacity 70%
|
||||
|
||||
5. Design System
|
||||
5.1 Light Mode
|
||||
Background
|
||||
|
||||
Page background: #F5F7FA
|
||||
|
||||
Card background: #FFFFFF
|
||||
|
||||
Primary Color
|
||||
|
||||
Blue: #3B82F6
|
||||
|
||||
Hover: #2563EB
|
||||
|
||||
Text
|
||||
|
||||
Primary: #111827
|
||||
|
||||
Secondary: #6B7280
|
||||
|
||||
Border
|
||||
|
||||
#E5E7EB
|
||||
|
||||
Shadow
|
||||
0 4px 12px rgba(0,0,0,0.05)
|
||||
|
||||
Icon Container
|
||||
|
||||
Background: #EFF6FF
|
||||
|
||||
Icon color: #2563EB
|
||||
|
||||
5.2 Dark Mode
|
||||
Background
|
||||
|
||||
Page background: #0F172A
|
||||
|
||||
Card background: #1E293B
|
||||
|
||||
Primary Color
|
||||
|
||||
Blue: #3B82F6
|
||||
|
||||
Hover: #60A5FA
|
||||
|
||||
Text
|
||||
|
||||
Primary: #F8FAFC
|
||||
|
||||
Secondary: #94A3B8
|
||||
|
||||
Border
|
||||
|
||||
#334155
|
||||
|
||||
Shadow
|
||||
0 4px 20px rgba(0,0,0,0.4)
|
||||
|
||||
Icon Container
|
||||
|
||||
Background: #1D4ED8
|
||||
|
||||
Icon color: #FFFFFF
|
||||
|
||||
6. Typography
|
||||
|
||||
Font Family:
|
||||
|
||||
Inter / Poppins / System UI
|
||||
|
||||
Hierarchy:
|
||||
|
||||
Element Size Weight
|
||||
Section Title 18–20px 600
|
||||
Card Title 16–18px 600
|
||||
List Item 14–16px 400
|
||||
Statistik Number 32–40px 700
|
||||
|
||||
Line height:
|
||||
|
||||
1.5 standard
|
||||
|
||||
1.2 for large numbers
|
||||
|
||||
7. Spacing System
|
||||
|
||||
Gunakan sistem 8pt grid:
|
||||
|
||||
8px
|
||||
|
||||
16px
|
||||
|
||||
24px
|
||||
|
||||
32px
|
||||
|
||||
48px
|
||||
|
||||
Padding Card: 24px
|
||||
Gap Grid Desktop: 32px
|
||||
|
||||
8. Responsivitas
|
||||
Desktop
|
||||
|
||||
3 kolom utama
|
||||
|
||||
Statistik 3 sejajar
|
||||
|
||||
Tablet
|
||||
|
||||
2 kolom
|
||||
|
||||
Statistik 2 + 1
|
||||
|
||||
Mobile
|
||||
|
||||
1 kolom
|
||||
|
||||
Statistik stacked vertical
|
||||
|
||||
Chat full width
|
||||
|
||||
9. State & Interactivity Requirements
|
||||
|
||||
Harus tersedia:
|
||||
|
||||
Hover state
|
||||
|
||||
Active state
|
||||
|
||||
Focus state (accessibility)
|
||||
|
||||
Disabled state
|
||||
|
||||
Loading state (chat)
|
||||
|
||||
Keyboard support:
|
||||
|
||||
Tab navigable
|
||||
|
||||
Enter kirim pesan
|
||||
|
||||
Esc tutup modal (jika ada)
|
||||
|
||||
10. Accessibility
|
||||
|
||||
Minimum contrast ratio 4.5:1
|
||||
|
||||
Focus ring visible
|
||||
|
||||
Button min-height 40px
|
||||
|
||||
Click area minimal 44x44px
|
||||
|
||||
11. Animasi
|
||||
|
||||
Durasi standar: 200ms – 300ms
|
||||
Easing: ease-in-out
|
||||
|
||||
Digunakan untuk:
|
||||
|
||||
Hover card
|
||||
|
||||
Accordion FAQ
|
||||
|
||||
Chat message appear
|
||||
|
||||
Button press
|
||||
|
||||
12. Toggle Dark / Light Mode
|
||||
|
||||
Harus tersedia:
|
||||
|
||||
Theme switcher
|
||||
|
||||
Persist ke localStorage
|
||||
|
||||
Default mengikuti system preference
|
||||
|
||||
13. Data Dinamis
|
||||
|
||||
Data yang harus bisa dinamis:
|
||||
|
||||
Jumlah artikel
|
||||
|
||||
Jumlah video
|
||||
|
||||
Status support 24/7
|
||||
|
||||
Chat message list
|
||||
|
||||
FAQ content
|
||||
|
||||
Dokumentasi link
|
||||
|
||||
14. Non-Functional Requirements
|
||||
|
||||
Clean modular component
|
||||
|
||||
Reusable Card component
|
||||
|
||||
Maintainable theme config
|
||||
|
||||
Dark & Light share same structure
|
||||
|
||||
15. Kesimpulan
|
||||
|
||||
Halaman ini menggunakan:
|
||||
|
||||
Card-based layout
|
||||
|
||||
Grid responsive
|
||||
|
||||
Dual theme (Light & Dark)
|
||||
|
||||
High clarity & readability
|
||||
|
||||
Modern SaaS style
|
||||
|
||||
Virtual assistant as engagement point
|
||||
|
||||
Implementasi wajib mengikuti spesifikasi ini agar:
|
||||
|
||||
Konsistensi visual terjaga
|
||||
|
||||
User experience optimal
|
||||
|
||||
Maintainability tinggi
|
||||
|
||||
Skalabilitas mudah
|
||||
246
src/components/help-page.tsx
Normal file
246
src/components/help-page.tsx
Normal file
@@ -0,0 +1,246 @@
|
||||
import { Container, Grid, Title, Text, SimpleGrid, Box, Accordion, Stack } from '@mantine/core';
|
||||
import { HelpCard } from '@/components/ui/help-card';
|
||||
import { IconBook, IconVideo, IconHelpCircle, IconMessage, IconFileText, IconHeadphones } from '@tabler/icons-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
const HelpPage = () => {
|
||||
// Sample data for sections
|
||||
const guideItems = [
|
||||
{ title: 'Cara Login', description: 'Langkah-langkah untuk login ke dashboard' },
|
||||
{ title: 'Navigasi Dashboard', description: 'Penjelasan tentang tata letak dan navigasi' },
|
||||
{ title: 'Fitur Dasar', description: 'Panduan penggunaan fitur-fitur utama' },
|
||||
{ title: 'Tips & Trik', description: 'Tips untuk meningkatkan produktivitas' },
|
||||
];
|
||||
|
||||
const videoItems = [
|
||||
{ title: 'Dashboard Overview', duration: '5:23' },
|
||||
{ title: 'Analisis Data', duration: '8:45' },
|
||||
{ title: 'Membuat Laporan', duration: '6:12' },
|
||||
{ title: 'Export Data', duration: '4:30' },
|
||||
];
|
||||
|
||||
const faqItems = [
|
||||
{ question: 'Bagaimana cara reset password?', answer: 'Anda dapat mereset password melalui halaman login dengan klik "Lupa Password"' },
|
||||
{ question: 'Apakah saya bisa mengakses data offline?', answer: 'Saat ini aplikasi hanya dapat diakses secara online' },
|
||||
{ question: 'Berapa lama waktu respon support?', answer: 'Tim support kami biasanya merespon dalam waktu kurang dari 24 jam' },
|
||||
{ question: 'Bagaimana cara menambahkan pengguna baru?', answer: 'Fitur penambahan pengguna dapat ditemukan di menu Pengaturan > Manajemen Pengguna' },
|
||||
];
|
||||
|
||||
const documentationItems = [
|
||||
{ title: 'API Reference', description: 'Dokumentasi lengkap untuk integrasi API' },
|
||||
{ title: 'Integrasi Sistem', description: 'Cara mengintegrasikan dengan sistem eksternal' },
|
||||
{ title: 'Format Data', description: 'Spesifikasi format data yang didukung' },
|
||||
{ title: 'Best Practices', description: 'Praktik terbaik dalam penggunaan platform' },
|
||||
];
|
||||
|
||||
const stats = [
|
||||
{ value: '150+', label: 'Artikel Panduan' },
|
||||
{ value: '50+', label: 'Video Tutorial' },
|
||||
{ value: '24/7', label: 'Support Aktif' },
|
||||
];
|
||||
|
||||
// State for chat functionality
|
||||
const [messages, setMessages] = useState([
|
||||
{ id: 1, text: 'Halo! Saya Jenna, asisten virtual Anda. Bagaimana saya bisa membantu hari ini?', sender: 'jenna' }
|
||||
]);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleSendMessage = () => {
|
||||
if (inputValue.trim() === '') return;
|
||||
|
||||
// Add user message
|
||||
const newUserMessage = {
|
||||
id: messages.length + 1,
|
||||
text: inputValue,
|
||||
sender: 'user'
|
||||
};
|
||||
|
||||
setMessages(prev => [...prev, newUserMessage]);
|
||||
setInputValue('');
|
||||
setIsLoading(true);
|
||||
|
||||
// Simulate Jenna's response after delay
|
||||
setTimeout(() => {
|
||||
const jennaResponse = {
|
||||
id: messages.length + 2,
|
||||
text: 'Terima kasih atas pertanyaan Anda. Saat ini saya adalah versi awal dari asisten virtual. Tim kami sedang mengembangkan kemampuan saya lebih lanjut.',
|
||||
sender: 'jenna'
|
||||
};
|
||||
setMessages(prev => [...prev, jennaResponse]);
|
||||
setIsLoading(false);
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
const handleKeyPress = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
handleSendMessage();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Container size="lg" py="xl">
|
||||
<Title order={1} mb="xl" ta="center">Pusat Bantuan</Title>
|
||||
<Text size="lg" color="dimmed" ta="center" mb="xl">
|
||||
Temukan jawaban untuk pertanyaan Anda atau hubungi tim support kami
|
||||
</Text>
|
||||
|
||||
{/* Statistics Section */}
|
||||
<SimpleGrid cols={3} spacing="lg" mb="xl">
|
||||
{stats.map((stat, index) => (
|
||||
<HelpCard key={index} p="lg" style={{ textAlign: 'center' }} h="100%">
|
||||
<Text size="xl" fw={700} style={{ fontSize: '32px' }}>{stat.value}</Text>
|
||||
<Text size="sm" color="dimmed">{stat.label}</Text>
|
||||
</HelpCard>
|
||||
))}
|
||||
</SimpleGrid>
|
||||
|
||||
<Stack gap="lg">
|
||||
<Box>
|
||||
<Grid gutter="lg" justify="center">
|
||||
{/* Panduan Memulai */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconBook size={24} />} title="Panduan Memulai" h="100%">
|
||||
<Box>
|
||||
{guideItems.map((item, index) => (
|
||||
<Box key={index} py="sm" style={{ borderBottom: '1px solid #eee', cursor: 'pointer' }} onClick={() => alert(`Navigasi ke ${item.title}`)}>
|
||||
<Text fw={500}>{item.title}</Text>
|
||||
<Text size="sm" color="dimmed">{item.description}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
|
||||
{/* Video Tutorial */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconVideo size={24} />} title="Video Tutorial" h="100%">
|
||||
<Box>
|
||||
{videoItems.map((item, index) => (
|
||||
<Box key={index} py="sm" style={{ borderBottom: '1px solid #eee', cursor: 'pointer' }} onClick={() => alert(`Buka video: ${item.title}`)}>
|
||||
<Text fw={500}>{item.title}</Text>
|
||||
<Text size="sm" color="dimmed">{item.duration}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
|
||||
{/* FAQ */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconHelpCircle size={24} />} title="FAQ" h="100%">
|
||||
<Accordion variant="separated">
|
||||
{faqItems.map((item, index) => (
|
||||
<Accordion.Item key={index} value={`faq-${index}`}>
|
||||
<Accordion.Control>{item.question}</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
<Text size="sm">{item.answer}</Text>
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
))}
|
||||
</Accordion>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Grid>
|
||||
{/* Hubungi Support */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconHeadphones size={24} />} title="Hubungi Support" h="100%">
|
||||
<Box>
|
||||
<Text fw={500}>Email</Text>
|
||||
<Text size="sm" color="dimmed" mb="md"><a href="mailto:support@example.com">support@example.com</a></Text>
|
||||
|
||||
<Text fw={500}>WhatsApp</Text>
|
||||
<Text size="sm" color="dimmed" mb="md"><a href="https://wa.me/1234567890">+62 123 456 7890</a></Text>
|
||||
|
||||
<Text fw={500}>Jam Kerja</Text>
|
||||
<Text size="sm" color="dimmed">Senin - Jumat, 09:00 - 17:00 WIB</Text>
|
||||
|
||||
<Text fw={500} mt="md">Waktu Respon</Text>
|
||||
<Text size="sm" color="dimmed">Rata-rata 2-4 jam kerja</Text>
|
||||
</Box>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
|
||||
{/* Dokumentasi */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconFileText size={24} />} title="Dokumentasi" h="100%">
|
||||
<Box>
|
||||
{documentationItems.map((item, index) => (
|
||||
<Box key={index} py="sm" style={{ borderBottom: '1px solid #eee', cursor: 'pointer' }} onClick={() => alert(`Navigasi ke dokumentasi: ${item.title}`)}>
|
||||
<Text fw={500}>{item.title}</Text>
|
||||
<Text size="sm" color="dimmed">{item.description}</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
|
||||
{/* Jenna - Virtual Assistant */}
|
||||
<Grid.Col span={{ base: 12, sm: 6, md: 4 }}>
|
||||
<HelpCard icon={<IconMessage size={24} />} title="Jenna - Virtual Assistant" h="100%">
|
||||
<Box style={{ height: '300px', display: 'flex', flexDirection: 'column' }}>
|
||||
<Box style={{ flex: 1, overflowY: 'auto', marginBottom: '12px', maxHeight: '200px' }}>
|
||||
{messages.map((msg) => (
|
||||
<Box
|
||||
key={msg.id}
|
||||
style={{
|
||||
alignSelf: msg.sender === 'user' ? 'flex-end' : 'flex-start',
|
||||
backgroundColor: msg.sender === 'user' ? '#3B82F6' : '#F3F4F6',
|
||||
color: msg.sender === 'user' ? 'white' : 'black',
|
||||
padding: '8px 12px',
|
||||
borderRadius: '8px',
|
||||
marginBottom: '8px',
|
||||
maxWidth: '80%'
|
||||
}}
|
||||
>
|
||||
{msg.text}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
<Box style={{ display: 'flex', gap: '8px' }}>
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
placeholder="Ketik pesan Anda..."
|
||||
style={{
|
||||
flex: 1,
|
||||
padding: '8px 12px',
|
||||
borderRadius: '20px',
|
||||
border: '1px solid #ccc',
|
||||
}}
|
||||
disabled={isLoading}
|
||||
/>
|
||||
<button
|
||||
onClick={handleSendMessage}
|
||||
disabled={isLoading || inputValue.trim() === ''}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
borderRadius: '20px',
|
||||
backgroundColor: '#3B82F6',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
Kirim
|
||||
</button>
|
||||
</Box>
|
||||
</Box>
|
||||
</HelpCard>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
export default HelpPage;
|
||||
90
src/components/ui/help-card.tsx
Normal file
90
src/components/ui/help-card.tsx
Normal file
@@ -0,0 +1,90 @@
|
||||
import { Card, useMantineTheme, useComputedColorScheme } from '@mantine/core';
|
||||
import type { CardProps } from '@mantine/core';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
interface HelpCardProps extends CardProps {
|
||||
children: ReactNode;
|
||||
icon?: ReactNode;
|
||||
title?: string;
|
||||
minHeight?: string | number; // Allow specifying a minimum height
|
||||
}
|
||||
|
||||
export const HelpCard = ({
|
||||
children,
|
||||
icon,
|
||||
title,
|
||||
minHeight = 'auto', // Default to auto, but allow override
|
||||
...props
|
||||
}: HelpCardProps) => {
|
||||
const theme = useMantineTheme();
|
||||
const colorScheme = useComputedColorScheme('light');
|
||||
const isDark = colorScheme === 'dark';
|
||||
|
||||
return (
|
||||
<Card
|
||||
shadow="sm"
|
||||
padding="xl"
|
||||
radius="md"
|
||||
withBorder
|
||||
style={{
|
||||
backgroundColor: isDark ? theme.colors.dark[7] : theme.white,
|
||||
borderRadius: '16px',
|
||||
transition: 'transform 0.2s ease, box-shadow 0.2s ease',
|
||||
border: `1px solid ${
|
||||
isDark ? theme.colors.dark[4] : theme.colors.gray[3]
|
||||
}`,
|
||||
minHeight, // Apply the minimum height
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{(icon || title) && (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '12px',
|
||||
marginBottom: '16px',
|
||||
}}
|
||||
>
|
||||
{icon && (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: isDark
|
||||
? theme.colors.blue[8]
|
||||
: theme.colors.blue[0],
|
||||
borderRadius: '8px',
|
||||
padding: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
{icon}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{title && (
|
||||
<h3
|
||||
style={{
|
||||
margin: 0,
|
||||
fontSize: '16px',
|
||||
fontWeight: 600,
|
||||
color: isDark
|
||||
? theme.colors.dark[0]
|
||||
: theme.colors.dark[9],
|
||||
}}
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div style={{ flex: 1 }}>
|
||||
{children}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
@@ -28,6 +28,7 @@ import { Route as DashboardKeamananRouteImport } from './routes/dashboard/keaman
|
||||
import { Route as DashboardJennaAnalyticRouteImport } from './routes/dashboard/jenna-analytic'
|
||||
import { Route as DashboardDemografiPekerjaanRouteImport } from './routes/dashboard/demografi-pekerjaan'
|
||||
import { Route as DashboardBumdesRouteImport } from './routes/dashboard/bumdes'
|
||||
import { Route as DashboardBantuanRouteImport } from './routes/dashboard/bantuan'
|
||||
import { Route as AdminUsersRouteImport } from './routes/admin/users'
|
||||
import { Route as AdminSettingsRouteImport } from './routes/admin/settings'
|
||||
import { Route as AdminApikeyRouteImport } from './routes/admin/apikey'
|
||||
@@ -130,6 +131,11 @@ const DashboardBumdesRoute = DashboardBumdesRouteImport.update({
|
||||
path: '/bumdes',
|
||||
getParentRoute: () => DashboardRouteRoute,
|
||||
} as any)
|
||||
const DashboardBantuanRoute = DashboardBantuanRouteImport.update({
|
||||
id: '/bantuan',
|
||||
path: '/bantuan',
|
||||
getParentRoute: () => DashboardRouteRoute,
|
||||
} as any)
|
||||
const AdminUsersRoute = AdminUsersRouteImport.update({
|
||||
id: '/users',
|
||||
path: '/users',
|
||||
@@ -155,6 +161,7 @@ export interface FileRoutesByFullPath {
|
||||
'/admin/apikey': typeof AdminApikeyRoute
|
||||
'/admin/settings': typeof AdminSettingsRoute
|
||||
'/admin/users': typeof AdminUsersRoute
|
||||
'/dashboard/bantuan': typeof DashboardBantuanRoute
|
||||
'/dashboard/bumdes': typeof DashboardBumdesRoute
|
||||
'/dashboard/demografi-pekerjaan': typeof DashboardDemografiPekerjaanRoute
|
||||
'/dashboard/jenna-analytic': typeof DashboardJennaAnalyticRoute
|
||||
@@ -177,6 +184,7 @@ export interface FileRoutesByTo {
|
||||
'/admin/apikey': typeof AdminApikeyRoute
|
||||
'/admin/settings': typeof AdminSettingsRoute
|
||||
'/admin/users': typeof AdminUsersRoute
|
||||
'/dashboard/bantuan': typeof DashboardBantuanRoute
|
||||
'/dashboard/bumdes': typeof DashboardBumdesRoute
|
||||
'/dashboard/demografi-pekerjaan': typeof DashboardDemografiPekerjaanRoute
|
||||
'/dashboard/jenna-analytic': typeof DashboardJennaAnalyticRoute
|
||||
@@ -202,6 +210,7 @@ export interface FileRoutesById {
|
||||
'/admin/apikey': typeof AdminApikeyRoute
|
||||
'/admin/settings': typeof AdminSettingsRoute
|
||||
'/admin/users': typeof AdminUsersRoute
|
||||
'/dashboard/bantuan': typeof DashboardBantuanRoute
|
||||
'/dashboard/bumdes': typeof DashboardBumdesRoute
|
||||
'/dashboard/demografi-pekerjaan': typeof DashboardDemografiPekerjaanRoute
|
||||
'/dashboard/jenna-analytic': typeof DashboardJennaAnalyticRoute
|
||||
@@ -228,6 +237,7 @@ export interface FileRouteTypes {
|
||||
| '/admin/apikey'
|
||||
| '/admin/settings'
|
||||
| '/admin/users'
|
||||
| '/dashboard/bantuan'
|
||||
| '/dashboard/bumdes'
|
||||
| '/dashboard/demografi-pekerjaan'
|
||||
| '/dashboard/jenna-analytic'
|
||||
@@ -250,6 +260,7 @@ export interface FileRouteTypes {
|
||||
| '/admin/apikey'
|
||||
| '/admin/settings'
|
||||
| '/admin/users'
|
||||
| '/dashboard/bantuan'
|
||||
| '/dashboard/bumdes'
|
||||
| '/dashboard/demografi-pekerjaan'
|
||||
| '/dashboard/jenna-analytic'
|
||||
@@ -274,6 +285,7 @@ export interface FileRouteTypes {
|
||||
| '/admin/apikey'
|
||||
| '/admin/settings'
|
||||
| '/admin/users'
|
||||
| '/dashboard/bantuan'
|
||||
| '/dashboard/bumdes'
|
||||
| '/dashboard/demografi-pekerjaan'
|
||||
| '/dashboard/jenna-analytic'
|
||||
@@ -437,6 +449,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof DashboardBumdesRouteImport
|
||||
parentRoute: typeof DashboardRouteRoute
|
||||
}
|
||||
'/dashboard/bantuan': {
|
||||
id: '/dashboard/bantuan'
|
||||
path: '/bantuan'
|
||||
fullPath: '/dashboard/bantuan'
|
||||
preLoaderRoute: typeof DashboardBantuanRouteImport
|
||||
parentRoute: typeof DashboardRouteRoute
|
||||
}
|
||||
'/admin/users': {
|
||||
id: '/admin/users'
|
||||
path: '/users'
|
||||
@@ -480,6 +499,7 @@ const AdminRouteRouteWithChildren = AdminRouteRoute._addFileChildren(
|
||||
)
|
||||
|
||||
interface DashboardRouteRouteChildren {
|
||||
DashboardBantuanRoute: typeof DashboardBantuanRoute
|
||||
DashboardBumdesRoute: typeof DashboardBumdesRoute
|
||||
DashboardDemografiPekerjaanRoute: typeof DashboardDemografiPekerjaanRoute
|
||||
DashboardJennaAnalyticRoute: typeof DashboardJennaAnalyticRoute
|
||||
@@ -492,6 +512,7 @@ interface DashboardRouteRouteChildren {
|
||||
}
|
||||
|
||||
const DashboardRouteRouteChildren: DashboardRouteRouteChildren = {
|
||||
DashboardBantuanRoute: DashboardBantuanRoute,
|
||||
DashboardBumdesRoute: DashboardBumdesRoute,
|
||||
DashboardDemografiPekerjaanRoute: DashboardDemografiPekerjaanRoute,
|
||||
DashboardJennaAnalyticRoute: DashboardJennaAnalyticRoute,
|
||||
|
||||
7
src/routes/dashboard/bantuan.ts
Normal file
7
src/routes/dashboard/bantuan.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import HelpPage from '@/components/help-page'
|
||||
|
||||
export const Route = createFileRoute('/dashboard/bantuan')({
|
||||
component: HelpPage,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user