Premier commit
This commit is contained in:
135
resources/views/contracts/create.blade.php
Normal file
135
resources/views/contracts/create.blade.php
Normal file
@@ -0,0 +1,135 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">Nouveau Contrat</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('contracts.store') }}">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Nom du Contrat</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required placeholder="ex: Maintenance Serveurs">
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="provider" class="form-label">Fournisseur</label>
|
||||
<input type="text" class="form-control" id="provider" name="provider" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="municipality_id" class="form-label">Commune Affectée</label>
|
||||
<select class="form-select" id="municipality_id" name="municipality_id">
|
||||
<option value="">Global / Agglomération</option>
|
||||
@foreach($municipalities as $municipality)
|
||||
<option value="{{ $municipality->id }}">{{ $municipality->name }} ({{ $municipality->zip_code }})</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="reference" class="form-label">Référence</label>
|
||||
<input type="text" class="form-control" id="reference" name="reference">
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="start_date" class="form-label">Date Début</label>
|
||||
<input type="date" class="form-control" id="start_date" name="start_date" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="end_date" class="form-label">Date Fin (Optionnel)</label>
|
||||
<input type="date" class="form-control" id="end_date" name="end_date">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="amount" class="form-label">Montant (€)</label>
|
||||
<input type="number" step="0.01" class="form-control" id="amount" name="amount">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="type" class="form-label">Type</label>
|
||||
<select class="form-select" id="type" name="type" required>
|
||||
<option value="microsoft_365">Microsoft 365</option>
|
||||
<option value="fiber">Fibre / Internet</option>
|
||||
<option value="domain">Nom de Domaine</option>
|
||||
<option value="software">Logiciel / Licence</option>
|
||||
<option value="hardware">Matériel</option>
|
||||
<option value="consulting">Prestation Intellectuelle</option>
|
||||
<option value="other">Autre</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="m365-fields" class="mb-3 p-3 bg-light border rounded" style="display: none;">
|
||||
<h6>Détails Microsoft 365</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Niveau de Licence</label>
|
||||
<select class="form-select" name="meta[m365_license_level]">
|
||||
<option value="">Sélectionner...</option>
|
||||
@foreach($licenseLevels as $level)
|
||||
<option value="{{ $level->name }}">{{ $level->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Nombre de Licences</label>
|
||||
<input type="number" class="form-control" name="meta[m365_quantity]" placeholder="ex: 10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="notes" class="form-label">Notes</label>
|
||||
<textarea class="form-control" id="notes" name="notes" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<h5>Méta-données supplémentaires</h5>
|
||||
<div id="meta-fields">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" name="meta[key1]" placeholder="Clé (ex: Débit)">
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<input type="text" class="form-control" name="meta[value1]" placeholder="Valeur (ex: 1Gbps)">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 mt-4">
|
||||
<button type="submit" class="btn btn-primary">Créer le Contrat</button>
|
||||
<a href="{{ route('contracts.index') }}" class="btn btn-link text-muted">Annuler</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const typeSelect = document.getElementById('type');
|
||||
const m365Fields = document.getElementById('m365-fields');
|
||||
|
||||
function toggleFields() {
|
||||
if (typeSelect.value === 'microsoft_365') {
|
||||
m365Fields.style.display = 'block';
|
||||
} else {
|
||||
m365Fields.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
typeSelect.addEventListener('change', toggleFields);
|
||||
toggleFields(); // Initial check
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
127
resources/views/contracts/edit.blade.php
Normal file
127
resources/views/contracts/edit.blade.php
Normal file
@@ -0,0 +1,127 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-primary text-white">Modifier le Contrat</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('contracts.update', $contract) }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Nom du Contrat</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="{{ old('name', $contract->name) }}" required>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="provider" class="form-label">Fournisseur</label>
|
||||
<input type="text" class="form-control" id="provider" name="provider" value="{{ old('provider', $contract->provider) }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="municipality_id" class="form-label">Commune Affectée</label>
|
||||
<select class="form-select" id="municipality_id" name="municipality_id">
|
||||
<option value="">Global / Agglomération</option>
|
||||
@foreach($municipalities as $municipality)
|
||||
<option value="{{ $municipality->id }}" {{ (old('municipality_id', $contract->municipality_id) == $municipality->id) ? 'selected' : '' }}>
|
||||
{{ $municipality->name }} ({{ $municipality->zip_code }})
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="reference" class="form-label">Référence</label>
|
||||
<input type="text" class="form-control" id="reference" name="reference" value="{{ old('reference', $contract->reference) }}">
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="start_date" class="form-label">Date Début</label>
|
||||
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ old('start_date', $contract->start_date->format('Y-m-d')) }}" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="end_date" class="form-label">Date Fin (Optionnel)</label>
|
||||
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ old('end_date', $contract->end_date ? $contract->end_date->format('Y-m-d') : '') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<label for="amount" class="form-label">Montant (€)</label>
|
||||
<input type="number" step="0.01" class="form-control" id="amount" name="amount" value="{{ old('amount', $contract->amount) }}">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="status" class="form-label">Statut</label>
|
||||
<select class="form-select" id="status" name="status" required>
|
||||
<option value="active" {{ $contract->status == 'active' ? 'selected' : '' }}>Actif</option>
|
||||
<option value="pending" {{ $contract->status == 'pending' ? 'selected' : '' }}>En attente</option>
|
||||
<option value="expired" {{ $contract->status == 'expired' ? 'selected' : '' }}>Expiré</option>
|
||||
<option value="cancelled" {{ $contract->status == 'cancelled' ? 'selected' : '' }}>Annulé</option>
|
||||
<option value="draft" {{ $contract->status == 'draft' ? 'selected' : '' }}>Brouillon</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="notes" class="form-label">Notes</label>
|
||||
<textarea class="form-control" id="notes" name="notes" rows="3">{{ old('notes', $contract->notes) }}</textarea>
|
||||
</div>
|
||||
|
||||
<!-- M365 Specifics -->
|
||||
@if($contract->type === 'microsoft_365')
|
||||
<div id="m365-fields" class="mb-3 p-3 bg-light border rounded">
|
||||
<h6>Détails Microsoft 365</h6>
|
||||
@php
|
||||
$level = $contract->meta->where('key', 'm365_license_level')->first()?->value;
|
||||
$qty = $contract->meta->where('key', 'm365_quantity')->first()?->value;
|
||||
@endphp
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Niveau de Licence</label>
|
||||
<select class="form-select" name="meta[m365_license_level]">
|
||||
<option value="">Sélectionner...</option>
|
||||
@php
|
||||
// Fallback if licenseLevels is not passed (though controller should pass it)
|
||||
$licenseLevels = $licenseLevels ?? \App\Models\LicenseLevel::active()->get();
|
||||
@endphp
|
||||
@foreach($licenseLevels as $l)
|
||||
<option value="{{ $l->name }}" {{ $level == $l->name ? 'selected' : '' }}>{{ $l->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Nombre de Licences</label>
|
||||
<input type="number" class="form-control" name="meta[m365_quantity]" value="{{ $qty }}" placeholder="ex: 10">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Meta Data Handling could be improved here, currently simplistic -->
|
||||
|
||||
<div class="d-grid gap-2 mt-4">
|
||||
<button type="submit" class="btn btn-primary">Mettre à jour</button>
|
||||
<a href="{{ route('contracts.show', $contract) }}" class="btn btn-link text-muted">Annuler</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
@if(auth()->user()->isAdmin())
|
||||
<form action="{{ route('contracts.destroy', $contract) }}" method="POST" onsubmit="return confirm('Êtes-vous sûr de vouloir supprimer définitivement ce contrat ?');">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-outline-danger w-100">Supprimer le Contrat</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
28
resources/views/contracts/index.blade.php
Normal file
28
resources/views/contracts/index.blade.php
Normal file
@@ -0,0 +1,28 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Gestion des Contrats')
|
||||
|
||||
@section('content')
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<p class="text-muted">Gérer les contrats de l'agglomération ({{ $contracts->total() }})</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-end">
|
||||
@if(auth()->user()->isManager())
|
||||
<a href="{{ route('contracts.create') }}" class="btn btn-primary shadow-sm">
|
||||
<i class="bi bi-plus-lg"></i> Nouveau Contrat
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="contracts-list-section">
|
||||
<!-- Vue Component -->
|
||||
<contracts-table :initial-contracts="{{ json_encode($contracts) }}"></contracts-table>
|
||||
|
||||
<div class="pagination mt-3 justify-content-center">
|
||||
{{ $contracts->links() }}
|
||||
<!-- Note: If using Vue-driven pagination, links() might conflict unless handled properly, but here we just pass initial page -->
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
136
resources/views/contracts/show.blade.php
Normal file
136
resources/views/contracts/show.blade.php
Normal file
@@ -0,0 +1,136 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="mb-4">
|
||||
<a href="{{ route('contracts.index') }}" class="btn btn-outline-secondary">← Retour</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-white d-flex justify-content-between align-items-center">
|
||||
<h3 class="mb-0">{{ $contract->name }}</h3>
|
||||
@if(auth()->user()->isManager())
|
||||
<a href="{{ route('contracts.edit', $contract) }}" class="btn btn-sm btn-outline-primary">Modifier</a>
|
||||
@endif
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<strong>Fournisseur:</strong> {{ $contract->provider }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<strong>Référence:</strong> {{ $contract->reference ?? 'N/A' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<strong>Commune:</strong>
|
||||
@if($contract->municipality)
|
||||
<span class="badge bg-secondary">{{ $contract->municipality->name }} ({{ $contract->municipality->zip_code }})</span>
|
||||
@else
|
||||
<span class="badge bg-light text-dark border">Global / Agglomération</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<strong>Type:</strong> <span class="badge bg-info text-dark">{{ $contract->type }}</span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<strong>Status:</strong> {{ $contract->status }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<strong>Date Début:</strong> {{ $contract->start_date->format('d/m/Y') }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<strong>Date Fin:</strong> {{ $contract->end_date ? $contract->end_date->format('d/m/Y') : 'Indéfinie' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<strong>Montant:</strong> {{ number_format($contract->amount, 2) }} {{ $contract->currency }}
|
||||
</div>
|
||||
@if($contract->notes)
|
||||
<div class="mb-3">
|
||||
<strong>Notes:</strong>
|
||||
<p class="text-muted">{{ $contract->notes }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Meta Data -->
|
||||
@if($contract->meta->isNotEmpty())
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-light">
|
||||
<h5 class="mb-0">Détails Techniques</h5>
|
||||
</div>
|
||||
<ul class="list-group list-group-flush">
|
||||
@foreach($contract->meta as $meta)
|
||||
<li class="list-group-item d-flex justify-content-between">
|
||||
<span>
|
||||
@if($meta->key == 'm365_license_level')
|
||||
<i class="bi bi-microsoft me-1"></i> Niveau Licence M365
|
||||
@elseif($meta->key == 'm365_quantity')
|
||||
<i class="bi bi-people-fill me-1"></i> Nombre de Licences
|
||||
@else
|
||||
{{ $meta->key }}
|
||||
@endif
|
||||
</span>
|
||||
<span class="fw-bold">{{ $meta->value }}</span>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<!-- Documents -->
|
||||
<div class="card shadow-sm mb-4">
|
||||
<div class="card-header bg-light d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Documents</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if($contract->documents->isEmpty())
|
||||
<p class="text-muted small">Aucun document.</p>
|
||||
@else
|
||||
<ul class="list-unstyled">
|
||||
@foreach($contract->documents as $doc)
|
||||
<li class="mb-2 d-flex justify-content-between align-items-center">
|
||||
<a href="{{ Storage::url($doc->path) }}" target="_blank" class="text-decoration-none text-truncate" style="max-width: 200px;">
|
||||
<i class="bi bi-file-earmark-text"></i> {{ $doc->filename }}
|
||||
</a>
|
||||
@if(auth()->id() == $doc->uploaded_by || auth()->user()->isManager())
|
||||
<form action="{{ route('documents.destroy', $doc) }}" method="POST" class="d-inline" onsubmit="return confirm('Supprimer ?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
|
||||
@if(auth()->user()->isManager())
|
||||
<hr>
|
||||
<form action="{{ route('documents.store', $contract) }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="mb-2">
|
||||
<label class="form-label small">Ajouter un document</label>
|
||||
<input type="file" name="file" class="form-control form-control-sm" required>
|
||||
</div>
|
||||
<div class="mb-2">
|
||||
<input type="text" name="description" placeholder="Description (optionnel)" class="form-control form-control-sm">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-sm btn-success w-100">Uploader</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user