chore: commit qui sert à rien

This commit is contained in:
N3WT DE COMPET
2025-02-13 17:13:31 +01:00
parent 9bf9c5f62d
commit cce78355a3
17 changed files with 210 additions and 143 deletions

View File

@ -0,0 +1,24 @@
from django.core.management.base import BaseCommand
from School.models import Establishment, StructureType
class Command(BaseCommand):
help = 'Initialize the establishment'
def handle(self, *args, **kwargs):
establishment_data = {
"name": "N3WT",
"address": "Société n3wt-innov 69 Chez LANA",
"total_capacity": 69,
"establishment_type": [StructureType.MATERNELLE, StructureType.PRIMAIRE],
"licence_code": ""
}
establishment, created = Establishment.objects.update_or_create(
name=establishment_data["name"],
defaults=establishment_data
)
if created:
self.stdout.write(self.style.SUCCESS('Establishment created successfully'))
else:
self.stdout.write(self.style.SUCCESS('Establishment updated successfully'))

View File

@ -1,5 +1,5 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from School.models import PaymentMode, PaymentModeType, FeeType from School.models import PaymentMode, PaymentModeType, FeeType, Establishment
class Command(BaseCommand): class Command(BaseCommand):
help = 'Initialize or update Payment Modes' help = 'Initialize or update Payment Modes'
@ -8,6 +8,7 @@ class Command(BaseCommand):
self.create_or_update_payment_modes() self.create_or_update_payment_modes()
def create_or_update_payment_modes(self): def create_or_update_payment_modes(self):
establishment = Establishment.objects.get(name="N3WT")
for fee_type in FeeType.choices: for fee_type in FeeType.choices:
fee_type_value = fee_type[0] fee_type_value = fee_type[0]
@ -18,7 +19,8 @@ class Command(BaseCommand):
mode=mode_value, mode=mode_value,
type=fee_type_value, type=fee_type_value,
defaults={ defaults={
'is_active': False 'is_active': False,
'establishment': establishment
} }
) )

View File

@ -1,7 +1,7 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.utils import timezone from django.utils import timezone
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from School.models import PaymentPlan, PaymentPlanType, FeeType from School.models import PaymentPlan, PaymentPlanType, FeeType, Establishment
class Command(BaseCommand): class Command(BaseCommand):
help = 'Initialize or update Payment Plans' help = 'Initialize or update Payment Plans'
@ -11,6 +11,7 @@ class Command(BaseCommand):
def create_or_update_payment_plans(self): def create_or_update_payment_plans(self):
current_date = timezone.now().date() current_date = timezone.now().date()
establishment = Establishment.objects.get(name="N3WT")
for fee_type in FeeType.choices: for fee_type in FeeType.choices:
fee_type_value = fee_type[0] fee_type_value = fee_type[0]
@ -21,7 +22,8 @@ class Command(BaseCommand):
type=fee_type_value, type=fee_type_value,
defaults={ defaults={
'due_dates': [current_date + relativedelta(months=1)], 'due_dates': [current_date + relativedelta(months=1)],
'is_active': True 'is_active': True,
'establishment': establishment
} }
) )
@ -31,7 +33,8 @@ class Command(BaseCommand):
type=fee_type_value, type=fee_type_value,
defaults={ defaults={
'due_dates': [current_date + relativedelta(months=1+4*i) for i in range(3)], 'due_dates': [current_date + relativedelta(months=1+4*i) for i in range(3)],
'is_active': False 'is_active': False,
'establishment': establishment
} }
) )
@ -41,7 +44,8 @@ class Command(BaseCommand):
type=fee_type_value, type=fee_type_value,
defaults={ defaults={
'due_dates': [current_date + relativedelta(months=1+i) for i in range(10)], 'due_dates': [current_date + relativedelta(months=1+i) for i in range(10)],
'is_active': False 'is_active': False,
'establishment': establishment
} }
) )
@ -51,7 +55,8 @@ class Command(BaseCommand):
type=fee_type_value, type=fee_type_value,
defaults={ defaults={
'due_dates': [current_date + relativedelta(months=1+i) for i in range(12)], 'due_dates': [current_date + relativedelta(months=1+i) for i in range(12)],
'is_active': False 'is_active': False,
'establishment': establishment
} }
) )

