codedeaffectation
codedeaffectation
<div class="row">
<div class="col-xl-12">
<div class="card custom-card">
<div class="card-header">
<div class="card-title">
<div class="input-group">
<input type="text" v-model="searchValue" class="form-control bg-
light border-0" placeholder="Rechercher" aria-describedby="button-addon2">
<button @click="searchConges" aria-label="button" class="btn btn-
light" type="button" id="button-addon2">
<i class="ri-search-line text-muted"></i>
</button>
</div>
</div>
<div class="ml-auto">
<div class="btn-group mr-4">
<button type="button" class="btn btn-outline-secondary rounded-
pill"
@click="printPage">
<img src="/print.svg" alt="Print Icon" class="svg-icon me-2
align-middle" />
</button>
</div>
</div>
</div>
<th>
<div class="d-flex align-items-center">
<span>#</span>
<i
class="ri-sort-asc ml-auto"
:class="sortColumn === 'index' ? (sortOrder === 'asc' ?
'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('index')"
></i> </div>
<input v-if="showSearch.index" v-model="columnSearch.index"
@input="filterConge" type="text" class="form-control mt-2">
</th>
<th>
<div class="d-flex align-items-center">
<span>Sigle </span>
<i class="ri-search-line text-success ml-auto"
@click="toggleSearch('code_type_dossier')"></i>
<i
:class="sortColumn === 'code_type_dossier' ? (sortOrder
=== 'asc' ? 'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('code_type_dossier')"
></i>
</div>
<input v-if="showSearch.code_type_dossier" v-
model="columnSearch.code_type_dossier" @input="filterConge" type="text"
class="form-control mt-2">
</th>
<th>
<div class="d-flex align-items-center">
<span>Nature dossier </span>
<i class="ri-search-line text-success ml-auto"
@click="toggleSearch('nature_dossier')"></i>
<i
:class="sortColumn === 'nature_dossier' ? (sortOrder
=== 'asc' ? 'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('nature_dossier')"
></i>
</div>
<input v-if="showSearch.nature_dossier" v-
model="columnSearch.nature_dossier" @input="filterConge" type="text" class="form-
control mt-2">
</th>
<th>
<div class="d-flex align-items-center">
<span>Type dossier </span>
<i class="ri-search-line text-success ml-auto"
@click="toggleSearch('libelle')"></i>
<i
:class="sortColumn === 'libelle' ? (sortOrder === 'asc'
? 'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('libelle')"
></i>
</div>
<input v-if="showSearch.libelle" v-
model="columnSearch.libelle" @input="filterConge" type="text" class="form-control
mt-2">
</th>
<th style="width: 100px;">
<div class="d-flex align-items-center">
<span>Pieces </span>
<i class="ri-search-line text-success ml-auto"
@click="toggleSearch('pieces1')"></i>
<i
:class="sortColumn === 'pieces1' ? (sortOrder === 'asc'
? 'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('pieces1')"
></i>
</div>
<input v-if="showSearch.pieces1" v-
model="columnSearch.pieces1" @input="filterConge" type="text" class="form-control
mt-2">
</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in dossiers" :key="item.id">
<td>{{ index + 1 }}</td>
<td>{{ item.code_type_dossier }}</td>
<td>{{ item.nature_dossier ? item.nature_dossier.libelle :
'N/A' }}</td>
<td>{{ item.libelle }}</td>
<td>
<!-- Loop through associated pieces and display them -->
<ul>
<li v-for="piece in
item.associatedPieces" :key="piece.id">{{ piece.libelle }}</li>
</ul>
</td>
<td>
<button class="btn btn-link"
@click="openAssignPiecesModal(item.id)" data-bs-target="#create-task" data-bs-
toggle="modal">
<i class="bi bi-plus-circle" title="Liste des
pièces"></i>
</button>
</td>
</tr>
<tr v-if="dossiers.length === 0">
<td colspan="7" class="text-center">
<h4 class="card">
<i class="bx bx-data"></i> Aucune donnée
</h4>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
import PageHeader from "@/components/common/pageheader.vue";
import axios from "axios";
import Swal from "sweetalert2";
import Papa from "papaparse";
import * as XLSX from "xlsx";
import jsPDF from "jspdf";
import "jspdf-autotable";
export default {
name: 'liste dossier',
components: {
PageHeader,
},
data() {
return {
pieces: [], // Tableau des pièces récupérées de l'API
selectedPieceIds: [], // Tableau des IDs des pièces sélectionnées
dossierTypeId: null,
conges: [],
dossiers: [],
agentOptions: [],
code_type_dossier: {},
dataToPass: {
current: "Affectation type dossier pièce ",
list: ['Affectation type dossier pièce', 'Parametre']
},
searchValue: "",
currentPage: 1,
itemsPerPage: 10,
showSearch: {
index: false,
libelle: false,
code_type_dossier: false,
nature_dossier: false,
pieces1: false,
piece_name: false,
duree: false
},
columnSearch: {},
sortColumn: "",
sortOrder: "asc",
};
},
computed: {
filteredConges() {
return this.conges.filter(conge => {
const agentName = this.getAgentName(conge.type_dossier_id).toLowerCase();
return (
(!this.columnSearch.index ||
conge.index.toString().includes(this.columnSearch.index)) &&
(!this.columnSearch.code_type_dossier ||
agentName.includes(this.columnSearch.code_type_dossier.toLowerCase())) &&
(!this.columnSearch.libelle ||
conge.libelle.toLowerCase().includes(this.columnSearch.libelle.toLowerCase())) &&
(!this.columnSearch.nature_dossier ||
conge.nature_dossier.includes(this.columnSearch.nature_dossier)) &&
(!this.columnSearch.pieces1 ||
conge.pieces1.toLowerCase().includes(this.columnSearch.pieces1.toLowerCase())) &&
(!this.columnSearch.duree ||
conge.duree.toLowerCase().includes(this.columnSearch.duree.toLowerCase()))
);
});
},
sortedConges() {
const congeWithIndex = this.filteredConges.map((conge, index) => {
return { ...conge, index: index + 1 };
});
const sortedConges = congeWithIndex.slice().sort((a, b) => {
let modifier = 1;
if (this.sortOrder === "desc") modifier = -1;
if (this.sortColumn) {
let valueA, valueB;
if (this.sortColumn === 'code_type_dossier') {
valueA = this.getAgentName(a.type_dossier_id).toLowerCase();
valueB = this.getAgentName(b.type_dossier_id).toLowerCase();
} else {
valueA = a[this.sortColumn];
valueB = b[this.sortColumn];
}
openAssignPiecesModal(dossierTypeId) {
this.dossierTypeId = dossierTypeId; // Assigner l'ID du type de dossier
sélectionné
this.selectedPieceIds = []; // Réinitialiser la sélection des pièces
this.fetchPieces(); // Charger les pièces
$('#create-task').modal('show'); // Afficher le modal
},
// Méthode pour gérer la sélection/désélection des pièces
toggleAssignment(index) {
const piece = this.pieces[index];
piece.assigned = !piece.assigned; // Inverser l'état de l'affectation
if (piece.assigned) {
this.selectedPieceIds.push(piece.id); // Ajouter l'ID de la pièce
sélectionnée
} else {
// Retirer l'ID de la pièce désélectionnée
const indexToRemove = this.selectedPieceIds.indexOf(piece.id);
if (indexToRemove > -1) {
this.selectedPieceIds.splice(indexToRemove, 1);
}
}
},
async assignPiecesToDossier() {
try {
if (this.selectedPieceIds.length === 0) {
alert('Veuillez sélectionner au moins une pièce à affecter.');
return;
}
if (response.ok) {
alert('Les pièces ont été affectées avec succès au type de dossier.');
$('#create-task').modal('hide');
this.fetchPieces();
} else {
alert("Erreur lors de l'affectation des pièces.");
}
} catch (error) {
console.error("Erreur lors de l'affectation des pièces:", error);
}
},
async fetchDossiers() {
try {
const response = await
axios.get('http://127.0.0.1:8000/api/typedossier-piece/liste/');
this.dossiers = response.data.map(dossier => {
return {
...dossier,
associatedPieces: dossier.piece_a_fournirs, // Only the pieces related to
this dossier type
nature_dossier: dossier.nature_dossier // Make sure nature_dossier is
included
};
});
} catch (error) {
console.error('Error fetching dossiers:', error);
}
},
downloadExcel() {
const worksheet = XLSX.utils.json_to_sheet(this.conges);
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'conges');
XLSX.writeFile(workbook, `conges_${this.getCurrentDateTime()}.xlsx`);
},
downloadPDF() {
try {
const doc = new jsPDF();
const currentDateTime = this.getCurrentDateTime();
doc.setFontSize(20);
doc.setTextColor('#157e6f');
const title = 'CABINET VAD';
const titleWidth = doc.getStringUnitWidth(title) * 20 /
doc.internal.scaleFactor;
doc.text(title, (doc.internal.pageSize.width - titleWidth) / 2, 10);
doc.setFontSize(12);
doc.setTextColor('#000000');
const subtitle = 'Listes des conges';
const subtitleWidth = doc.getStringUnitWidth(subtitle) * 12 /
doc.internal.scaleFactor;
doc.text(subtitle, (doc.internal.pageSize.width - subtitleWidth) / 2,
17);
doc.setFontSize(10);
doc.text(currentDateTime, 10, doc.internal.pageSize.height - 10);
doc.autoTable({
head: [['#', 'Agent', 'Type', 'Date debut', 'Date fin', 'Durée']],
body: this.conges.map((conge, index) => [
index + 1,
this.getAgentName(conge.type_dossier_id),
conge.type,
conge._dossier,
conge.pieces1,
conge.duree
]),
startY: 25,
theme: 'striped',
headStyles: { fillColor: '#157e6f' }
});
const header = `
<div style="text-align: center; font-size: 20px; color: #157e6f; margin-
bottom: 20px;">
CABINET VAD
</div>
<div style="text-align: center; font-size: 12px; color: #000000; margin-
bottom: 20px;">
Liste des congés
</div>
`;
const footer = `
<div style="position: fixed; bottom: 10px; left: 10px; font-size: 10px;">
${currentDateTime}
</div>
<div style="position: fixed; bottom: 10px; right: 10px; font-size:
10px;">
Développé par Gescano
</div>
`;
const tableStyle = `
<style>
table {
width: 100%;
border-collapse: collapse;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
}
th {
background-color: #f4f4f4;
color: #333;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #e9e9e9;
}
</style>
`;
</script>
<style scoped>
/* Ajoutez vos styles CSS spécifiques si nécessaire */
</style>