287 lines
10 KiB
Vue
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';
|
|
|
|
definePageMeta({
|
|
middleware: 'auth'
|
|
});
|
|
|
|
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';
|
|
}
|
|
}
|
|
});
|
|
</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> |