View File

@ -1,6 +1,6 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from Auth.models import Profile from Auth.models import Profile
from School.models import Speciality, Teacher, SchoolClass from School.models import Speciality, Teacher, SchoolClass, Establishment
class Command(BaseCommand): class Command(BaseCommand):
help = 'Initialize or update Fees and Discounts' help = 'Initialize or update Fees and Discounts'
@ -108,6 +108,7 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Teachers initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Teachers initialized or updated successfully'))
def create_or_update_schoolClasses(self): def create_or_update_schoolClasses(self):
establishment = Establishment.objects.get(name="N3WT")
school_classes_data = [ school_classes_data = [
{ {
"atmosphere_name": "Classe A", "atmosphere_name": "Classe A",
@ -119,7 +120,8 @@ class Command(BaseCommand):
"type": 1, "type": 1,
"time_range": ["08:30", "17:30"], "time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5], "opening_days": [1, 2, 4, 5],
"teachers": [2] # ID of Severus Rogue "teachers": [2], # ID of Severus Rogue
"establishment": establishment
}, },
{ {
"atmosphere_name": "Classe B", "atmosphere_name": "Classe B",
@ -131,7 +133,8 @@ class Command(BaseCommand):
"type": 1, "type": 1,
"time_range": ["08:30", "17:30"], "time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5], "opening_days": [1, 2, 4, 5],
"teachers": [3] # ID of Minerva McGonagall "teachers": [3], # ID of Minerva McGonagall
"establishment": establishment
}, },
{ {
"atmosphere_name": "Classe C", "atmosphere_name": "Classe C",
@ -143,7 +146,8 @@ class Command(BaseCommand):
"type": 1, "type": 1,
"time_range": ["08:30", "17:30"], "time_range": ["08:30", "17:30"],
"opening_days": [1, 2, 4, 5], "opening_days": [1, 2, 4, 5],
"teachers": [4] # ID of Pomona Chourave "teachers": [4], # ID of Pomona Chourave
"establishment": establishment
} }
] ]

View File

