mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
chore: commit qui sert à rien
This commit is contained in:
24
Back-End/School/management/commands/init_establishment.py
Normal file
24
Back-End/School/management/commands/init_establishment.py
Normal 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'))
|
||||
@ -1,5 +1,5 @@
|
||||
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):
|
||||
help = 'Initialize or update Payment Modes'
|
||||
@ -8,6 +8,7 @@ class Command(BaseCommand):
|
||||
self.create_or_update_payment_modes()
|
||||
|
||||
def create_or_update_payment_modes(self):
|
||||
establishment = Establishment.objects.get(name="N3WT")
|
||||
for fee_type in FeeType.choices:
|
||||
fee_type_value = fee_type[0]
|
||||
|
||||
@ -18,7 +19,8 @@ class Command(BaseCommand):
|
||||
mode=mode_value,
|
||||
type=fee_type_value,
|
||||
defaults={
|
||||
'is_active': False
|
||||
'is_active': False,
|
||||
'establishment': establishment
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from School.models import PaymentPlan, PaymentPlanType, FeeType
|
||||
from School.models import PaymentPlan, PaymentPlanType, FeeType, Establishment
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Initialize or update Payment Plans'
|
||||
@ -11,6 +11,7 @@ class Command(BaseCommand):
|
||||
|
||||
def create_or_update_payment_plans(self):
|
||||
current_date = timezone.now().date()
|
||||
establishment = Establishment.objects.get(name="N3WT")
|
||||
|
||||
for fee_type in FeeType.choices:
|
||||
fee_type_value = fee_type[0]
|
||||
@ -21,7 +22,8 @@ class Command(BaseCommand):
|
||||
type=fee_type_value,
|
||||
defaults={
|
||||
'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,
|
||||
defaults={
|
||||
'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,
|
||||
defaults={
|
||||
'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,
|
||||
defaults={
|
||||
'due_dates': [current_date + relativedelta(months=1+i) for i in range(12)],
|
||||
'is_active': False
|
||||
'is_active': False,
|
||||
'establishment': establishment
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
from Auth.models import Profile
|
||||
from School.models import Speciality, Teacher, SchoolClass
|
||||
from School.models import Speciality, Teacher, SchoolClass, Establishment
|
||||
|
||||
class Command(BaseCommand):
|
||||
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'))
|
||||
|
||||
def create_or_update_schoolClasses(self):
|
||||
establishment = Establishment.objects.get(name="N3WT")
|
||||
school_classes_data = [
|
||||
{
|
||||
"atmosphere_name": "Classe A",
|
||||
@ -119,7 +120,8 @@ class Command(BaseCommand):
|
||||
"type": 1,
|
||||
"time_range": ["08:30", "17:30"],
|
||||
"opening_days": [1, 2, 4, 5],
|
||||
"teachers": [2] # ID of Severus Rogue
|
||||
"teachers": [2], # ID of Severus Rogue
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"atmosphere_name": "Classe B",
|
||||
@ -131,7 +133,8 @@ class Command(BaseCommand):
|
||||
"type": 1,
|
||||
"time_range": ["08:30", "17:30"],
|
||||
"opening_days": [1, 2, 4, 5],
|
||||
"teachers": [3] # ID of Minerva McGonagall
|
||||
"teachers": [3], # ID of Minerva McGonagall
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"atmosphere_name": "Classe C",
|
||||
@ -143,7 +146,8 @@ class Command(BaseCommand):
|
||||
"type": 1,
|
||||
"time_range": ["08:30", "17:30"],
|
||||
"opening_days": [1, 2, 4, 5],
|
||||
"teachers": [4] # ID of Pomona Chourave
|
||||
"teachers": [4], # ID of Pomona Chourave
|
||||
"establishment": establishment
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from django.core.management.base import BaseCommand
|
||||
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):
|
||||
help = 'Initialize or update Fees and Discounts'
|
||||
@ -10,41 +10,47 @@ class Command(BaseCommand):
|
||||
self.create_or_update_discounts()
|
||||
|
||||
def create_or_update_fees(self):
|
||||
establishment = Establishment.objects.get(name="N3WT")
|
||||
fees_data = [
|
||||
{
|
||||
"name": "Frais d'inscription",
|
||||
"base_amount": "150.00",
|
||||
"description": "Montant de base",
|
||||
"is_active": True,
|
||||
"type": FeeType.REGISTRATION_FEE
|
||||
"type": FeeType.REGISTRATION_FEE,
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"name": "Matériel",
|
||||
"base_amount": "85.00",
|
||||
"description": "Livres / jouets",
|
||||
"is_active": True,
|
||||
"type": FeeType.REGISTRATION_FEE
|
||||
"type": FeeType.REGISTRATION_FEE,
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"name": "Sorties périscolaires",
|
||||
"base_amount": "120.00",
|
||||
"description": "Sorties",
|
||||
"is_active": True,
|
||||
"type": FeeType.REGISTRATION_FEE
|
||||
"type": FeeType.REGISTRATION_FEE,
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"name": "Les colibris",
|
||||
"base_amount": "4500.00",
|
||||
"description": "TPS / PS / MS / GS",
|
||||
"is_active": True,
|
||||
"type": FeeType.TUITION_FEE
|
||||
"type": FeeType.TUITION_FEE,
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"name": "Les butterflies",
|
||||
"base_amount": "5000.00",
|
||||
"description": "CP / CE1 / CE2 / CM1 / CM2",
|
||||
"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'))
|
||||
|
||||
def create_or_update_discounts(self):
|
||||
establishment = Establishment.objects.get(name="N3WT")
|
||||
discounts_data = [
|
||||
{
|
||||
"name": "Parrainage",
|
||||
"amount": "10.00",
|
||||
"description": "Réduction pour parrainage",
|
||||
"discount_type": DiscountType.PERCENT,
|
||||
"type": FeeType.TUITION_FEE
|
||||
"type": FeeType.TUITION_FEE,
|
||||
"establishment": establishment
|
||||
},
|
||||
{
|
||||
"name": "Réinscription",
|
||||
"amount": "100.00",
|
||||
"description": "Réduction pour Réinscription",
|
||||
"discount_type": DiscountType.PERCENT,
|
||||
"type": FeeType.REGISTRATION_FEE
|
||||
"type": FeeType.REGISTRATION_FEE,
|
||||
"establishment": establishment
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ from django.contrib.postgres.fields import ArrayField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
LEVEL_CHOICES = [
|
||||
(1, 'Très Petite Section (TPS)'),
|
||||
(2, 'Petite Section (PS)'),
|
||||
@ -19,6 +18,23 @@ LEVEL_CHOICES = [
|
||||
(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):
|
||||
name = models.CharField(max_length=100)
|
||||
updated_date = models.DateTimeField(auto_now=True)
|
||||
@ -56,6 +72,7 @@ class SchoolClass(models.Model):
|
||||
type = models.IntegerField(choices=PLANNING_TYPE_CHOICES, default=1)
|
||||
time_range = models.JSONField(default=list)
|
||||
opening_days = ArrayField(models.IntegerField(), default=list)
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='school_classes')
|
||||
|
||||
def __str__(self):
|
||||
return self.atmosphere_name
|
||||
@ -95,6 +112,7 @@ class Discount(models.Model):
|
||||
discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY)
|
||||
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='discounts')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -106,6 +124,7 @@ class Fee(models.Model):
|
||||
is_active = models.BooleanField(default=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='fees')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@ -115,6 +134,7 @@ class PaymentPlan(models.Model):
|
||||
due_dates = ArrayField(models.DateField(), blank=True)
|
||||
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
|
||||
is_active = models.BooleanField(default=False)
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_plans')
|
||||
|
||||
def __str__(self):
|
||||
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)
|
||||
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
|
||||
is_active = models.BooleanField(default=False)
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='payment_modes')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.get_mode_display()} - {self.get_type_display()}"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
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 N3wtSchool import settings, bdd
|
||||
from django.utils import timezone
|
||||
@ -201,3 +201,8 @@ class PaymentModeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = PaymentMode
|
||||
fields = '__all__'
|
||||
|
||||
class EstablishmentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Establishment
|
||||
fields = '__all__'
|
||||
@ -16,7 +16,9 @@ from School.views import (
|
||||
PaymentPlansView,
|
||||
PaymentPlanView,
|
||||
PaymentModesView,
|
||||
PaymentModeView
|
||||
PaymentModeView,
|
||||
EstablishmentsView,
|
||||
EstablishmentView
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@ -51,4 +53,9 @@ urlpatterns = [
|
||||
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/([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')
|
||||
|
||||
]
|
||||
@ -5,8 +5,8 @@ from rest_framework.parsers import JSONParser
|
||||
from rest_framework.views import APIView
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee, PaymentPlan, PaymentMode
|
||||
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer, PaymentPlanSerializer, PaymentModeSerializer
|
||||
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee, PaymentPlan, PaymentMode, Establishment
|
||||
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer, PaymentPlanSerializer, PaymentModeSerializer, EstablishmentSerializer
|
||||
from N3wtSchool import bdd
|
||||
from N3wtSchool.bdd import delete_object, getAllObjects, getObject
|
||||
|
||||
@ -401,3 +401,45 @@ class PaymentModeView(APIView):
|
||||
payment_mode_serializer.save()
|
||||
return JsonResponse(payment_mode_serializer.data, safe=False)
|
||||
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)
|
||||
@ -4,7 +4,7 @@ from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from Auth.models import Profile
|
||||
from School.models import SchoolClass, Fee, Discount
|
||||
from School.models import SchoolClass, Fee, Discount, Establishment
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
@ -209,6 +209,8 @@ class RegistrationForm(models.Model):
|
||||
null=True,
|
||||
blank=True)
|
||||
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.CASCADE, related_name='register_forms')
|
||||
|
||||
def __str__(self):
|
||||
return "RF_" + self.student.last_name + "_" + self.student.first_name
|
||||
|
||||
|
||||
@ -20,14 +20,15 @@ commands = [
|
||||
["python", "manage.py", "makemigrations", "GestionMessagerie", "--noinput"],
|
||||
["python", "manage.py", "makemigrations", "Auth", "--noinput"],
|
||||
["python", "manage.py", "makemigrations", "School", "--noinput"],
|
||||
["python", "manage.py", "migrate", "--noinput"],
|
||||
["python", "manage.py", "init_payment_plans"],
|
||||
["python", "manage.py", "init_payment_modes"]
|
||||
["python", "manage.py", "migrate", "--noinput"]
|
||||
]
|
||||
|
||||
test_commands = [
|
||||
["python", "manage.py", "init_establishment"],
|
||||
["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:
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
// src/components/Layout.js
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import Sidebar from '@/components/Sidebar';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import {useTranslations} from 'next-intl';
|
||||
@ -25,6 +25,7 @@ import {
|
||||
} from '@/utils/Url';
|
||||
|
||||
import { disconnect } from '@/app/lib/authAction';
|
||||
import { fetchEstablishment } from '@/app/lib/schoolAction';
|
||||
|
||||
export default function Layout({
|
||||
children,
|
||||
@ -40,6 +41,9 @@ export default function Layout({
|
||||
"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 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 (
|
||||
<>
|
||||
<div className="flex min-h-screen bg-gray-50">
|
||||
<Sidebar currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
||||
<div className="flex flex-col flex-1">
|
||||
{/* Header - h-16 = 64px */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||
<DropdownMenu
|
||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
||||
items={dropdownItems}
|
||||
buttonClassName=""
|
||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||
/>
|
||||
</header>
|
||||
{/* Main Content */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* Content avec scroll si nécessaire */}
|
||||
<div className="flex-1 overflow-auto">
|
||||
{children}
|
||||
</div>
|
||||
{/* 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>© {new Date().getFullYear()} N3WT-INNOV Tous droits réservés.</span>
|
||||
<div className="text-sm font-light">{softwareName} - {softwareVersion}</div>
|
||||
{!isLoading && (
|
||||
<div className="flex min-h-screen bg-gray-50">
|
||||
<Sidebar establishment={establishment} currentPage={currentPage} items={Object.values(sidebarItems)} className="h-full" />
|
||||
<div className="flex flex-col flex-1">
|
||||
{/* Header - h-16 = 64px */}
|
||||
<header className="h-16 bg-white border-b border-gray-200 px-8 py-4 flex items-center justify-between z-9">
|
||||
<div className="text-xl font-semibold">{headerTitle}</div>
|
||||
<DropdownMenu
|
||||
buttonContent={<img src="https://i.pravatar.cc/32" alt="Profile" className="w-8 h-8 rounded-full cursor-pointer" />}
|
||||
items={dropdownItems}
|
||||
buttonClassName=""
|
||||
menuClassName="absolute right-0 mt-2 w-48 bg-white border border-gray-200 rounded shadow-lg"
|
||||
/>
|
||||
</header>
|
||||
{/* Main Content */}
|
||||
<div className="flex-1 flex flex-col">
|
||||
{/* Content avec scroll si nécessaire */}
|
||||
<div className="flex-1 overflow-auto">
|
||||
{children}
|
||||
</div>
|
||||
<Logo className="w-8 h-8" />
|
||||
</footer>
|
||||
{/* 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>© {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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -6,7 +6,9 @@ import {
|
||||
BE_SCHOOL_FEES_URL,
|
||||
BE_SCHOOL_DISCOUNTS_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';
|
||||
|
||||
const requestResponseHandler = async (response) => {
|
||||
@ -82,6 +84,11 @@ export const fetchTuitionPaymentModes = () => {
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const fetchEstablishment = () => {
|
||||
return fetch(`${BE_SCHOOL_ESTABLISHMENT_URL}/${ESTABLISHMENT_ID}`)
|
||||
.then(requestResponseHandler)
|
||||
}
|
||||
|
||||
export const createDatas = (url, newData, csrfToken) => {
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
|
||||
@ -14,7 +14,7 @@ const SidebarItem = ({ icon: Icon, text, active, url, onClick }) => (
|
||||
</div>
|
||||
);
|
||||
|
||||
function Sidebar({ currentPage, items }) {
|
||||
function Sidebar({ establishment, currentPage, items }) {
|
||||
const router = useRouter();
|
||||
const [selectedItem, setSelectedItem] = useState(currentPage);
|
||||
|
||||
@ -31,7 +31,7 @@ function Sidebar({ currentPage, items }) {
|
||||
{/* Sidebar */}
|
||||
<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="text-xl font-semibold">Ecole NEWT</div>
|
||||
<div className="text-xl font-semibold">{establishment?.name}</div>
|
||||
</div>
|
||||
|
||||
<nav className="space-y-1">
|
||||
|
||||
@ -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_MODE_URL = `${BASE_URL}/School/paymentMode`;
|
||||
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
|
||||
export const BE_GESTIONMESSAGERIE_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messages`
|
||||
|
||||
62
README.md
62
README.md
@ -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
|
||||
```
|
||||
|
||||
20
package.json
20
package.json
@ -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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user