Premier commit

This commit is contained in:
jeremy bayse
2026-02-09 11:27:21 +01:00
commit 89a369964d
114 changed files with 17837 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
<script setup>
import { ref, computed } from 'vue';
const props = defineProps({
initialContracts: {
type: Object, // Laravel Paginate Object
required: true
}
});
const contracts = ref(props.initialContracts.data);
const searchQuery = ref('');
const typeFilter = ref('');
const filteredContracts = computed(() => {
return contracts.value.filter(contract => {
const matchesSearch = contract.name.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
contract.provider.toLowerCase().includes(searchQuery.value.toLowerCase()) ||
(contract.municipality && contract.municipality.name.toLowerCase().includes(searchQuery.value.toLowerCase()));
const matchesType = typeFilter.value ? contract.type === typeFilter.value : true;
return matchesSearch && matchesType;
});
});
const formatDate = (date) => {
return new Date(date).toLocaleDateString('fr-FR');
};
const formatCurrency = (amount, currency) => {
return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: currency }).format(amount);
};
const isExpiringSoon = (dateString) => {
if (!dateString) return false;
const today = new Date();
today.setHours(0, 0, 0, 0);
const date = new Date(dateString);
// Create date 2 months from now
const twoMonthsFromNow = new Date();
twoMonthsFromNow.setMonth(today.getMonth() + 2);
// Check if date is in the future (or today) AND before 2 months from now
// If it's already past, it's expired, not expiring soon (unless we want to highlight overdue too but usually that's red)
// The user asked "arrivant a échéances", implies approaching.
// Let's include today.
return date >= today && date <= twoMonthsFromNow;
};
</script>
<template>
<div class="card shadow-sm border-0">
<div class="card-header border-bottom-0 d-flex justify-content-between align-items-center">
<h5 class="mb-0 text-white">Contrats</h5>
<div class="d-flex gap-2">
<input v-model="searchQuery" type="text" class="form-control form-control-sm" placeholder="Rechercher...">
<select v-model="typeFilter" class="form-select form-select-sm">
<option value="">Tous les types</option>
<option value="microsoft_365">Microsoft 365</option>
<option value="fiber">Fibre</option>
<option value="domain">Domaine</option>
<option value="software">Logiciel</option>
</select>
</div>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle mb-0">
<thead>
<tr>
<th>Nom</th>
<th>Commune</th>
<th>Fournisseur</th>
<th>Type</th>
<th>État</th>
<th>Date fin</th>
<th>Montant</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="contract in filteredContracts" :key="contract.id" :class="{ 'table-warning': isExpiringSoon(contract.end_date) && contract.status !== 'expired' }">
<td>
{{ contract.name }}
<i v-if="isExpiringSoon(contract.end_date) && contract.status !== 'expired'" class="bi bi-exclamation-triangle-fill text-warning ms-1" title="Expire dans moins de 2 mois"></i>
</td>
<td>
<span v-if="contract.municipality" class="badge bg-secondary">{{ contract.municipality.name }}</span>
<span v-else class="text-muted small">Global</span>
</td>
<td>{{ contract.provider }}</td>
<td>
<span class="badge bg-info">{{ contract.type }}</span>
</td>
<td>
<span :class="{
'badge bg-success': contract.status === 'active',
'badge bg-warning': contract.status === 'pending',
'badge bg-danger': contract.status === 'expired',
'badge bg-secondary': contract.status === 'draft' || contract.status === 'cancelled'
}">{{ contract.status }}</span>
</td>
<td :class="{ 'fw-bold text-danger': isExpiringSoon(contract.end_date) && contract.status !== 'expired' }">
{{ contract.end_date ? formatDate(contract.end_date) : '-' }}
</td>
<td>{{ contract.amount ? formatCurrency(contract.amount, contract.currency) : '-' }}</td>
<td>
<a :href="`/contracts/${contract.id}`" class="btn btn-sm btn-outline-primary me-1">
Voir
</a>
</td>
</tr>
<tr v-if="filteredContracts.length === 0">
<td colspan="8" class="text-center py-3 text-muted">Aucun contrat trouvé.</td>
</tr>
</tbody>
</table>
</div>
<!-- Simple Pagination links (could be enhanced) -->
</div>
</template>