@ -1,6 +1,6 @@
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from Auth.models import Profile from Auth.models import Profile
from School.models import Fee, Discount, FeeType, DiscountType from School.models import Fee, Discount, FeeType, DiscountType, Establishment
class Command(BaseCommand): class Command(BaseCommand):
help = 'Initialize or update Fees and Discounts' help = 'Initialize or update Fees and Discounts'
@ -10,41 +10,47 @@ class Command(BaseCommand):
self.create_or_update_discounts() self.create_or_update_discounts()
def create_or_update_fees(self): def create_or_update_fees(self):
establishment = Establishment.objects.get(name="N3WT")
fees_data = [ fees_data = [
{ {
"name": "Frais d'inscription", "name": "Frais d'inscription",
"base_amount": "150.00", "base_amount": "150.00",
"description": "Montant de base", "description": "Montant de base",
"is_active": True, "is_active": True,
"type": FeeType.REGISTRATION_FEE "type": FeeType.REGISTRATION_FEE,
"establishment": establishment
}, },
{ {
"name": "Matériel", "name": "Matériel",
"base_amount": "85.00", "base_amount": "85.00",
"description": "Livres / jouets", "description": "Livres / jouets",
"is_active": True, "is_active": True,
"type": FeeType.REGISTRATION_FEE "type": FeeType.REGISTRATION_FEE,
"establishment": establishment
}, },
{ {
"name": "Sorties périscolaires", "name": "Sorties périscolaires",
"base_amount": "120.00", "base_amount": "120.00",
"description": "Sorties", "description": "Sorties",
"is_active": True, "is_active": True,
"type": FeeType.REGISTRATION_FEE "type": FeeType.REGISTRATION_FEE,
"establishment": establishment
}, },
{ {
"name": "Les colibris", "name": "Les colibris",
"base_amount": "4500.00", "base_amount": "4500.00",
"description": "TPS / PS / MS / GS", "description": "TPS / PS / MS / GS",
"is_active": True, "is_active": True,
"type": FeeType.TUITION_FEE "type": FeeType.TUITION_FEE,
"establishment": establishment
}, },
{ {
"name": "Les butterflies", "name": "Les butterflies",
"base_amount": "5000.00", "base_amount": "5000.00",
"description": "CP / CE1 / CE2 / CM1 / CM2", "description": "CP / CE1 / CE2 / CM1 / CM2",
"is_active": True, "is_active": True,
"type": FeeType.TUITION_FEE "type": FeeType.TUITION_FEE,
"establishment": establishment
} }
] ]
@ -58,20 +64,23 @@ class Command(BaseCommand):
self.stdout.write(self.style.SUCCESS('Fees initialized or updated successfully')) self.stdout.write(self.style.SUCCESS('Fees initialized or updated successfully'))
def create_or_update_discounts(self): def create_or_update_discounts(self):
establishment = Establishment.objects.get(name="N3WT")
discounts_data = [ discounts_data = [
{ {
"name": "Parrainage", "name": "Parrainage",
"amount": "10.00", "amount": "10.00",
"description": "Réduction pour parrainage", "description": "Réduction pour parrainage",
"discount_type": DiscountType.PERCENT, "discount_type": DiscountType.PERCENT,
"type": FeeType.TUITION_FEE "type": FeeType.TUITION_FEE,
"establishment": establishment
}, },
{ {
"name": "Réinscription", "name": "Réinscription",
"amount": "100.00", "amount": "100.00",
"description": "Réduction pour Réinscription", "description": "Réduction pour Réinscription",
"discount_type": DiscountType.PERCENT, "discount_type": DiscountType.PERCENT,
"type": FeeType.REGISTRATION_FEE "type": FeeType.REGISTRATION_FEE,
"establishment": establishment
} }
] ]

View File

@ -6,7 +6,6 @@ from django.contrib.postgres.fields import ArrayField
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
LEVEL_CHOICES = [ LEVEL_CHOICES = [
(1, 'Très Petite Section (TPS)'), (1, 'Très Petite Section (TPS)'),
(2, 'Petite Section (PS)'), (2, 'Petite Section (PS)'),
@ -19,6 +18,23 @@ LEVEL_CHOICES = [
(9, 'Cours Moyen 2 (CM2)') (9, 'Cours Moyen 2 (CM2)')
] ]
class StructureType(models.IntegerChoices):
MATERNELLE = 1, _('Maternelle')
PRIMAIRE = 2, _('Primaire')
SECONDAIRE = 3, _('Secondaire')
class Establishment(models.Model):
name = models.CharField(max_length=255, unique=True)
address = models.CharField(max_length=255)
total_capacity = models.IntegerField()
establishment_type = ArrayField(models.IntegerField(choices=StructureType.choices))
licence_code = models.CharField(max_length=100, blank=True)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Speciality(models.Model): class Speciality(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
updated_date = models.DateTimeField(auto_now=True) updated_date = models.DateTimeField(auto_now=True)
@ -56,6 +72,7 @@ class SchoolClass(models.Model):
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1) type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
time_range = models.JSONField(default=list) time_range = models.JSONField(default=list)
opening_days = ArrayField(models.IntegerField(), default=list) opening_days = ArrayField(models.IntegerField(), default=list)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='school_classes')
def __str__(self): def __str__(self):
return self.atmosphere_name return self.atmosphere_name
@ -95,6 +112,7 @@ class Discount(models.Model):
discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY) discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE) type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='discounts')
def __str__(self): def __str__(self):
return self.name return self.name
@ -106,6 +124,7 @@ class Fee(models.Model):
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE) type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='fees')
def __str__(self): def __str__(self):
return self.name return self.name
@ -115,6 +134,7 @@ class PaymentPlan(models.Model):
due_dates = ArrayField(models.DateField(), blank=True) due_dates = ArrayField(models.DateField(), blank=True)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE) type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
is_active = models.BooleanField(default=False) is_active = models.BooleanField(default=False)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_plans')
def __str__(self): def __str__(self):
return f"{self.get_frequency_display()} - {self.get_type_display()}" return f"{self.get_frequency_display()} - {self.get_type_display()}"
@ -123,6 +143,7 @@ class PaymentMode(models.Model):
mode = models.IntegerField(choices=PaymentModeType.choices, default=PaymentModeType.SEPA) mode = models.IntegerField(choices=PaymentModeType.choices, default=PaymentModeType.SEPA)
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE) type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
is_active = models.BooleanField(default=False) is_active = models.BooleanField(default=False)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_modes')
def __str__(self): def __str__(self):
return f"{self.get_mode_display()} - {self.get_type_display()}" return f"{self.get_mode_display()} - {self.get_type_display()}"

