162 lines
8.6 KiB
Vue
162 lines
8.6 KiB
Vue
<script setup>
|
|
import { Head, useForm, Link, usePage } from '@inertiajs/vue3';
|
|
import { ref } from 'vue';
|
|
import AdminLayout from '@/Layouts/AdminLayout.vue';
|
|
|
|
const page = usePage();
|
|
|
|
const props = defineProps({
|
|
users: Array,
|
|
tenants: Array
|
|
});
|
|
|
|
const isCreating = ref(false);
|
|
const editingUser = ref(null);
|
|
|
|
const form = useForm({
|
|
name: '',
|
|
email: '',
|
|
role: 'admin',
|
|
tenant_id: ''
|
|
});
|
|
|
|
const submit = () => {
|
|
if (editingUser.value) {
|
|
form.put(route('admin.users.update', editingUser.value.id), {
|
|
onSuccess: () => {
|
|
editingUser.value = null;
|
|
form.reset();
|
|
}
|
|
});
|
|
} else {
|
|
form.post(route('admin.users.store'), {
|
|
onSuccess: () => {
|
|
isCreating.value = false;
|
|
form.reset();
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
const editUser = (user) => {
|
|
editingUser.value = user;
|
|
form.name = user.name;
|
|
form.email = user.email;
|
|
form.role = user.role;
|
|
form.tenant_id = user.tenant_id || '';
|
|
isCreating.value = true;
|
|
};
|
|
|
|
const deleteUser = (user) => {
|
|
if (confirm('Êtes-vous sûr de vouloir supprimer cet administrateur ?')) {
|
|
form.delete(route('admin.users.destroy', user.id));
|
|
}
|
|
};
|
|
|
|
const resetPassword = (user) => {
|
|
if (confirm(`Êtes-vous sûr de vouloir réinitialiser le mot de passe de ${user.name} ? Un nouveau mot de passe sera généré aléatoirement.`)) {
|
|
form.post(route('admin.users.reset-password', user.id));
|
|
}
|
|
};
|
|
|
|
const cancel = () => {
|
|
isCreating.value = false;
|
|
editingUser.value = null;
|
|
form.reset();
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Head title="Équipe / Utilisateurs Admin" />
|
|
<AdminLayout>
|
|
<template #header>Équipe / Utilisateurs Admin</template>
|
|
|
|
<div class="mb-6 flex justify-between items-center">
|
|
<h1 class="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-500 to-indigo-500">
|
|
Administrateurs Plateforme
|
|
</h1>
|
|
<button v-if="!isCreating" @click="isCreating = true" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition">
|
|
Ajouter un Utilisateur
|
|
</button>
|
|
</div>
|
|
|
|
<div v-if="isCreating" class="mb-8 p-6 bg-white dark:bg-slate-800 rounded-xl shadow border border-slate-200 dark:border-slate-700">
|
|
<h2 class="text-lg font-bold mb-4">{{ editingUser ? 'Modifier l\'utilisateur' : 'Nouvel utilisateur admin' }}</h2>
|
|
<form @submit.prevent="submit" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">Nom Complet</label>
|
|
<input v-model="form.name" type="text" class="mt-1 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6" required />
|
|
<div v-if="form.errors.name" class="mt-1 text-sm text-red-600">{{ form.errors.name }}</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">Adresse Email</label>
|
|
<input v-model="form.email" type="email" class="mt-1 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6" required />
|
|
<div v-if="form.errors.email" class="mt-1 text-sm text-red-600">{{ form.errors.email }}</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">Rôle</label>
|
|
<select v-model="form.role" class="mt-1 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6">
|
|
<option value="admin">Administrateur Standard (SaaS)</option>
|
|
<option value="super_admin">Super Administrateur (Global)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div v-if="form.role === 'admin'">
|
|
<label class="block text-sm font-medium text-slate-700 dark:text-slate-300">Structure / Service</label>
|
|
<select v-model="form.tenant_id" class="mt-1 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-blue-600 sm:text-sm sm:leading-6" required>
|
|
<option disabled value="">Sélectionnez une structure</option>
|
|
<option v-for="tenant in tenants" :key="tenant.id" :value="tenant.id">{{ tenant.name }}</option>
|
|
</select>
|
|
<div v-if="form.errors.tenant_id" class="mt-1 text-sm text-red-600">{{ form.errors.tenant_id }}</div>
|
|
</div>
|
|
|
|
<div class="md:col-span-2 flex justify-end gap-3 mt-4">
|
|
<button type="button" @click="cancel" class="px-4 py-2 border border-slate-300 text-slate-700 dark:text-slate-300 rounded-lg whitespace-nowrap">Annuler</button>
|
|
<button type="submit" class="px-4 py-2 bg-blue-600 focus:bg-blue-700 text-white rounded-lg whitespace-nowrap" :disabled="form.processing">
|
|
{{ editingUser ? 'Mettre à jour compte' : 'Créer l\'accès' }}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="bg-white dark:bg-slate-800 rounded-xl shadow overflow-hidden border border-slate-200 dark:border-slate-700">
|
|
<table class="w-full text-left border-collapse">
|
|
<thead>
|
|
<tr class="bg-slate-50 dark:bg-slate-700/50 border-b border-slate-200 dark:border-slate-700">
|
|
<th class="py-4 px-6 font-semibold text-slate-600 dark:text-slate-300">Nom</th>
|
|
<th class="py-4 px-6 font-semibold text-slate-600 dark:text-slate-300">Email</th>
|
|
<th class="py-4 px-6 font-semibold text-slate-600 dark:text-slate-300">Rôle</th>
|
|
<th class="py-4 px-6 font-semibold text-slate-600 dark:text-slate-300">Rattachement</th>
|
|
<th class="py-4 px-6 font-semibold text-slate-600 dark:text-slate-300 text-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="user in users" :key="user.id" class="border-b border-slate-100 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors">
|
|
<td class="py-3 px-6 font-medium">{{ user.name }}</td>
|
|
<td class="py-3 px-6 text-slate-500">{{ user.email }}</td>
|
|
<td class="py-3 px-6">
|
|
<span v-if="user.role === 'super_admin'" class="inline-flex items-center rounded-md bg-purple-50 px-2 py-1 text-xs font-medium text-purple-700 ring-1 ring-inset ring-purple-700/10">Super Admin</span>
|
|
<span v-else class="inline-flex items-center rounded-md bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">Admin Site</span>
|
|
</td>
|
|
<td class="py-3 px-6 text-slate-500">
|
|
{{ user.tenant ? user.tenant.name : (user.role === 'super_admin' ? 'Toutes les structures' : 'Aucun rattachement') }}
|
|
</td>
|
|
<td class="py-3 px-6 text-right space-x-2">
|
|
<button v-if="page.props.auth.user.role === 'super_admin'" @click="resetPassword(user)" class="text-orange-600 hover:text-orange-900 px-3 py-1 rounded bg-orange-50 hover:bg-orange-100 transition-colors" title="Réinitialiser le mot de passe">
|
|
MDP
|
|
</button>
|
|
<button @click="editUser(user)" class="text-indigo-600 hover:text-indigo-900 px-3 py-1 rounded bg-indigo-50 hover:bg-indigo-100 transition-colors">Modifier</button>
|
|
<button @click="deleteUser(user)" class="text-red-600 hover:text-red-900 px-3 py-1 rounded bg-red-50 hover:bg-red-100 transition-colors">Supprimer</button>
|
|
</td>
|
|
</tr>
|
|
<tr v-if="users.length === 0">
|
|
<td colspan="5" class="py-8 text-center text-slate-500">Aucun accès administrateur trouvé.</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</AdminLayout>
|
|
</template>
|