210 lines
6.5 KiB
Vue
210 lines
6.5 KiB
Vue
<template>
|
|
<div class="fixed inset-0 flex items-center justify-center bg-black/65 z-50">
|
|
<div class="bg-white rounded-lg p-6 w-96 shadow-lg">
|
|
<h2 class="text-lg font-bold mb-4">Edit Akun</h2>
|
|
|
|
<form @submit.prevent="updateAkun" class="space-y-3">
|
|
<!-- Nama -->
|
|
<div>
|
|
<label for="nama" class="block text-sm font-medium">Nama</label>
|
|
<InputField
|
|
v-model="form.nama"
|
|
id="nama"
|
|
type="text"
|
|
:required="true"
|
|
@input="clearError('nama')"
|
|
/>
|
|
<p v-if="errors.nama" class="text-red-500 text-sm">{{ errors.nama }}</p>
|
|
</div>
|
|
|
|
<!-- Password -->
|
|
<div>
|
|
<label for="password" class="block text-sm font-medium">Password</label>
|
|
<InputPassword
|
|
v-model="form.password"
|
|
id="password"
|
|
type="password"
|
|
:required="false"
|
|
@input="clearError('password')"
|
|
/>
|
|
<p class="text-sm">Kosongkan jika tidak ingin ubah password</p>
|
|
<p v-if="errors.password" class="text-red-500 text-sm">{{ errors.password }}</p>
|
|
</div>
|
|
|
|
<!-- Confirm Password -->
|
|
<div v-if="form.password">
|
|
<label for="confirmPassword" class="block text-sm font-medium">Konfirmasi Password</label>
|
|
<InputPassword
|
|
v-model="form.confirmPassword"
|
|
id="confirmPassword"
|
|
type="password"
|
|
:required="false"
|
|
@input="clearError('confirmPassword')"
|
|
/>
|
|
<p v-if="errors.confirmPassword" class="text-red-500 text-sm">
|
|
{{ errors.confirmPassword }}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Role -->
|
|
<div>
|
|
<label for="role" class="block text-sm font-medium">Peran</label>
|
|
|
|
<!-- 🔒 Kalau akun sendiri tampil readonly -->
|
|
<template v-if="isEditingSelf">
|
|
<p class="mt-1 px-3 py-2 border rounded bg-gray-100 text-gray-700">
|
|
{{ form.role === 'owner' ? 'Owner' : 'Kasir' }}
|
|
</p>
|
|
</template>
|
|
|
|
<!-- 🔓 Kalau akun lain bisa diubah -->
|
|
<template v-else>
|
|
<InputSelect
|
|
v-model="form.role"
|
|
:options="[
|
|
{ value: 'owner', label: 'Owner' },
|
|
{ value: 'kasir', label: 'Kasir' }
|
|
]"
|
|
placeholder="-- Pilih Peran --"
|
|
@change="clearError('role')"
|
|
/>
|
|
<p v-if="errors.role" class="text-red-500 text-sm">{{ errors.role }}</p>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Tombol -->
|
|
<div class="flex justify-end gap-2 mt-4">
|
|
<button
|
|
type="button"
|
|
@click="$emit('close')"
|
|
class="bg-gray-300 hover:bg-gray-400 px-4 py-2 rounded"
|
|
>
|
|
Batal
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded disabled:opacity-50 disabled:cursor-not-allowed"
|
|
:disabled="!isFormValid"
|
|
>
|
|
Ubah
|
|
</button>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Error global -->
|
|
<p v-if="errorMessage" class="text-red-500 text-sm mt-3">
|
|
{{ errorMessage }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, computed, onMounted } from "vue";
|
|
import axios from "axios";
|
|
import InputField from "@/components/InputField.vue";
|
|
import InputSelect from "@/components/InputSelect.vue";
|
|
import InputPassword from "./InputPassword.vue";
|
|
|
|
const props = defineProps({
|
|
akun: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits(["refresh", "close"]);
|
|
|
|
const form = ref({
|
|
nama: props.akun?.nama || "",
|
|
password: "",
|
|
confirmPassword: "",
|
|
role: props.akun?.role || "",
|
|
});
|
|
|
|
const errors = ref({ nama: "", password: "", confirmPassword: "", role: "" });
|
|
const errorMessage = ref("");
|
|
const loggedInId = ref(localStorage.getItem("userId")); // 🔥 ambil dari localStorage
|
|
|
|
const isFormValid = computed(() => {
|
|
if (form.value.password && form.value.password !== form.value.confirmPassword) {
|
|
return false;
|
|
}
|
|
return (
|
|
form.value.nama.trim() &&
|
|
form.value.role &&
|
|
!errors.value.nama &&
|
|
!errors.value.password &&
|
|
!errors.value.confirmPassword &&
|
|
!errors.value.role
|
|
);
|
|
});
|
|
|
|
// 🔥 ini cek apakah akun yang diedit adalah akun sendiri
|
|
const isEditingSelf = computed(() => {
|
|
return String(props.akun.id) === String(loggedInId.value);
|
|
});
|
|
|
|
const clearError = (field) => {
|
|
errors.value[field] = "";
|
|
errorMessage.value = "";
|
|
};
|
|
|
|
const validateForm = () => {
|
|
let valid = true;
|
|
errors.value = { nama: "", password: "", confirmPassword: "", role: "" };
|
|
|
|
if (!form.value.nama) {
|
|
errors.value.nama = "Nama wajib diisi";
|
|
valid = false;
|
|
}
|
|
if (form.value.password && form.value.password.length < 6) {
|
|
errors.value.password = "Password minimal 6 karakter";
|
|
valid = false;
|
|
}
|
|
if (form.value.password && form.value.password !== form.value.confirmPassword) {
|
|
errors.value.confirmPassword = "Konfirmasi password tidak cocok";
|
|
valid = false;
|
|
}
|
|
if (!form.value.role) {
|
|
errors.value.role = "Role wajib dipilih";
|
|
valid = false;
|
|
}
|
|
|
|
return valid;
|
|
};
|
|
|
|
const updateAkun = async () => {
|
|
if (!validateForm()) return;
|
|
|
|
try {
|
|
const payload = { ...form.value };
|
|
if (!payload.password) delete payload.password;
|
|
delete payload.confirmPassword;
|
|
|
|
await axios.put(`/api/user/${props.akun.id}`, payload, {
|
|
headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
|
|
});
|
|
|
|
emit("refresh");
|
|
emit("close");
|
|
} catch (err) {
|
|
if (err.response?.status === 422 && err.response.data.errors) {
|
|
const backendErrors = err.response.data.errors;
|
|
Object.keys(backendErrors).forEach((key) => {
|
|
errors.value[key] = backendErrors[key][0];
|
|
});
|
|
} else {
|
|
errorMessage.value = err.response?.data?.message || "Gagal update akun.";
|
|
}
|
|
console.error("Gagal update akun:", err);
|
|
}
|
|
};
|
|
|
|
onMounted(() => {
|
|
console.log("Akun.id:", props.akun.id);
|
|
console.log("LoggedInId:", loggedInId.value);
|
|
console.log("isEditingSelf:", isEditingSelf.value);
|
|
});
|
|
</script>
|
|
|