View File

@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, Fee, PaymentPlan, PaymentMode from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, Fee, PaymentPlan, PaymentMode, Establishment
from Auth.models import Profile from Auth.models import Profile
from N3wtSchool import settings, bdd from N3wtSchool import settings, bdd
from django.utils import timezone from django.utils import timezone
@ -200,4 +200,9 @@ class PaymentPlanSerializer(serializers.ModelSerializer):
class PaymentModeSerializer(serializers.ModelSerializer): class PaymentModeSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = PaymentMode model = PaymentMode
fields = '__all__'
class EstablishmentSerializer(serializers.ModelSerializer):
class Meta:
model = Establishment
fields = '__all__' fields = '__all__'

View File

@ -16,7 +16,9 @@ from School.views import (
PaymentPlansView, PaymentPlansView,
PaymentPlanView, PaymentPlanView,
PaymentModesView, PaymentModesView,
PaymentModeView PaymentModeView,
EstablishmentsView,
EstablishmentView
) )
urlpatterns = [ urlpatterns = [
@ -51,4 +53,9 @@ urlpatterns = [
re_path(r'^paymentModes/(?P<_filter>[a-zA-z]+)$', PaymentModesView.as_view(), name="paymentModes"), re_path(r'^paymentModes/(?P<_filter>[a-zA-z]+)$', PaymentModesView.as_view(), name="paymentModes"),
re_path(r'^paymentMode$', PaymentModeView.as_view(), name="paymentMode"), re_path(r'^paymentMode$', PaymentModeView.as_view(), name="paymentMode"),
re_path(r'^paymentMode/([0-9]+)$', PaymentModeView.as_view(), name="paymentMode"), re_path(r'^paymentMode/([0-9]+)$', PaymentModeView.as_view(), name="paymentMode"),
re_path(r'^establishments$', EstablishmentsView.as_view(), name="establishments"),
re_path(r'^establishment$', EstablishmentView.as_view(), name='establishment'),
re_path(r'^establishment/([0-9]+)$', EstablishmentView.as_view(), name='establishment')
] ]

View File

@ -5,8 +5,8 @@ from rest_framework.parsers import JSONParser
from rest_framework.views import APIView from rest_framework.views import APIView
from django.core.cache import cache from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee, PaymentPlan, PaymentMode from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee, PaymentPlan, PaymentMode, Establishment
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer, PaymentPlanSerializer, PaymentModeSerializer from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer, PaymentPlanSerializer, PaymentModeSerializer, EstablishmentSerializer
from N3wtSchool import bdd from N3wtSchool import bdd
from N3wtSchool.bdd import delete_object, getAllObjects, getObject from N3wtSchool.bdd import delete_object, getAllObjects, getObject
@ -400,4 +400,46 @@ class PaymentModeView(APIView):
if payment_mode_serializer.is_valid(): if payment_mode_serializer.is_valid():
payment_mode_serializer.save() payment_mode_serializer.save()
return JsonResponse(payment_mode_serializer.data, safe=False) return JsonResponse(payment_mode_serializer.data, safe=False)
return JsonResponse(payment_mode_serializer.errors, safe=False, status=400) return JsonResponse(payment_mode_serializer.errors, safe=False, status=400)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class EstablishmentsView(APIView):
def get(self, request):
establishments=getAllObjects(Establishment)
establishments_serializer=EstablishmentSerializer(establishments, many=True)
return JsonResponse(establishments_serializer.data, safe=False, status=200)
@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class EstablishmentView(APIView):
def get(self, request, _id):
try:
establishment = Establishment.objects.get(id=_id)
establishment_serializer = EstablishmentSerializer(establishment)
return JsonResponse(establishment_serializer.data, safe=False)
except Establishment.DoesNotExist:
return JsonResponse({'error': 'No object found'}, status=404)
def post(self, request):
establishment_data = JSONParser().parse(request)
establishment_serializer = EstablishmentSerializer(data=establishment_data)
if establishment_serializer.is_valid():
establishment_serializer.save()
return JsonResponse(establishment_serializer.data, safe=False, status=201)
return JsonResponse(establishment_serializer.errors, safe=False, status=400)
def put(self, request, _id):
establishment_data = JSONParser().parse(request)
try:
establishment = Establishment.objects.get(id=_id)
except Establishment.DoesNotExist:
return JsonResponse({'error': 'No object found'}, status=404)
establishment_serializer = EstablishmentSerializer(establishment, data=establishment_data, partial=True)
if establishment_serializer.is_valid():
establishment_serializer.save()
return JsonResponse(establishment_serializer.data, safe=False)
return JsonResponse(establishment_serializer.errors, safe=False, status=400)
def delete(self, request, _id):
return delete_object(Establishment, _id)

View File

@ -4,7 +4,7 @@ from django.conf import settings
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from Auth.models import Profile from Auth.models import Profile
from School.models import SchoolClass, Fee, Discount from School.models import SchoolClass, Fee, Discount, Establishment
from datetime import datetime from datetime import datetime
@ -209,6 +209,8 @@ class RegistrationForm(models.Model):
null=True, null=True,
blank=True) blank=True)
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='register_forms')
def __str__(self): def __str__(self):
return "RF_" + self.student.last_name + "_" + self.student.first_name return "RF_" + self.student.last_name + "_" + self.student.first_name

