mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
chore: Initial Commit
feat: Gestion des inscriptions [#1] feat(frontend): Création des vues pour le paramétrage de l'école [#2] feat: Gestion du login [#6] fix: Correction lors de la migration des modèle [#8] feat: Révision du menu principal [#9] feat: Ajout d'un footer [#10] feat: Création des dockers compose pour les environnements de développement et de production [#12] doc(ci): Mise en place de Husky et d'un suivi de version automatique [#14]
This commit is contained in:
97
Front-End/src/utils/Date.js
Normal file
97
Front-End/src/utils/Date.js
Normal file
@ -0,0 +1,97 @@
|
||||
import { startOfWeek, endOfWeek, eachDayOfInterval, format } from 'date-fns';
|
||||
import { fr } from 'date-fns/locale';
|
||||
|
||||
/**
|
||||
* Convertit une date string d'un format à un objet Date
|
||||
* @param {*} dateString
|
||||
* @param {*} format
|
||||
* @returns
|
||||
*/
|
||||
export function parseDate(dateString, format) {
|
||||
const formatParts = format.split(/[- :]/);
|
||||
const dateParts = dateString.split(/[- :]/);
|
||||
const dateMap = {};
|
||||
|
||||
formatParts.forEach((part, index) => {
|
||||
dateMap[part] = parseInt(dateParts[index], 10);
|
||||
});
|
||||
|
||||
return new Date(
|
||||
dateMap['YYYY'] || 0,
|
||||
(dateMap['MM'] || 1) - 1,
|
||||
dateMap['DD'] || 1,
|
||||
dateMap['hh'] || 0,
|
||||
dateMap['mm'] || 0,
|
||||
dateMap['ss'] || 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit un objet Date en une date string d'un format donné
|
||||
* @param {*} date
|
||||
* @param {*} toFormat
|
||||
* @returns
|
||||
*/
|
||||
export function formatDate (date, toFormat) {
|
||||
const padZero = (num) => (num < 10 ? '0' + num : num);
|
||||
const formatMap = {
|
||||
'DD': padZero(date.getDate()),
|
||||
'MM': padZero(date.getMonth() + 1),
|
||||
'YYYY': date.getFullYear(),
|
||||
'hh': padZero(date.getHours()),
|
||||
'mm': padZero(date.getMinutes()),
|
||||
'ss': padZero(date.getSeconds())
|
||||
};
|
||||
|
||||
return toFormat.replace(/DD|MM|YYYY|hh|mm|ss/g, (match) => formatMap[match]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fonction qui convertit une date string d'un format à un autre format
|
||||
* @param {*} dateString
|
||||
* @param {*} fromFormat
|
||||
* @param {*} toFormat
|
||||
* @returns
|
||||
*/
|
||||
export function swapFormatDate(dateString, fromFormat = 'DD-MM-YYYY hh:mm:ss', toFormat = 'DD/MM/YYYY') {
|
||||
const date = parseDate(dateString, fromFormat);
|
||||
return formatDate(date, toFormat);
|
||||
}
|
||||
// ...existing code...
|
||||
|
||||
/**
|
||||
* Convertit une date en format ISO pour l'API
|
||||
*/
|
||||
export function toISOFormat(date) {
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formate une date pour l'affichage dans le calendrier
|
||||
*/
|
||||
export function toCalendarFormat(date) {
|
||||
return formatDate(date, 'DD/MM/YYYY HH:mm');
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si deux dates sont le même jour
|
||||
*/
|
||||
export function isSameDay(date1, date2) {
|
||||
return date1.getFullYear() === date2.getFullYear() &&
|
||||
date1.getMonth() === date2.getMonth() &&
|
||||
date1.getDate() === date2.getDate();
|
||||
}
|
||||
|
||||
|
||||
export const getWeekDays = (date) => {
|
||||
const start = startOfWeek(date, { locale: fr, weekStartsOn: 1 });
|
||||
const end = endOfWeek(date, { locale: fr, weekStartsOn: 1 });
|
||||
|
||||
return eachDayOfInterval({ start, end });
|
||||
};
|
||||
|
||||
|
||||
export const isWeekend = (date) => {
|
||||
const day = date.getDay();
|
||||
return day === 0 || day === 6;
|
||||
};
|
||||
35
Front-End/src/utils/Telephone.js
Normal file
35
Front-End/src/utils/Telephone.js
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
const localePrefixes = {
|
||||
"fr-FR": "+33",
|
||||
// Ajoutez d'autres locales et leurs préfixes ici
|
||||
};
|
||||
|
||||
|
||||
export function formatPhoneNumber(phoneString, fromFormat = 'XX-XX-XX-XX-XX', toFormat = 'LX-XX-XX-XX-XX', locale = "fr-FR") {
|
||||
// Extraire les chiffres du numéro de téléphone
|
||||
const digits = phoneString.replace(/\D/g, '');
|
||||
|
||||
// Déterminer le préfixe international en fonction de la locale
|
||||
|
||||
|
||||
let prefix = localePrefixes[locale] || '';
|
||||
|
||||
// Si le format d'entrée commence par 'L', détecter la locale
|
||||
if (fromFormat.startsWith('L')) {
|
||||
const detectedPrefix = phoneString.match(/^\+\d+/);
|
||||
if (detectedPrefix) {
|
||||
prefix = detectedPrefix[0];
|
||||
phoneString = phoneString.replace(prefix, '');
|
||||
}
|
||||
}
|
||||
|
||||
// Remplacer 'L' par le préfixe et 'X' par les chiffres du numéro de téléphone
|
||||
let formattedNumber = toFormat.replace('L', prefix);
|
||||
let digitIndex = 0;
|
||||
|
||||
formattedNumber = formattedNumber.replace(/X/g, () => {
|
||||
return digits[digitIndex++] || '';
|
||||
});
|
||||
|
||||
return formattedNumber;
|
||||
}
|
||||
72
Front-End/src/utils/Url.js
Normal file
72
Front-End/src/utils/Url.js
Normal file
@ -0,0 +1,72 @@
|
||||
export const BASE_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
|
||||
|
||||
//URL-Back-End
|
||||
|
||||
export const BK_NEW_PASSWORD_URL = `${BASE_URL}/GestionLogin/newPassword`
|
||||
export const BK_REGISTER_URL = `${BASE_URL}/GestionLogin/subscribe`
|
||||
export const BK_RESET_PASSWORD_URL = `${BASE_URL}/GestionLogin/resetPassword`
|
||||
export const BK_LOGIN_URL = `${BASE_URL}/GestionLogin/login`
|
||||
export const BK_LOGOUT_URL = `${BASE_URL}/GestionLogin/logout`
|
||||
export const BK_PROFILE_URL = `${BASE_URL}/GestionLogin/profil`
|
||||
export const BK_GESTIONINSCRIPTION_ELEVE_URL = `${BASE_URL}/GestionInscriptions/eleve`
|
||||
export const BK_GESTIONINSCRIPTION_ENFANTS_URL = `${BASE_URL}/GestionInscriptions/enfants` // Récupère la liste des élèves d'un profil
|
||||
export const BK_GESTIONINSCRIPTION_ELEVES_URL = `${BASE_URL}/GestionInscriptions/eleves` // Récupère la liste des élèves inscrits ou en cours d'inscriptions
|
||||
export const BK_GESTIONINSCRIPTION_SEND_URL = `${BASE_URL}/GestionInscriptions/send`
|
||||
export const BK_GESTIONINSCRIPTION_ARCHIVE_URL = `${BASE_URL}/GestionInscriptions/archive`
|
||||
export const BK_GESTIONINSCRIPTION_FICHESINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/fichesInscription`
|
||||
export const BK_GESTIONINSCRIPTION_FICHEINSCRIPTION_URL = `${BASE_URL}/GestionInscriptions/ficheInscription`
|
||||
export const BK_GESTIONINSCRIPTION_RECUPEREDERNIER_RESPONSABLE_URL = `${BASE_URL}/GestionInscriptions/recupereDernierResponsable`
|
||||
export const BK_GESTIONINSCRIPTION_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
|
||||
export const BK_GESTIONINSCRIPTION_SPECIALITES_URL = `${BASE_URL}/GestionEnseignants/specialites`
|
||||
export const BK_GESTIONINSCRIPTION_SPECIALITE_URL = `${BASE_URL}//GestionEnseignants/specialite`
|
||||
export const BK_GESTIONINSCRIPTION_CLASSES_URL = `${BASE_URL}/GestionEnseignants/classes`
|
||||
export const BK_GESTIONINSCRIPTION_CLASSE_URL = `${BASE_URL}/GestionEnseignants/classe`
|
||||
export const BK_GESTIONINSCRIPTION_TEACHERS_URL = `${BASE_URL}/GestionEnseignants/enseignants`
|
||||
export const BK_GESTIONINSCRIPTION_TEACHER_URL = `${BASE_URL}/GestionEnseignants/enseignant`
|
||||
|
||||
export const BK_GET_CSRF = `${BASE_URL}/GestionLogin/csrf`
|
||||
|
||||
|
||||
// URL FRONT-END
|
||||
|
||||
export const FR_HOME_URL = `/`
|
||||
|
||||
// USERS
|
||||
export const FR_USERS_LOGIN_URL = `/users/login`
|
||||
export const FR_USERS_SUBSCRIBE_URL = `/users/subscribe`
|
||||
export const FR_USERS_RESET_PASSWORD_URL = `/users/password/reset`
|
||||
export const FR_USERS_NEW_PASSWORD_URL = `/users/password/new`
|
||||
|
||||
|
||||
//ADMIN
|
||||
export const FR_ADMIN_HOME_URL = `/admin`
|
||||
|
||||
// ADMIN/STUDENTS URL
|
||||
export const FR_ADMIN_STUDENT_URL = `/admin/students`
|
||||
export const FR_ADMIN_STUDENT_EDIT_SUBSCRIBE = `/admin/students/editInscription`
|
||||
|
||||
//ADMIN/CLASSES URL
|
||||
export const FR_ADMIN_CLASSES_URL = `/admin/classes`
|
||||
|
||||
//ADMIN/STRUCTURE URL
|
||||
export const FR_ADMIN_STRUCTURE_URL = `/admin/structure`
|
||||
|
||||
//ADMIN/GRADES URL
|
||||
export const FR_ADMIN_GRADES_URL = `/admin/grades`
|
||||
|
||||
//ADMIN/TEACHERS URL
|
||||
export const FR_ADMIN_TEACHERS_URL = `/admin/teachers`
|
||||
|
||||
//ADMIN/PLANNING URL
|
||||
export const FR_ADMIN_PLANNING_URL = `/admin/planning`
|
||||
|
||||
//ADMIN/SETTINGS URL
|
||||
export const FR_ADMIN_SETTINGS_URL = `/admin/settings`
|
||||
|
||||
// PARENT HOME
|
||||
export const FR_PARENTS_HOME_URL = `/parents`
|
||||
export const FR_PARENTS_MESSAGERIE_URL = `/parents/messagerie`
|
||||
export const FR_PARENTS_SETTINGS_URL = `/parents/settings`
|
||||
export const FR_PARENTS_EDIT_INSCRIPTION_URL = `/parents/editInscription`
|
||||
30
Front-End/src/utils/constants.js
Normal file
30
Front-End/src/utils/constants.js
Normal file
@ -0,0 +1,30 @@
|
||||
export const WEEKDAYS = [
|
||||
{ id: 1, name: 'Lundi' },
|
||||
{ id: 2, name: 'Mardi' },
|
||||
{ id: 3, name: 'Mercredi' },
|
||||
{ id: 4, name: 'Jeudi' },
|
||||
{ id: 5, name: 'Vendredi' },
|
||||
{ id: 6, name: 'Samedi' },
|
||||
{ id: 7, name: 'Dimanche' }
|
||||
];
|
||||
|
||||
export const DEFAULT_EVENT = {
|
||||
title: '',
|
||||
description: '',
|
||||
start: '',
|
||||
end: '',
|
||||
location: '',
|
||||
scheduleId: 'default',
|
||||
color: '#10b981',
|
||||
recurrence: 'none',
|
||||
selectedDays: [],
|
||||
recurrenceEnd: ''
|
||||
};
|
||||
|
||||
export const VIEW_TYPES = {
|
||||
WEEK: 'week',
|
||||
MONTH: 'month',
|
||||
YEAR: 'year'
|
||||
};
|
||||
|
||||
export const TIME_SLOTS = Array.from({ length: 24 }, (_, i) => i);
|
||||
110
Front-End/src/utils/events.js
Normal file
110
Front-End/src/utils/events.js
Normal file
@ -0,0 +1,110 @@
|
||||
import { isSameDay, startOfDay, endOfDay } from 'date-fns';
|
||||
|
||||
/**
|
||||
* Calcule la position et les dimensions d'un événement dans le calendrier
|
||||
* @param {Object} event - L'événement à positionner
|
||||
* @param {Array<Object>} overlappingEvents - Liste des événements qui se chevauchent
|
||||
* @returns {Object} Position et dimensions de l'événement (top, height, position, width, left)
|
||||
*/
|
||||
export const calculateEventPosition = (event, overlappingEvents) => {
|
||||
const start = new Date(event.start);
|
||||
const end = new Date(event.end);
|
||||
const startHour = start.getHours() + start.getMinutes() / 60;
|
||||
const endHour = end.getHours() + end.getMinutes() / 60;
|
||||
const duration = endHour - startHour;
|
||||
|
||||
const sortedEvents = overlappingEvents.sort((a, b) => new Date(a.start) - new Date(b.start));
|
||||
const index = sortedEvents.findIndex(e => e.id === event.id);
|
||||
|
||||
return {
|
||||
top: `${startHour * 5}rem`,
|
||||
height: `${duration * 5}rem`,
|
||||
position: 'absolute',
|
||||
width: `${95 / overlappingEvents.length}%`,
|
||||
left: `${(index * 95) / overlappingEvents.length}%`,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Récupère tous les événements qui se chevauchent avec l'événement donné
|
||||
* @param {Object} event - L'événement de référence
|
||||
* @param {Array<Object>} dayEvents - Liste des événements de la journée
|
||||
* @returns {Array<Object>} Liste des événements qui se chevauchent
|
||||
*/
|
||||
export const getOverlappingEvents = (event, dayEvents) => {
|
||||
return dayEvents.filter(otherEvent => {
|
||||
if (event.id === otherEvent.id) return false;
|
||||
const eventStart = new Date(event.start);
|
||||
const eventEnd = new Date(event.end);
|
||||
const otherStart = new Date(otherEvent.start);
|
||||
const otherEnd = new Date(otherEvent.end);
|
||||
return (eventStart < otherEnd && eventEnd > otherStart);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Filtre les événements pour une date spécifique
|
||||
* @param {Date} date - La date pour laquelle filtrer les événements
|
||||
* @param {Array<Object>} [events=[]] - Liste des événements à filtrer
|
||||
* @returns {Array<Object>} Liste des événements pour la date donnée
|
||||
*/
|
||||
export const getEventsForDate = (date, events = []) => {
|
||||
return events.filter(event => {
|
||||
const eventDate = new Date(event.start);
|
||||
return (
|
||||
eventDate.getDate() === date.getDate() &&
|
||||
eventDate.getMonth() === date.getMonth() &&
|
||||
eventDate.getFullYear() === date.getFullYear()
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Compte le nombre d'événements pour un mois donné
|
||||
* @param {Date} month - Le mois pour lequel compter les événements
|
||||
* @param {Array<Object>} [events=[]] - Liste des événements à compter
|
||||
* @returns {number} Nombre d'événements dans le mois
|
||||
*/
|
||||
export const getMonthEventCount = (month, events = []) => {
|
||||
return events.filter(event => {
|
||||
const eventDate = new Date(event.start);
|
||||
return (
|
||||
eventDate.getMonth() === month.getMonth() &&
|
||||
eventDate.getFullYear() === month.getFullYear()
|
||||
);
|
||||
}).length;
|
||||
};
|
||||
|
||||
/**
|
||||
* Récupère tous les événements d'une semaine donnée
|
||||
* @param {Date} day - Un jour de la semaine
|
||||
* @param {Array<Object>} events - Liste des événements à filtrer
|
||||
* @returns {Array<Object>} Liste des événements de la semaine
|
||||
*/
|
||||
export const getWeekEvents = (day, events) => {
|
||||
const start = startOfDay(day);
|
||||
const end = endOfDay(day);
|
||||
|
||||
return events.filter(event => {
|
||||
const eventStart = new Date(event.start);
|
||||
const eventEnd = new Date(event.end);
|
||||
|
||||
// Un événement est dans la journée si :
|
||||
// - il commence pendant la journée
|
||||
// - il finit pendant la journée
|
||||
// - il englobe toute la journée
|
||||
return (eventStart >= start && eventStart <= end) || // commence dans la journée
|
||||
(eventEnd >= start && eventEnd <= end) || // finit dans la journée
|
||||
(eventStart <= start && eventEnd >= end); // englobe la journée
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Filtre les événements en excluant ceux des emplois du temps masqués
|
||||
* @param {Array<Object>} events - Liste de tous les événements
|
||||
* @param {Array<string|number>} hiddenSchedules - IDs des emplois du temps masqués
|
||||
* @returns {Array<Object>} Liste des événements filtrés
|
||||
*/
|
||||
export const filterEventsByVisibleSchedules = (events, hiddenSchedules) => {
|
||||
return events.filter(event => !hiddenSchedules.includes(event.scheduleId));
|
||||
};
|
||||
21
Front-End/src/utils/i18n.js
Normal file
21
Front-End/src/utils/i18n.js
Normal file
@ -0,0 +1,21 @@
|
||||
// utils/i18n.js
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* Récupère la liste des locales disponibles.
|
||||
* @param {string} locale - La locale pour laquelle récupérer les namespaces
|
||||
* @returns {Promise<string[]>} Liste des locales disponibles
|
||||
*/
|
||||
export async function getAvailableNamespaces(locale) {
|
||||
try {
|
||||
const messagesPath = path.join(process.cwd(), 'messages', locale);
|
||||
const files = await fs.readdir(messagesPath);
|
||||
return files
|
||||
.filter(file => file.endsWith('.json'))
|
||||
.map(file => file.replace('.json', ''));
|
||||
} catch (error) {
|
||||
console.warn(`Impossible de lire les namespaces pour ${locale}:`, error);
|
||||
return ['common']; // Namespace par défaut
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user