Files
2026-03-17 09:22:24 +07:00

283 lines
12 KiB
Vue

<script setup lang="ts">
import UiParentCard from '@/components/shared/UiParentCard.vue';
import UiChildCard from '@/components/shared/UiChildCard.vue';
const components = [
{
name: 'UiParentCard',
file: 'UiParentCard.vue',
category: 'Card',
description: 'Card elevated (elevation=10) sebagai wrapper utama halaman. Mendukung slot action di header.',
props: ['title'],
slots: ['default', 'action'],
link: '/shared-components/UiParentCard',
},
{
name: 'UiChildCard',
file: 'UiChildCard.vue',
category: 'Card',
description: 'Card outlined untuk memisahkan bagian-bagian konten di dalam UiParentCard.',
props: ['title'],
slots: ['default'],
link: '/shared-components/UiParentCard',
},
{
name: 'WidgetCard',
file: 'WidgetCard.vue',
category: 'Widget',
description: 'Card outlined ringan untuk widget/statistik. Margin bawah otomatis (mb-6).',
props: ['title'],
slots: ['default'],
link: '/shared-components/WidgetCards',
},
{
name: 'WidgetCardv2',
file: 'WidgetCardv2.vue',
category: 'Widget',
description: 'Widget card dengan footer yang bisa disembunyikan menggunakan prop hideaction.',
props: ['title', 'hideaction'],
slots: ['default', 'footer'],
link: '/shared-components/WidgetCards',
},
{
name: 'CardHeaderFooter',
file: 'CardHeaderFooter.vue',
category: 'Card',
description: 'Card dengan header, konten, dan footer yang dipisahkan garis pembatas.',
props: ['title'],
slots: ['default', 'footer'],
link: '/shared-components/CardComponents',
},
{
name: 'UiTableCard',
file: 'UiTableCard.vue',
category: 'Card',
description: 'Card wrapper untuk tabel data. Slot default langsung menerima v-data-table.',
props: ['title'],
slots: ['default'],
link: '/shared-components/CardComponents',
},
{
name: 'UiParentCardLogo',
file: 'UiParentCardLogo.vue',
category: 'Card',
description: 'Card elevated dengan Logo aplikasi di header. Ideal untuk halaman auth.',
props: [],
slots: ['default', 'action'],
link: '/shared-components/CardComponents',
},
{
name: 'BaseBreadcrumb',
file: 'BaseBreadcrumb.vue',
category: 'Navigation',
description: 'Header halaman dengan judul di kiri dan breadcrumb chip-style di kanan.',
props: ['title', 'breadcrumbs'],
slots: [],
link: '/shared-components/BaseBreadcrumb',
},
{
name: 'UiTextfieldPrimary',
file: 'UiTextfieldPrimary.vue',
category: 'Form',
description: 'Wrapper v-text-field dengan color="primary" otomatis.',
props: ['v-model', '...all v-text-field props'],
slots: ['default'],
link: '/shared-components/UiTextfieldPrimary',
},
{
name: 'AppBaseCard',
file: 'AppBaseCard.vue',
category: 'Layout',
description: 'Layout dua panel (kiri/kanan) responsif. Panel kiri menjadi drawer di mobile.',
props: [],
slots: ['leftpart', 'rightpart', 'mobileLeftContent'],
link: '/shared-components/AppBaseCard',
},
{
name: 'AppEmailCard',
file: 'AppEmailCard.vue',
category: 'Layout',
description: 'Layout tiga panel (compose/list/detail) untuk antarmuka email.',
props: [],
slots: ['mailCompose', 'mailList', 'mailDetail'],
link: '/shared-components/AppBaseCard',
},
];
const categoryColors: Record<string, string> = {
Card: 'primary',
Widget: 'success',
Navigation: 'info',
Form: 'warning',
Layout: 'secondary',
};
const categories = [...new Set(components.map(c => c.category))];
</script>
<template>
<v-row>
<v-col cols="12">
<UiParentCard title="Shared Components — Panduan Penggunaan">
<p class="text-body-1 mb-6">
Direktori <code>components/shared/</code> berisi komponen-komponen yang dapat digunakan
kembali di seluruh aplikasi. Gunakan komponen ini secara konsisten untuk menjaga
tampilan yang seragam.
</p>
<!-- Summary Stats -->
<v-row class="mb-6">
<v-col v-for="category in categories" :key="category" cols="6" md="4" lg="2">
<v-card variant="tonal" :color="categoryColors[category]" class="text-center pa-3">
<div class="text-h5 font-weight-bold">
{{ components.filter(c => c.category === category).length }}
</div>
<div class="text-caption">{{ category }}</div>
</v-card>
</v-col>
<v-col cols="6" md="4" lg="2">
<v-card variant="tonal" color="error" class="text-center pa-3">
<div class="text-h5 font-weight-bold">{{ components.length }}</div>
<div class="text-caption">Total</div>
</v-card>
</v-col>
</v-row>
<!-- Component Cards -->
<v-row>
<v-col
v-for="comp in components"
:key="comp.name"
cols="12"
md="6"
lg="4"
>
<v-card
variant="outlined"
height="100%"
class="d-flex flex-column"
>
<v-card-item>
<template #prepend>
<v-chip
:color="categoryColors[comp.category]"
size="small"
variant="tonal"
class="mr-2"
>
{{ comp.category }}
</v-chip>
</template>
<v-card-title class="text-body-1 font-weight-bold">
{{ comp.name }}
</v-card-title>
<v-card-subtitle class="text-caption">
{{ comp.file }}
</v-card-subtitle>
</v-card-item>
<v-divider />
<v-card-text class="flex-grow-1">
<p class="text-body-2 mb-3">{{ comp.description }}</p>
<!-- Props -->
<div v-if="comp.props.length" class="mb-2">
<span class="text-caption font-weight-bold text-medium-emphasis">PROPS: </span>
<v-chip
v-for="prop in comp.props"
:key="prop"
size="x-small"
color="primary"
variant="tonal"
class="mr-1"
>
{{ prop }}
</v-chip>
</div>
<!-- Slots -->
<div v-if="comp.slots.length">
<span class="text-caption font-weight-bold text-medium-emphasis">SLOTS: </span>
<v-chip
v-for="slot in comp.slots"
:key="slot"
size="x-small"
color="secondary"
variant="tonal"
class="mr-1"
>
#{{ slot }}
</v-chip>
</div>
</v-card-text>
<v-divider />
<v-card-actions>
<v-btn
:to="comp.link"
color="primary"
variant="text"
size="small"
append-icon="mdi-arrow-right"
>
Lihat Tutorial
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
<!-- Quick Start -->
<UiChildCard title="Quick Start — Import Komponen" class="mt-6">
<pre class="bg-grey-lighten-4 pa-4 rounded text-body-2 overflow-auto">{{ quickStartCode }}</pre>
</UiChildCard>
<!-- Best Practice -->
<UiChildCard title="Best Practice" class="mt-4">
<v-list lines="two">
<v-list-item
prepend-icon="mdi-check-circle"
title="Gunakan UiParentCard sebagai wrapper halaman"
subtitle="Setiap halaman sebaiknya dibungkus dengan UiParentCard untuk konsistensi elevation dan border."
/>
<v-list-item
prepend-icon="mdi-check-circle"
title="Gunakan UiChildCard untuk sub-section"
subtitle="Pisahkan setiap bagian konten dalam UiChildCard agar lebih terstruktur."
/>
<v-list-item
prepend-icon="mdi-check-circle"
title="Gunakan BaseBreadcrumb di awal halaman"
subtitle="Tempatkan BaseBreadcrumb sebagai elemen pertama untuk navigasi yang konsisten."
/>
<v-list-item
prepend-icon="mdi-check-circle"
title="Gunakan UiTextfieldPrimary alih-alih v-text-field"
subtitle="Untuk konsistensi warna primary di seluruh form aplikasi."
/>
</v-list>
</UiChildCard>
</UiParentCard>
</v-col>
</v-row>
</template>
<script lang="ts">
export default {
data() {
return {
quickStartCode: `// Import individual sesuai kebutuhan:
import UiParentCard from '@/components/shared/UiParentCard.vue';
import UiChildCard from '@/components/shared/UiChildCard.vue';
import WidgetCard from '@/components/shared/WidgetCard.vue';
import WidgetCardv2 from '@/components/shared/WidgetCardv2.vue';
import CardHeaderFooter from '@/components/shared/CardHeaderFooter.vue';
import UiTableCard from '@/components/shared/UiTableCard.vue';
import UiParentCardLogo from '@/components/shared/UiParentCardLogo.vue';
import BaseBreadcrumb from '@/components/shared/BaseBreadcrumb.vue';
import UiTextfieldPrimary from '@/components/shared/UiTextfieldPrimary.vue';
import AppBaseCard from '@/components/shared/AppBaseCard.vue';
import AppEmailCard from '@/components/shared/AppEmailCard.vue';`,
};
}
};
</script>