Initial commit of the L'Ami Fiduciaire SaaS platform built on Laravel 12, Vue 3, Inertia.js 2, and Tailwind CSS 4. Story 0.1 (rename folders to declarations in database) is implemented and code-reviewed: migration, rollback, and 6 Pest tests all passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
217 lines
8.2 KiB
Vue
217 lines
8.2 KiB
Vue
<script setup lang="ts">
|
|
import { Head, Link, router } from '@inertiajs/vue3';
|
|
import { FolderOpen } from 'lucide-vue-next';
|
|
import Heading from '@/components/Heading.vue';
|
|
import AppLayout from '@/layouts/AppLayout.vue';
|
|
import Pagination from '@/components/Pagination.vue';
|
|
import { Button } from '@/components/ui/button';
|
|
|
|
type Folder = {
|
|
id: number;
|
|
title: string;
|
|
type: string;
|
|
client_name: string;
|
|
status: string;
|
|
due_date: string | null;
|
|
showUrl: string;
|
|
editUrl: string;
|
|
destroyUrl: string;
|
|
};
|
|
|
|
type PaginatedData<T> = {
|
|
data: T[];
|
|
from: number | null;
|
|
to: number | null;
|
|
total: number;
|
|
current_page: number;
|
|
last_page: number;
|
|
per_page: number;
|
|
path: string;
|
|
first_page_url: string;
|
|
prev_page_url: string | null;
|
|
next_page_url: string | null;
|
|
last_page_url: string;
|
|
};
|
|
|
|
type Props = {
|
|
folders: PaginatedData<Folder>;
|
|
createUrl: string;
|
|
workspaceName: string;
|
|
};
|
|
|
|
defineProps<Props>();
|
|
|
|
function destroy(folder: Folder) {
|
|
if (
|
|
window.confirm(
|
|
`Êtes-vous sûr de vouloir supprimer « ${folder.title} » ?`,
|
|
)
|
|
) {
|
|
router.delete(folder.destroyUrl);
|
|
}
|
|
}
|
|
|
|
const typeLabels: Record<string, string> = {
|
|
vat: 'TVA',
|
|
vat_monthly: 'TVA mensuelle',
|
|
vat_quarterly: 'TVA trimestrielle',
|
|
corporate_tax: 'IS',
|
|
income_tax: 'IR',
|
|
cnss: 'CNSS',
|
|
annual_balance: 'Bilan',
|
|
other: 'Autre',
|
|
};
|
|
|
|
const statusLabels: Record<string, string> = {
|
|
draft: 'Brouillon',
|
|
waiting_documents: 'En attente documents',
|
|
documents_received: 'Documents reçus',
|
|
processing: 'En cours de traitement',
|
|
additional_documents_requested: 'Pièces complémentaires demandées',
|
|
waiting_client_validation: 'En attente validation client',
|
|
validated: 'Validé',
|
|
closed: 'Clôturé',
|
|
cancelled: 'Annulé',
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<AppLayout
|
|
:breadcrumbs="[
|
|
{ title: 'Dossiers' },
|
|
]"
|
|
>
|
|
<Head title="Dossiers" />
|
|
|
|
<div class="flex flex-col space-y-6 p-4">
|
|
<div class="flex items-center justify-between">
|
|
<Heading
|
|
variant="small"
|
|
title="Dossiers"
|
|
:description="`Gérer les dossiers du workspace « ${workspaceName} »`"
|
|
/>
|
|
<Button as-child>
|
|
<Link :href="createUrl">Créer un dossier</Link>
|
|
</Button>
|
|
</div>
|
|
|
|
<div
|
|
class="rounded-xl border border-sidebar-border/70 dark:border-sidebar-border overflow-hidden"
|
|
>
|
|
<div class="overflow-x-auto">
|
|
<table class="w-full text-sm">
|
|
<thead class="border-b border-sidebar-border/70 bg-muted/50">
|
|
<tr>
|
|
<th
|
|
class="h-10 px-4 text-left font-medium align-middle"
|
|
>
|
|
Titre
|
|
</th>
|
|
<th
|
|
class="h-10 px-4 text-left font-medium align-middle"
|
|
>
|
|
Client
|
|
</th>
|
|
<th
|
|
class="h-10 px-4 text-left font-medium align-middle"
|
|
>
|
|
Type
|
|
</th>
|
|
<th
|
|
class="h-10 px-4 text-left font-medium align-middle"
|
|
>
|
|
Statut
|
|
</th>
|
|
<th
|
|
class="h-10 px-4 text-left font-medium align-middle"
|
|
>
|
|
Date limite
|
|
</th>
|
|
<th
|
|
class="h-10 px-4 text-right font-medium align-middle"
|
|
>
|
|
Actions
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="folder in folders.data"
|
|
:key="folder.id"
|
|
class="border-b border-sidebar-border/50 last:border-0"
|
|
>
|
|
<td class="px-4 py-3 font-medium">
|
|
<Link
|
|
:href="folder.showUrl"
|
|
class="hover:underline"
|
|
>
|
|
{{ folder.title }}
|
|
</Link>
|
|
</td>
|
|
<td class="px-4 py-3 text-muted-foreground">
|
|
{{ folder.client_name }}
|
|
</td>
|
|
<td class="px-4 py-3 text-muted-foreground">
|
|
{{ typeLabels[folder.type] ?? folder.type }}
|
|
</td>
|
|
<td class="px-4 py-3 text-muted-foreground">
|
|
{{ statusLabels[folder.status] ?? folder.status }}
|
|
</td>
|
|
<td class="px-4 py-3 text-muted-foreground">
|
|
{{ folder.due_date || '—' }}
|
|
</td>
|
|
<td class="px-4 py-3 text-right space-x-2">
|
|
<Button variant="outline" size="sm" as-child>
|
|
<Link :href="folder.showUrl"
|
|
>Voir</Link
|
|
>
|
|
</Button>
|
|
<Button variant="outline" size="sm" as-child>
|
|
<Link :href="folder.editUrl"
|
|
>Modifier</Link
|
|
>
|
|
</Button>
|
|
<Button
|
|
variant="destructive"
|
|
size="sm"
|
|
@click="destroy(folder)"
|
|
>
|
|
Supprimer
|
|
</Button>
|
|
</td>
|
|
</tr>
|
|
<tr v-if="!folders.data.length">
|
|
<td
|
|
colspan="6"
|
|
class="px-4 py-8 text-center text-muted-foreground"
|
|
>
|
|
<div class="flex flex-col items-center gap-2">
|
|
<FolderOpen class="h-10 w-10" />
|
|
<p>Aucun dossier pour le moment.</p>
|
|
<Button as-child>
|
|
<Link :href="createUrl"
|
|
>Créer votre premier
|
|
dossier</Link
|
|
>
|
|
</Button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<Pagination
|
|
:pagination="{
|
|
from: folders.from ?? 0,
|
|
to: folders.to ?? 0,
|
|
total: folders.total,
|
|
current_page: folders.current_page,
|
|
last_page: folders.last_page,
|
|
per_page: folders.per_page,
|
|
}"
|
|
/>
|
|
</div>
|
|
</AppLayout>
|
|
</template>
|