Files
antrean-operasi/pages/setting/user/form.vue
T
2026-02-02 08:13:15 +07:00

287 lines
10 KiB
Vue

<script setup lang="ts">
import BaseBreadcrumb from '@/components/shared/BaseBreadcrumb.vue';
import hakAksesData from '~/data/mock/hakAkses.json';
import type { PageMode } from '~/types/common';
const route = useRoute();
const router = useRouter();
// Detect mode from route query
const mode = computed<PageMode>(() => {
const modeParam = route.query.mode as string;
if (modeParam === 'edit') return 'edit';
if (modeParam === 'view') return 'view';
return 'create';
});
// Computed readonly state
const isReadonly = computed(() => mode.value === 'view');
// Dynamic page title based on mode
const pageTitle = computed(() => {
switch (mode.value) {
case 'edit':
return 'Edit User';
case 'view':
return 'Detail User';
default:
return 'Tambah User';
}
});
// Dynamic breadcrumbs based on mode
const breadcrumbText = computed(() => {
switch (mode.value) {
case 'edit':
return 'Edit';
case 'view':
return 'Detail';
default:
return 'Tambah';
}
});
const page = ref({ title: pageTitle });
const breadcrumbs = computed(() => [
{
text: 'User',
disabled: false,
href: '/setting/user'
},
{
text: breadcrumbText.value,
disabled: true,
href: '#'
}
]);
// Form data
const form = ref();
const valid = ref(true);
const namaUser = ref('');
const username = ref('');
const email = ref('');
const hakAkses = ref<number | null>(null);
const status = ref('aktif');
// Rules
const rules = {
required: (value: any) => !!value || 'Field ini wajib diisi',
email: (value: string) => {
const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return pattern.test(value) || 'Format email tidak valid';
}
};
// Hak Akses options
const hakAksesList = ref(hakAksesData);
const hakAksesOptions = computed(() => {
return hakAksesList.value.map(h => ({
title: h.namaHakAkses,
value: h.id
}));
});
const handleSimpan = async () => {
const { valid } = await form.value.validate();
if (valid) {
console.log({
namaUser: namaUser.value,
username: username.value,
email: email.value,
hakAkses: hakAkses.value,
status: status.value
});
alert('Data berhasil disimpan!');
router.push('/setting/user');
}
};
const handleReset = () => {
if (confirm('Apakah Anda yakin ingin mereset form?')) {
form.value.reset();
namaUser.value = '';
username.value = '';
email.value = '';
hakAkses.value = null;
status.value = 'aktif';
}
};
const handleKembali = () => {
router.push('/setting/user');
};
// Load data if edit or view mode
onMounted(() => {
if (mode.value !== 'create') {
const id = route.query.id;
// TODO: Load data based on id
// For now, just mock data
if (id === '1') {
namaUser.value = 'Dr. John Doe';
username.value = 'john.doe';
email.value = 'john.doe@hospital.com';
hakAkses.value = 3; // Dokter
status.value = 'aktif';
} else if (id === '2') {
namaUser.value = 'Admin Sistem';
username.value = 'admin';
email.value = 'admin@hospital.com';
hakAkses.value = 1; // Super Admin
status.value = 'aktif';
}
}
});
definePageMeta({
middleware: 'auth'
});
</script>
<template>
<v-form ref="form" v-model="valid" lazy-validation>
<v-row>
<v-col cols="12">
<BaseBreadcrumb :title="pageTitle" :button-back="true" :breadcrumbs="breadcrumbs"></BaseBreadcrumb>
</v-col>
<!-- Form Card -->
<v-col cols="12">
<v-card elevation="10">
<v-card-item>
<h5 class="text-h5 font-weight-bold">Informasi User</h5>
</v-card-item>
<v-divider></v-divider>
<v-card-text>
<v-row>
<!-- Nama User -->
<v-col cols="12" md="6">
<v-label class="mb-2 font-weight-medium">Nama User <span class="text-error">*</span></v-label>
<v-text-field
v-model="namaUser"
placeholder="Masukan nama lengkap user"
variant="outlined"
density="comfortable"
:rules="[rules.required]"
hide-details="auto"
:readonly="isReadonly"
:bg-color="isReadonly ? 'grey-lighten-3' : undefined"
></v-text-field>
</v-col>
<!-- Username -->
<v-col cols="12" md="6">
<v-label class="mb-2 font-weight-medium">Username <span class="text-error">*</span></v-label>
<v-text-field
v-model="username"
placeholder="Masukan username"
variant="outlined"
density="comfortable"
:rules="[rules.required]"
hide-details="auto"
:readonly="isReadonly"
:bg-color="isReadonly ? 'grey-lighten-3' : undefined"
></v-text-field>
</v-col>
<!-- Email -->
<v-col cols="12" md="6">
<v-label class="mb-2 font-weight-medium">Email <span class="text-error">*</span></v-label>
<v-text-field
v-model="email"
placeholder="contoh@email.com"
variant="outlined"
density="comfortable"
type="email"
:rules="[rules.required, rules.email]"
hide-details="auto"
:readonly="isReadonly"
:bg-color="isReadonly ? 'grey-lighten-3' : undefined"
></v-text-field>
</v-col>
<!-- Hak Akses -->
<v-col cols="12" md="6">
<v-label class="mb-2 font-weight-medium">Hak Akses <span class="text-error">*</span></v-label>
<v-autocomplete
v-model="hakAkses"
:items="hakAksesOptions"
placeholder="Pilih hak akses"
variant="outlined"
density="comfortable"
:rules="[rules.required]"
hide-details="auto"
:readonly="isReadonly"
:disabled="isReadonly"
:bg-color="isReadonly ? 'grey-lighten-3' : undefined"
></v-autocomplete>
</v-col>
<!-- Status -->
<v-col cols="12" md="6">
<v-label class="mb-2 font-weight-medium">Status <span class="text-error">*</span></v-label>
<v-switch
v-model="status"
true-value="aktif"
false-value="tidak aktif"
color="success"
hide-details="auto"
:readonly="isReadonly"
:disabled="isReadonly"
inset
>
<template #label>
<span :class="status === 'aktif' ? 'text-success' : 'text-error'">
{{ status === 'aktif' ? 'Aktif' : 'Tidak Aktif' }}
</span>
</template>
</v-switch>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-col>
<!-- Action Buttons -->
<v-col cols="12">
<v-card elevation="10">
<v-card-text>
<div class="d-flex justify-end ga-3">
<v-btn
color="default"
size="large"
variant="outlined"
prepend-icon="mdi-arrow-left"
@click="handleKembali"
>
Kembali
</v-btn>
<v-btn
v-if="!isReadonly"
color="error"
size="large"
variant="outlined"
prepend-icon="mdi-reload"
@click="handleReset"
>
Reset
</v-btn>
<v-btn
v-if="!isReadonly"
color="primary"
size="large"
prepend-icon="mdi-content-save"
@click="handleSimpan"
>
Simpan
</v-btn>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-form>
</template>