283 lines
12 KiB
Vue
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>
|