View File

@ -20,14 +20,15 @@ commands = [
["python", "manage.py", "makemigrations", "GestionMessagerie", "--noinput"], ["python", "manage.py", "makemigrations", "GestionMessagerie", "--noinput"],
["python", "manage.py", "makemigrations", "Auth", "--noinput"], ["python", "manage.py", "makemigrations", "Auth", "--noinput"],
["python", "manage.py", "makemigrations", "School", "--noinput"], ["python", "manage.py", "makemigrations", "School", "--noinput"],
["python", "manage.py", "migrate", "--noinput"], ["python", "manage.py", "migrate", "--noinput"]
["python", "manage.py", "init_payment_plans"],
["python", "manage.py", "init_payment_modes"]
] ]
test_commands = [ test_commands = [
["python", "manage.py", "init_establishment"],
["python", "manage.py", "init_school_configuration"], ["python", "manage.py", "init_school_configuration"],
["python", "manage.py", "init_school_fees"] ["python", "manage.py", "init_school_fees"],
["python", "manage.py", "init_payment_plans"],
["python", "manage.py", "init_payment_modes"]
] ]
for command in commands: for command in commands:

View File

@ -1,6 +1,6 @@
'use client' 'use client'
// src/components/Layout.js // src/components/Layout.js
import React from 'react'; import React, { useState, useEffect } from 'react';
import Sidebar from '@/components/Sidebar'; import Sidebar from '@/components/Sidebar';
import { usePathname } from 'next/navigation'; import { usePathname } from 'next/navigation';
import {useTranslations} from 'next-intl'; import {useTranslations} from 'next-intl';
@ -25,6 +25,7 @@ import {
} from '@/utils/Url'; } from '@/utils/Url';
import { disconnect } from '@/app/lib/authAction'; import { disconnect } from '@/app/lib/authAction';
import { fetchEstablishment } from '@/app/lib/schoolAction';
export default function Layout({ export default function Layout({
children, children,
@ -40,6 +41,9 @@ export default function Layout({
"settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings } "settings": { "id": "settings", "name": t('settings'), "url": FE_ADMIN_SETTINGS_URL, "icon": Settings }
}; };
const [establishment, setEstablishment] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const pathname = usePathname(); const pathname = usePathname();
const currentPage = pathname.split('/').pop(); const currentPage = pathname.split('/').pop();
@ -57,38 +61,50 @@ export default function Layout({
}, },
]; ];
useEffect(() => {
setIsLoading(true);
fetchEstablishment()
.then(data => {
setEstablishment(data);
})
.catch(error => console.error('Error fetching establishment : ', error))
.finally(() => setIsLoading(false));
}, []);
return ( return (
<> <>
<div className="flex min-h-screen bg-gray-50"> {!isLoading && (
<Sidebar currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" /> <div className="flex min-h-screen bg-gray-50">
<div className="flex flex-col flex-1"> <Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
{/* Header - h-16 = 64px */} <div className="flex flex-col flex-1">
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9"> {/* Header - h-16 = 64px */}
<div className="text-xl font-semibold">{headerTitle}</div> <header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
<DropdownMenu <div className="text-xl font-semibold">{headerTitle}</div>
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />} <DropdownMenu
items={dropdownItems} buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
buttonClassName="" items={dropdownItems}
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg" buttonClassName=""
/> menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
</header> />
{/* Main Content */} </header>
<div className="flex-1 flex flex-col"> {/* Main Content */}
{/* Content avec scroll si nécessaire */} <div className="flex-1 flex flex-col">
<div className="flex-1 overflow-auto"> {/* Content avec scroll si nécessaire */}
{children} <div className="flex-1 overflow-auto">
</div> {children}
{/* Footer - h-16 = 64px */}
<footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
<div className="text-sm font-light">
<span>&copy; {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
</div> </div>
<Logo className="w-8 h-8" /> {/* Footer - h-16 = 64px */}
</footer> <footer className="h-16 bg-white border-t border-gray-200 px-8 py-4 flex items-center justify-between">
<div className="text-sm font-light">
<span>&copy; {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
</div>
<Logo className="w-8 h-8" />
</footer>
</div>
</div> </div>
</div> </div>
</div> )}
</> </>
); );
} }

View File

@ -6,7 +6,9 @@ import {
BE_SCHOOL_FEES_URL, BE_SCHOOL_FEES_URL,
BE_SCHOOL_DISCOUNTS_URL, BE_SCHOOL_DISCOUNTS_URL,
BE_SCHOOL_PAYMENT_PLANS_URL, BE_SCHOOL_PAYMENT_PLANS_URL,
BE_SCHOOL_PAYMENT_MODES_URL BE_SCHOOL_PAYMENT_MODES_URL,
BE_SCHOOL_ESTABLISHMENT_URL,
ESTABLISHMENT_ID
} from '@/utils/Url'; } from '@/utils/Url';
const requestResponseHandler = async (response) => { const requestResponseHandler = async (response) => {
@ -82,6 +84,11 @@ export const fetchTuitionPaymentModes = () => {
.then(requestResponseHandler) .then(requestResponseHandler)
} }
export const fetchEstablishment = () => {
return fetch(`${BE_SCHOOL_ESTABLISHMENT_URL}/${ESTABLISHMENT_ID}`)
.then(requestResponseHandler)
}
export const createDatas = (url, newData, csrfToken) => { export const createDatas = (url, newData, csrfToken) => {
return fetch(url, { return fetch(url, {
method: 'POST', method: 'POST',

View File

@ -14,7 +14,7 @@ const SidebarItem = ({ icon: Icon, text, active, url, onClick }) => (
</div> </div>
); );
function Sidebar({ currentPage, items }) { function Sidebar({ establishment, currentPage, items }) {
const router = useRouter(); const router = useRouter();
const [selectedItem, setSelectedItem] = useState(currentPage); const [selectedItem, setSelectedItem] = useState(currentPage);
@ -31,7 +31,7 @@ function Sidebar({ currentPage, items }) {
{/* Sidebar */} {/* Sidebar */}
<div className="w-64 bg-white border-r border-gray-200 py-6 px-4"> <div className="w-64 bg-white border-r border-gray-200 py-6 px-4">
<div className="flex items-center mb-8 px-2"> <div className="flex items-center mb-8 px-2">
<div className="text-xl font-semibold">Ecole NEWT</div> <div className="text-xl font-semibold">{establishment?.name}</div>
</div> </div>
<nav className="space-y-1"> <nav className="space-y-1">

View File

@ -41,6 +41,10 @@ export const BE_SCHOOL_PAYMENT_PLAN_URL = `${BASE_URL}/School/paymentPlan`;
export const BE_SCHOOL_PAYMENT_PLANS_URL = `${BASE_URL}/School/paymentPlans`; export const BE_SCHOOL_PAYMENT_PLANS_URL = `${BASE_URL}/School/paymentPlans`;
export const BE_SCHOOL_PAYMENT_MODE_URL = `${BASE_URL}/School/paymentMode`; export const BE_SCHOOL_PAYMENT_MODE_URL = `${BASE_URL}/School/paymentMode`;
export const BE_SCHOOL_PAYMENT_MODES_URL = `${BASE_URL}/School/paymentModes`; export const BE_SCHOOL_PAYMENT_MODES_URL = `${BASE_URL}/School/paymentModes`;
export const BE_SCHOOL_ESTABLISHMENT_URL = `${BASE_URL}/School/establishment`;
// En attendant la gestion des sessions
export const ESTABLISHMENT_ID = 1;
// GESTION MESSAGERIE // GESTION MESSAGERIE
export const BE_GESTIONMESSAGERIE_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messages` export const BE_GESTIONMESSAGERIE_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messages`

View File

@ -1,62 +0,0 @@
# N3wt School
Logiciel de gestion d'école
## Maquette
Maquette figma : https://www.figma.com/design/1BtWHIQlJDTeue2oYblefV/Maquette-Logiciel-de-gestion-Ecole?node-id=42-296&t=AdaSQYWkLLf1o5OI-0
## Installation
### Installation de docker
Lien de téléchargement : https://www.docker.com/get-started/
# Lancement de monteschool
```sh
docker compose up -d
```
Lancement du front end
```sh
npm run dev
```
se connecter à localhost:8080
# Installation et développement en local
* [Installation Manuelle](./docs/Installation_Manuelle.md)
* [Convention de codage](./docs/CODING_GUIDELINES.md)
# Installer la vérification de commit (dans le projet principal)
```
npm i
npm run prepare
```
# Faire une livraison Mise en Production
```sh
# Faire la première release (1.0.0)
npm run release -- --first-release
# Faire une prerelease (RC,alpha,beta)
npm run release -- --prerelease <name>
# Faire une release
npm run release
# Forcer la release sur un mode particulier (majeur, mineur ou patch)
# npm run script
npm run release -- --release-as minor
# Or
npm run release -- --release-as 1.1.0
# ignorer les hooks de commit lors de la release
npm run release -- --no-verify
```

View File

@ -1,20 +0,0 @@
{
"name": "n3wt-school",
"version": "0.0.1",
"scripts": {
"prepare": "husky",
"release": "standard-version",
"update-version": "node scripts/update-version.js"
},
"standard-version": {
"scripts": {
"postbump": "git add Front-End/package.json Back-End/__version__.py && git commit --amend --no-edit"
}
},
"devDependencies": {
"@commitlint/cli": "^19.5.0",
"@commitlint/config-conventional": "^19.5.0",
"husky": "^9.1.6",
"standard-version": "^9.5.0"
}
}