- Site color field with color picker in create/edit modals - Dark mode theme (mytheme-dark) with toggle in navbar - Stronger site color visibility on cards (gradient, top border, badges) - Bigger action buttons (btn-sm) on machine cards - White card backgrounds with proper dark mode support Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
221 lines
7.0 KiB
Vue
221 lines
7.0 KiB
Vue
<template>
|
|
<div v-if="visible" class="modal modal-open">
|
|
<div class="modal-box max-w-md">
|
|
<h3 class="font-bold text-lg mb-4">
|
|
{{ disabled ? 'Détails du site' : 'Modifier le site' }}
|
|
<span v-if="siteName" class="block text-sm font-normal text-base-content/50">{{ siteName }}</span>
|
|
</h3>
|
|
<form class="space-y-4" @submit.prevent="emit('submit')">
|
|
<div class="form-control">
|
|
<label class="label">
|
|
<span class="label-text">Nom du site</span>
|
|
</label>
|
|
<input
|
|
v-model="form.name"
|
|
type="text"
|
|
placeholder="Nom du site"
|
|
class="input input-bordered"
|
|
:disabled="disabled"
|
|
required
|
|
>
|
|
</div>
|
|
|
|
<div class="form-control">
|
|
<label class="label">
|
|
<span class="label-text">Couleur</span>
|
|
</label>
|
|
<div v-if="form.color" class="flex items-center gap-3">
|
|
<input
|
|
:value="form.color"
|
|
type="color"
|
|
class="w-10 h-10 rounded cursor-pointer border border-base-300"
|
|
:disabled="disabled"
|
|
@input="form.color = $event.target.value"
|
|
>
|
|
<input
|
|
v-model="form.color"
|
|
type="text"
|
|
placeholder="#000000"
|
|
class="input input-bordered input-sm flex-1"
|
|
:disabled="disabled"
|
|
maxlength="7"
|
|
>
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs"
|
|
:disabled="disabled"
|
|
@click="form.color = ''"
|
|
>
|
|
Effacer
|
|
</button>
|
|
</div>
|
|
<button
|
|
v-else
|
|
type="button"
|
|
class="btn btn-outline btn-sm w-fit"
|
|
:disabled="disabled"
|
|
@click="form.color = '#3b82f6'"
|
|
>
|
|
Choisir une couleur
|
|
</button>
|
|
</div>
|
|
|
|
<SiteContactFormFields :form="props.form" :disabled="disabled" />
|
|
|
|
<div class="border-t border-base-200 pt-4 space-y-4">
|
|
<div class="flex items-center justify-between">
|
|
<div>
|
|
<h4 class="font-semibold text-sm">
|
|
Documents liés
|
|
</h4>
|
|
<p class="text-xs text-base-content/50">
|
|
Ajoutez des documents (PDF, images...) relatifs à ce site.
|
|
</p>
|
|
</div>
|
|
<span v-if="selectedFilesModel.length" class="badge badge-outline">
|
|
{{ selectedFilesModel.length }} fichier{{ selectedFilesModel.length > 1 ? 's' : '' }} prêt{{ selectedFilesModel.length > 1 ? 's' : '' }} à être ajouté
|
|
</span>
|
|
</div>
|
|
|
|
<DocumentUpload
|
|
v-if="!disabled"
|
|
v-model="selectedFilesModel"
|
|
title="Déposer vos fichiers"
|
|
subtitle="Formats courants acceptés : PDF, JPG, PNG, DOCX..."
|
|
/>
|
|
|
|
<div v-if="documents.length" class="space-y-3">
|
|
<h5 class="text-sm font-medium">
|
|
Documents existants
|
|
</h5>
|
|
<div class="space-y-2 max-h-48 overflow-y-auto pr-1">
|
|
<div
|
|
v-for="document in documents"
|
|
:key="document.id"
|
|
class="flex items-center justify-between rounded border border-base-200 bg-base-100 px-3 py-2"
|
|
>
|
|
<div class="flex items-center gap-3 text-sm">
|
|
<div class="h-14 w-14 flex-shrink-0 overflow-hidden rounded-md border border-base-200 bg-base-200/70 flex items-center justify-center">
|
|
<img
|
|
v-if="isImageDocument(document) && (document.fileUrl || document.path)"
|
|
:src="document.fileUrl || document.path"
|
|
class="h-full w-full object-cover"
|
|
:alt="`Aperçu de ${document.name}`"
|
|
>
|
|
<component
|
|
v-else
|
|
:is="documentIcon(document).component"
|
|
class="h-6 w-6"
|
|
:class="documentIcon(document).colorClass"
|
|
aria-hidden="true"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<div class="font-medium">
|
|
{{ document.name }}
|
|
</div>
|
|
<div class="text-xs text-base-content/50">
|
|
{{ document.mimeType || 'Inconnu' }} • {{ formatSize(document.size) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex items-center gap-2">
|
|
<button
|
|
type="button"
|
|
class="btn btn-ghost btn-xs"
|
|
:disabled="!canPreviewDocument(document)"
|
|
:title="canPreviewDocument(document) ? 'Consulter le document' : 'Aucun aperçu disponible pour ce type'"
|
|
@click="emit('preview-document', document)"
|
|
>
|
|
Consulter
|
|
</button>
|
|
<button type="button" class="btn btn-ghost btn-xs" @click="emit('download-document', document)">
|
|
Télécharger
|
|
</button>
|
|
<button v-if="!disabled" type="button" class="btn btn-error btn-xs" @click="emit('remove-document', document.id)">
|
|
Supprimer
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-action">
|
|
<button type="button" class="btn" @click="emit('close')">
|
|
Annuler
|
|
</button>
|
|
<button type="submit" class="btn btn-primary" :disabled="disabled || uploadingDocuments">
|
|
<span v-if="uploadingDocuments" class="loading loading-spinner loading-xs mr-2" />
|
|
Enregistrer
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed } from 'vue'
|
|
import { isImageDocument } from '~/utils/documentPreview'
|
|
import DocumentUpload from '~/components/DocumentUpload.vue'
|
|
import SiteContactFormFields from '~/components/sites/SiteContactFormFields.vue'
|
|
|
|
const props = defineProps({
|
|
visible: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
siteName: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
form: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
documents: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
selectedFiles: {
|
|
type: Array,
|
|
default: () => []
|
|
},
|
|
uploadingDocuments: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
canPreviewDocument: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
documentIcon: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
formatSize: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits([
|
|
'close',
|
|
'submit',
|
|
'remove-document',
|
|
'download-document',
|
|
'preview-document',
|
|
'update:selectedFiles'
|
|
])
|
|
|
|
const selectedFilesModel = computed({
|
|
get: () => props.selectedFiles,
|
|
set: value => emit('update:selectedFiles', value)
|
|
})
|
|
</script>
|