0% found this document useful (0 votes)
2 views11 pages

codedeaffectation

Uploaded by

Elysee Woto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views11 pages

codedeaffectation

Uploaded by

Elysee Woto
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 11

<template>

<PageHeader :propData="dataToPass" />

<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>

<button type="button" class="btn btn-outline-secondary rounded-


pill"
@click="downloadPDF">
<img src="/pdf1.svg" alt="PDF Icon" class="svg-icon me-2 align-
middle" />
</button>

<button type="button" class="btn btn-outline-secondary rounded-


pill"
@click="downloadCSV">
<img src="/csv1.svg" alt="Csv Icon" class="svg-icon me-2
align-middle" />
</button>

<button type="button" class="btn btn-outline-secondary rounded-


pill"
@click="downloadExcel">
<img src="/excel.svg" alt="Excel Icon" class="excel-icon
me-2 align-middle" />
</button>

</div>

</div>
</div>

<div class="card custom-card">


<div class="card-body">
<div class="table-responsive">
<table class="table text-nowrap table-bordered">
<thead>
<tr>

<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 class="modal fade" id="create-task" tabindex="-1" aria-


hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body px-4">
<div class="table-responsive">
<table class="table text-nowrap">
<thead>
<tr>
<th></th>
<th>#</th>
<th>
<div class="d-flex align-items-center">
<span>Pièces</span>
<i class="ri-search-line text-success ml-auto"
@click="toggleSearch('piece_name')"></i>
<i :class="sortColumn === 'piece_name' ? (sortOrder
=== 'asc' ? 'ri-sort-desc' : 'ri-sort-asc') : 'ri-sort-asc'"
@click="sortColumnToggle('piece_name')"></i>
</div>
<input v-if="showSearch.piece_name" v-
model="columnSearch.piece_name" @input="filterConge" type="text" class="form-
control mt-2">
</th>
<th>Affecté</th>
</tr>
</thead>
<tbody>
<tr v-for="(piece, index) in pieces" :key="piece.id"
class="product-list">
<td class="task-checkbox">
<input
@click="toggleAssignment(index)"
v-model="piece.assigned"
ref="checkOption"
class="form-check-input"
type="checkbox"
:checked="piece.assigned"
aria-label="..."
/>
</td>
<td>{{ piece.id }}</td>
<td>{{ piece.libelle }}</td>
<td>
<div :class="['btn', 'btn-sm', piece.assigned ? 'btn-
light' : 'btn-danger-light']">
{{ piece.assigned ? 'oui' : 'non' }}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-warning" data-bs-
dismiss="modal" aria-label="Close">Retour</button>
<button type="button" class="btn btn-primary"
@click="assignPiecesToDossier(dossierTypeId)">Affecter pièce</button>

</div>
</div>
</div>
</div>

<!-- Pagination controls -->


<nav aria-label="Page navigation">
<ul class="pagination mb-0">
<li class="page-item" :class="{ disabled: currentPage === 1 }">
<a class="page-link" href="javascript:void(0);"
@click="prevPage">Précédent</a>
</li>
<li class="page-item" v-for="page in
totalPages" :key="page" :class="{ active: currentPage === page }">
<a class="page-link" href="javascript:void(0);"
@click="changePage(page)">{{ page }}</a>
</li>
<li class="page-item" :class="{ disabled: currentPage ===
totalPages }">
<a class="page-link" href="javascript:void(0);"
@click="nextPage">Suivant</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</template>

<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];
}

if (valueA < valueB) return -1 * modifier;


if (valueA > valueB) return 1 * modifier;
}
return 0;
});
return sortedConges.map((conge, index) => {
return { ...conge, index: index + 1 };
});
},
paginatedConges() {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.sortedConges.slice(start, end);
},
totalPages() {
return Math.ceil(this.sortedConges.length / this.itemsPerPage);
}
},
async mounted() {
await this.fetchDossiers();
await this.fetchPieces();
await this.getConges();
},
methods: {
toggleAssignment(index) {
// Inverse l'état de la case cochée
this.pieces[index].assigned = !this.pieces[index].assigned;
},
selectAllProducts() {
// Permet de tout sélectionner ou désélectionner
const allSelected = this.pieces.every(piece => piece.assigned);
this.pieces.forEach(piece => piece.assigned = !allSelected);
},
async fetchPieces() {
try {
const response = await fetch('http://127.0.0.1:8000/api/piece-a-fournir');
const data = await response.json();
this.pieces = data; // Stocker les pièces dans le tableau
} catch (error) {
console.error("Erreur lors de la récupération des pièces:", error);
}
},

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;
}

const response = await fetch(`http://127.0.0.1:8000/api/type-dossiers/$


{this.dossierTypeId}/attach-to-pieces`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
piece_a_fournir_ids: this.selectedPieceIds,
}),
});

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);

const footerText = 'Développé par Gescano';


const footerWidth = doc.getStringUnitWidth(footerText) * 10 /
doc.internal.scaleFactor;
doc.text(footerText, doc.internal.pageSize.width - footerWidth - 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' }
});

doc.save(`conges_${currentDateTime.replace(/ /g, '_').replace(/:/g,


'-')}.pdf`);
} catch (error) {
console.error('Erreur lors de l\'exportation PDF:', error);
}
},
printPage() {
const printContent = document.createElement('div');
const table = document.querySelector('.table-responsive').cloneNode(true);

const rows = table.querySelectorAll('tr');


rows.forEach(row => {
const lastCell = row.lastElementChild;
if (lastCell) {
row.removeChild(lastCell);
}
});

const currentDateTime = this.getCurrentDateTime();

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>
`;

printContent.innerHTML = header + tableStyle + table.outerHTML + footer;

const printWindow = window.open('', '', 'width=800,height=600');


printWindow.document.write('<html><head><title>Impression</title>');
printWindow.document.write('</head><body>');
printWindow.document.write(printContent.innerHTML);
printWindow.document.write('</body></html>');
printWindow.document.close();
printWindow.print();
},
toggleSearch(column) {
this.showSearch[column] = !this.showSearch[column];
if (!this.showSearch[column]) {
this.columnSearch[column] = "";
}
},
sortColumnToggle(column) {
if (this.sortColumn === column) {
this.sortOrder = this.sortOrder === "asc" ? "desc" : "asc";
} else {
this.sortColumn = column;
this.sortOrder = "asc";
}
},
changePage(page) {
this.currentPage = page;
},
nextPage() {
if (this.currentPage < this.totalPages) {
this.currentPage++;
}
},
prevPage() {
if (this.currentPage > 1) {
this.currentPage--;
}
},
getCurrentDateTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
}
};

</script>

<style scoped>
/* Ajoutez vos styles CSS spécifiques si nécessaire */
</style>

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy