mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
feat: Harmonisation des fees / ajout de type de réduction / mise à jour
du calcul [#18]
This commit is contained in:
@ -73,40 +73,33 @@ class PaymentOptions(models.IntegerChoices):
|
|||||||
FOUR_TIME_PAYMENT = 1, _('Paiement en 4 fois')
|
FOUR_TIME_PAYMENT = 1, _('Paiement en 4 fois')
|
||||||
TEN_TIME_PAYMENT = 2, _('Paiement en 10 fois')
|
TEN_TIME_PAYMENT = 2, _('Paiement en 10 fois')
|
||||||
|
|
||||||
|
class DiscountType(models.IntegerChoices):
|
||||||
|
CURRENCY = 0, 'Currency'
|
||||||
|
PERCENT = 1, 'Percent'
|
||||||
|
|
||||||
|
class FeeType(models.IntegerChoices):
|
||||||
|
REGISTRATION_FEE = 0, 'Registration Fee'
|
||||||
|
TUITION_FEE = 1, 'Tuition Fee'
|
||||||
|
|
||||||
class Discount(models.Model):
|
class Discount(models.Model):
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
amount = models.DecimalField(max_digits=10, decimal_places=2)
|
amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||||
description = models.TextField(blank=True)
|
description = models.TextField(blank=True)
|
||||||
|
discount_type = models.IntegerField(choices=DiscountType.choices, default=DiscountType.CURRENCY)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Fee(models.Model):
|
class Fee(models.Model):
|
||||||
name = models.CharField(max_length=255, unique=True)
|
name = models.CharField(max_length=255, unique=True)
|
||||||
description = models.TextField(blank=True)
|
|
||||||
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
||||||
currency = models.CharField(max_length=3, default='EUR')
|
description = models.TextField(blank=True)
|
||||||
|
payment_option = models.IntegerField(choices=PaymentOptions.choices, default=PaymentOptions.SINGLE_PAYMENT)
|
||||||
discounts = models.ManyToManyField('Discount', blank=True)
|
discounts = models.ManyToManyField('Discount', blank=True)
|
||||||
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
|
|
||||||
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)
|
||||||
|
currency = models.CharField(max_length=3, default='EUR')
|
||||||
|
type = models.IntegerField(choices=FeeType.choices, default=FeeType.REGISTRATION_FEE)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class TuitionFee(models.Model):
|
|
||||||
name = models.CharField(max_length=255, unique=True)
|
|
||||||
description = models.TextField(blank=True)
|
|
||||||
base_amount = models.DecimalField(max_digits=10, decimal_places=2, default=0)
|
|
||||||
currency = models.CharField(max_length=3, default='EUR')
|
|
||||||
discounts = models.ManyToManyField('Discount', blank=True)
|
|
||||||
payment_option = models.IntegerField(choices=PaymentOptions, default=PaymentOptions.SINGLE_PAYMENT)
|
|
||||||
is_active = models.BooleanField(default=True)
|
|
||||||
updated_at = models.DateTimeField(auto_now=True)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def clean(self):
|
|
||||||
if self.validity_end_date <= self.validity_start_date:
|
|
||||||
raise ValidationError(_('La date de fin de validité doit être après la date de début de validité.'))
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, TuitionFee, Fee
|
from .models import Teacher, Speciality, SchoolClass, Planning, LEVEL_CHOICES, Discount, Fee
|
||||||
from Subscriptions.models import RegistrationForm
|
from Subscriptions.models import RegistrationForm
|
||||||
from Subscriptions.serializers import StudentSerializer
|
from Subscriptions.serializers import StudentSerializer
|
||||||
from Auth.serializers import ProfileSerializer
|
from Auth.serializers import ProfileSerializer
|
||||||
@ -208,42 +208,7 @@ class FeeSerializer(serializers.ModelSerializer):
|
|||||||
instance.payment_option = validated_data.get('payment_option', instance.payment_option)
|
instance.payment_option = validated_data.get('payment_option', instance.payment_option)
|
||||||
instance.is_active = validated_data.get('is_active', instance.is_active)
|
instance.is_active = validated_data.get('is_active', instance.is_active)
|
||||||
instance.updated_at = validated_data.get('updated_at', instance.updated_at)
|
instance.updated_at = validated_data.get('updated_at', instance.updated_at)
|
||||||
instance.save()
|
instance.type = validated_data.get('type', instance.type)
|
||||||
|
|
||||||
# Update discounts if provided
|
|
||||||
instance.discounts.set(discounts_data)
|
|
||||||
|
|
||||||
return instance
|
|
||||||
|
|
||||||
class TuitionFeeSerializer(serializers.ModelSerializer):
|
|
||||||
discounts = serializers.PrimaryKeyRelatedField(queryset=Discount.objects.all(), many=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = TuitionFee
|
|
||||||
fields = '__all__'
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
discounts_data = validated_data.pop('discounts', [])
|
|
||||||
|
|
||||||
# Create the TuitionFee instance
|
|
||||||
tuition_fee = TuitionFee.objects.create(**validated_data)
|
|
||||||
|
|
||||||
# Add discounts if provided
|
|
||||||
tuition_fee.discounts.set(discounts_data)
|
|
||||||
|
|
||||||
return tuition_fee
|
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
|
||||||
discounts_data = validated_data.pop('discounts', [])
|
|
||||||
|
|
||||||
# Update the TuitionFee instance
|
|
||||||
instance.name = validated_data.get('name', instance.name)
|
|
||||||
instance.description = validated_data.get('description', instance.description)
|
|
||||||
instance.base_amount = validated_data.get('base_amount', instance.base_amount)
|
|
||||||
instance.currency = validated_data.get('currency', instance.currency)
|
|
||||||
instance.payment_option = validated_data.get('payment_option', instance.payment_option)
|
|
||||||
instance.is_active = validated_data.get('is_active', instance.is_active)
|
|
||||||
instance.updated_at = validated_data.get('updated_at', instance.updated_at)
|
|
||||||
instance.save()
|
instance.save()
|
||||||
|
|
||||||
# Update discounts if provided
|
# Update discounts if provided
|
||||||
|
|||||||
@ -11,8 +11,6 @@ from School.views import (
|
|||||||
PlanningView,
|
PlanningView,
|
||||||
FeesView,
|
FeesView,
|
||||||
FeeView,
|
FeeView,
|
||||||
TuitionFeesView,
|
|
||||||
TuitionFeeView,
|
|
||||||
DiscountsView,
|
DiscountsView,
|
||||||
DiscountView,
|
DiscountView,
|
||||||
)
|
)
|
||||||
@ -34,14 +32,10 @@ urlpatterns = [
|
|||||||
re_path(r'^planning$', PlanningView.as_view(), name="planning"),
|
re_path(r'^planning$', PlanningView.as_view(), name="planning"),
|
||||||
re_path(r'^planning/([0-9]+)$', PlanningView.as_view(), name="planning"),
|
re_path(r'^planning/([0-9]+)$', PlanningView.as_view(), name="planning"),
|
||||||
|
|
||||||
re_path(r'^fees$', FeesView.as_view(), name="fees"),
|
re_path(r'^fees/(?P<_filter>[a-zA-z]+)$', FeesView.as_view(), name="fees"),
|
||||||
re_path(r'^fee$', FeeView.as_view(), name="fee"),
|
re_path(r'^fee$', FeeView.as_view(), name="fee"),
|
||||||
re_path(r'^fee/([0-9]+)$', FeeView.as_view(), name="fee"),
|
re_path(r'^fee/([0-9]+)$', FeeView.as_view(), name="fee"),
|
||||||
|
|
||||||
re_path(r'^tuitionFees$', TuitionFeesView.as_view(), name="tuitionFees"),
|
|
||||||
re_path(r'^tuitionFee$', TuitionFeeView.as_view(), name="tuitionFee"),
|
|
||||||
re_path(r'^tuitionFee/([0-9]+)$', TuitionFeeView.as_view(), name="tuitionFee"),
|
|
||||||
|
|
||||||
re_path(r'^discounts$', DiscountsView.as_view(), name="discounts"),
|
re_path(r'^discounts$', DiscountsView.as_view(), name="discounts"),
|
||||||
re_path(r'^discount$', DiscountView.as_view(), name="discount"),
|
re_path(r'^discount$', DiscountView.as_view(), name="discount"),
|
||||||
re_path(r'^discount/([0-9]+)$', DiscountView.as_view(), name="discount"),
|
re_path(r'^discount/([0-9]+)$', DiscountView.as_view(), name="discount"),
|
||||||
|
|||||||
@ -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, TuitionFee, Fee
|
from .models import Teacher, Speciality, SchoolClass, Planning, Discount, Fee
|
||||||
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, TuitionFeeSerializer, FeeSerializer
|
from .serializers import TeacherSerializer, SpecialitySerializer, SchoolClassSerializer, PlanningSerializer, DiscountSerializer, FeeSerializer
|
||||||
from N3wtSchool import bdd
|
from N3wtSchool import bdd
|
||||||
from N3wtSchool.bdd import delete_object, getAllObjects, getObject
|
from N3wtSchool.bdd import delete_object, getAllObjects, getObject
|
||||||
|
|
||||||
@ -267,18 +267,16 @@ class PlanningView(APIView):
|
|||||||
@method_decorator(csrf_protect, name='dispatch')
|
@method_decorator(csrf_protect, name='dispatch')
|
||||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||||
class FeesView(APIView):
|
class FeesView(APIView):
|
||||||
def get(self, request):
|
def get(self, request, _filter, *args, **kwargs):
|
||||||
feesList = Fee.objects.all()
|
|
||||||
fees_serializer = FeeSerializer(feesList, many=True)
|
|
||||||
return JsonResponse(fees_serializer.data, safe=False)
|
|
||||||
|
|
||||||
def post(self, request):
|
if _filter not in ['registration', 'tuition']:
|
||||||
fee_data = JSONParser().parse(request)
|
return JsonResponse({"error": "Invalid type parameter. Must be 'registration' or 'tuition'."}, safe=False, status=400)
|
||||||
fee_serializer = FeeSerializer(data=fee_data)
|
|
||||||
if fee_serializer.is_valid():
|
fee_type_value = 0 if _filter == 'registration' else 1
|
||||||
fee_serializer.save()
|
fees = Fee.objects.filter(type=fee_type_value)
|
||||||
return JsonResponse(fee_serializer.data, safe=False, status=201)
|
fee_serializer = FeeSerializer(fees, many=True)
|
||||||
return JsonResponse(fee_serializer.errors, safe=False, status=400)
|
|
||||||
|
return JsonResponse(fee_serializer.data, safe=False, status=200)
|
||||||
|
|
||||||
@method_decorator(csrf_protect, name='dispatch')
|
@method_decorator(csrf_protect, name='dispatch')
|
||||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
||||||
@ -313,46 +311,3 @@ class FeeView(APIView):
|
|||||||
|
|
||||||
def delete(self, request, _id):
|
def delete(self, request, _id):
|
||||||
return delete_object(Fee, _id)
|
return delete_object(Fee, _id)
|
||||||
|
|
||||||
# Vues pour les frais de scolarité (TuitionFee)
|
|
||||||
@method_decorator(csrf_protect, name='dispatch')
|
|
||||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
|
||||||
class TuitionFeesView(APIView):
|
|
||||||
def get(self, request):
|
|
||||||
tuitionFeesList = TuitionFee.objects.all()
|
|
||||||
tuitionFees_serializer = TuitionFeeSerializer(tuitionFeesList, many=True)
|
|
||||||
return JsonResponse(tuitionFees_serializer.data, safe=False)
|
|
||||||
|
|
||||||
@method_decorator(csrf_protect, name='dispatch')
|
|
||||||
@method_decorator(ensure_csrf_cookie, name='dispatch')
|
|
||||||
class TuitionFeeView(APIView):
|
|
||||||
def get(self, request, _id):
|
|
||||||
try:
|
|
||||||
tuitionFee = TuitionFee.objects.get(id=_id)
|
|
||||||
tuitionFee_serializer = TuitionFeeSerializer(tuitionFee)
|
|
||||||
return JsonResponse(tuitionFee_serializer.data, safe=False)
|
|
||||||
except TuitionFee.DoesNotExist:
|
|
||||||
return JsonResponse({'error': 'No object found'}, status=404)
|
|
||||||
|
|
||||||
def post(self, request):
|
|
||||||
tuitionFee_data = JSONParser().parse(request)
|
|
||||||
tuitionFee_serializer = TuitionFeeSerializer(data=tuitionFee_data)
|
|
||||||
if tuitionFee_serializer.is_valid():
|
|
||||||
tuitionFee_serializer.save()
|
|
||||||
return JsonResponse(tuitionFee_serializer.data, safe=False, status=201)
|
|
||||||
return JsonResponse(tuitionFee_serializer.errors, safe=False, status=400)
|
|
||||||
|
|
||||||
def put(self, request, _id):
|
|
||||||
tuitionFee_data = JSONParser().parse(request)
|
|
||||||
try:
|
|
||||||
tuitionFee = TuitionFee.objects.get(id=_id)
|
|
||||||
except TuitionFee.DoesNotExist:
|
|
||||||
return JsonResponse({'error': 'No object found'}, status=404)
|
|
||||||
tuitionFee_serializer = TuitionFeeSerializer(tuitionFee, data=tuitionFee_data, partial=True) # Utilisation de partial=True
|
|
||||||
if tuitionFee_serializer.is_valid():
|
|
||||||
tuitionFee_serializer.save()
|
|
||||||
return JsonResponse(tuitionFee_serializer.data, safe=False)
|
|
||||||
return JsonResponse(tuitionFee_serializer.errors, safe=False, status=400)
|
|
||||||
|
|
||||||
def delete(self, request, _id):
|
|
||||||
return delete_object(TuitionFee, _id)
|
|
||||||
@ -1,20 +1,19 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { School, Calendar, DollarSign } from 'lucide-react'; // Import de l'icône DollarSign
|
|
||||||
import StructureManagement from '@/components/Structure/Configuration/StructureManagement';
|
import StructureManagement from '@/components/Structure/Configuration/StructureManagement';
|
||||||
import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement';
|
import ScheduleManagement from '@/components/Structure/Planning/ScheduleManagement';
|
||||||
import FeesManagement from '@/components/Structure/Configuration/FeesManagement';
|
import FeesManagement from '@/components/Structure/Configuration/FeesManagement';
|
||||||
import DjangoCSRFToken from '@/components/DjangoCSRFToken';
|
import DjangoCSRFToken from '@/components/DjangoCSRFToken';
|
||||||
import useCsrfToken from '@/hooks/useCsrfToken';
|
import useCsrfToken from '@/hooks/useCsrfToken';
|
||||||
import { ClassesProvider } from '@/context/ClassesContext';
|
import { ClassesProvider } from '@/context/ClassesContext';
|
||||||
import { fetchSpecialities, fetchTeachers, fetchClasses, fetchSchedules, fetchDiscounts, fetchFees, fetchTuitionFees } from '@/app/lib/schoolAction';
|
import { fetchSpecialities, fetchTeachers, fetchClasses, fetchSchedules, fetchDiscounts, fetchRegistrationFees, fetchTuitionFees } from '@/app/lib/schoolAction';
|
||||||
import SidebarTabs from '@/components/SidebarTabs';
|
import SidebarTabs from '@/components/SidebarTabs';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [specialities, setSpecialities] = useState([]);
|
const [specialities, setSpecialities] = useState([]);
|
||||||
const [classes, setClasses] = useState([]);
|
const [classes, setClasses] = useState([]);
|
||||||
const [teachers, setTeachers] = useState([]);
|
const [teachers, setTeachers] = useState([]);
|
||||||
const [fees, setFees] = useState([]);
|
const [registrationFees, setRegistrationFees] = useState([]);
|
||||||
const [discounts, setDiscounts] = useState([]);
|
const [discounts, setDiscounts] = useState([]);
|
||||||
const [tuitionFees, setTuitionFees] = useState([]);
|
const [tuitionFees, setTuitionFees] = useState([]);
|
||||||
|
|
||||||
@ -33,13 +32,13 @@ export default function Page() {
|
|||||||
// Fetch data for schedules
|
// Fetch data for schedules
|
||||||
handleSchedules();
|
handleSchedules();
|
||||||
|
|
||||||
// Fetch data for fees
|
|
||||||
handleFees();
|
|
||||||
|
|
||||||
// Fetch data for discounts
|
// Fetch data for discounts
|
||||||
handleDiscounts();
|
handleDiscounts();
|
||||||
|
|
||||||
// Fetch data for TuitionFee
|
// Fetch data for registration fees
|
||||||
|
handleRegistrationFees();
|
||||||
|
|
||||||
|
// Fetch data for tuition fees
|
||||||
handleTuitionFees();
|
handleTuitionFees();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -75,14 +74,6 @@ export default function Page() {
|
|||||||
.catch(error => console.error('Error fetching schedules:', error));
|
.catch(error => console.error('Error fetching schedules:', error));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFees = () => {
|
|
||||||
fetchFees()
|
|
||||||
.then(data => {
|
|
||||||
setFees(data);
|
|
||||||
})
|
|
||||||
.catch(error => console.error('Error fetching fees:', error));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDiscounts = () => {
|
const handleDiscounts = () => {
|
||||||
fetchDiscounts()
|
fetchDiscounts()
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@ -91,6 +82,14 @@ export default function Page() {
|
|||||||
.catch(error => console.error('Error fetching discounts:', error));
|
.catch(error => console.error('Error fetching discounts:', error));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleRegistrationFees = () => {
|
||||||
|
fetchRegistrationFees()
|
||||||
|
.then(data => {
|
||||||
|
setRegistrationFees(data);
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching registration fees:', error));
|
||||||
|
};
|
||||||
|
|
||||||
const handleTuitionFees = () => {
|
const handleTuitionFees = () => {
|
||||||
fetchTuitionFees()
|
fetchTuitionFees()
|
||||||
.then(data => {
|
.then(data => {
|
||||||
@ -237,10 +236,10 @@ export default function Page() {
|
|||||||
label: 'Tarifications',
|
label: 'Tarifications',
|
||||||
content: (
|
content: (
|
||||||
<FeesManagement
|
<FeesManagement
|
||||||
fees={fees}
|
|
||||||
setFees={setFees}
|
|
||||||
discounts={discounts}
|
discounts={discounts}
|
||||||
setDiscounts={setDiscounts}
|
setDiscounts={setDiscounts}
|
||||||
|
registrationFees={registrationFees}
|
||||||
|
setRegistrationFees={setRegistrationFees}
|
||||||
tuitionFees={tuitionFees}
|
tuitionFees={tuitionFees}
|
||||||
setTuitionFees={setTuitionFees}
|
setTuitionFees={setTuitionFees}
|
||||||
handleCreate={handleCreate}
|
handleCreate={handleCreate}
|
||||||
|
|||||||
@ -4,8 +4,7 @@ import {
|
|||||||
BE_SCHOOL_SCHOOLCLASSES_URL,
|
BE_SCHOOL_SCHOOLCLASSES_URL,
|
||||||
BE_SCHOOL_PLANNINGS_URL,
|
BE_SCHOOL_PLANNINGS_URL,
|
||||||
BE_SCHOOL_FEES_URL,
|
BE_SCHOOL_FEES_URL,
|
||||||
BE_SCHOOL_DISCOUNTS_URL,
|
BE_SCHOOL_DISCOUNTS_URL
|
||||||
BE_SCHOOL_TUITION_FEES_URL
|
|
||||||
} from '@/utils/Url';
|
} from '@/utils/Url';
|
||||||
|
|
||||||
const requestResponseHandler = async (response) => {
|
const requestResponseHandler = async (response) => {
|
||||||
@ -46,12 +45,12 @@ export const fetchDiscounts = () => {
|
|||||||
.then(requestResponseHandler)
|
.then(requestResponseHandler)
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchFees = () => {
|
export const fetchRegistrationFees = () => {
|
||||||
return fetch(`${BE_SCHOOL_FEES_URL}`)
|
return fetch(`${BE_SCHOOL_FEES_URL}/registration`)
|
||||||
.then(requestResponseHandler)
|
.then(requestResponseHandler)
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchTuitionFees = () => {
|
export const fetchTuitionFees = () => {
|
||||||
return fetch(`${BE_SCHOOL_TUITION_FEES_URL}`)
|
return fetch(`${BE_SCHOOL_FEES_URL}/tuition`)
|
||||||
.then(requestResponseHandler)
|
.then(requestResponseHandler)
|
||||||
};
|
};
|
||||||
@ -1,10 +1,10 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Plus, Trash, Edit3, Check, X } from 'lucide-react';
|
import { Plus, Trash, Edit3, Check, X, Percent, EuroIcon } from 'lucide-react';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import InputTextIcon from '@/components/InputTextIcon';
|
import InputTextIcon from '@/components/InputTextIcon';
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
|
|
||||||
const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete }) => {
|
const DiscountsSection = ({ discounts, setDiscounts, handleCreate, handleEdit, handleDelete, errors }) => {
|
||||||
const [editingDiscount, setEditingDiscount] = useState(null);
|
const [editingDiscount, setEditingDiscount] = useState(null);
|
||||||
const [newDiscount, setNewDiscount] = useState(null);
|
const [newDiscount, setNewDiscount] = useState(null);
|
||||||
const [formData, setFormData] = useState({});
|
const [formData, setFormData] = useState({});
|
||||||
@ -13,17 +13,24 @@ const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete })
|
|||||||
const [popupMessage, setPopupMessage] = useState("");
|
const [popupMessage, setPopupMessage] = useState("");
|
||||||
|
|
||||||
const handleAddDiscount = () => {
|
const handleAddDiscount = () => {
|
||||||
setNewDiscount({ id: Date.now(), name: '', amount: '', description: '' });
|
setNewDiscount({ id: Date.now(), name: '', amount: '', description: '', discountType: 'amount' });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleRemoveDiscount = (id) => {
|
const handleRemoveDiscount = (id) => {
|
||||||
handleDelete(id)
|
handleDelete(id)
|
||||||
|
.then(() => {
|
||||||
|
setDiscounts(prevDiscounts => prevDiscounts.filter(discount => discount.id !== id));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveNewDiscount = () => {
|
const handleSaveNewDiscount = () => {
|
||||||
if (newDiscount.name && newDiscount.amount) {
|
if (newDiscount.name && newDiscount.amount) {
|
||||||
handleCreate(newDiscount)
|
handleCreate(newDiscount)
|
||||||
.then(() => {
|
.then((createdDiscount) => {
|
||||||
|
setDiscounts([createdDiscount, ...discounts]);
|
||||||
setNewDiscount(null);
|
setNewDiscount(null);
|
||||||
setLocalErrors({});
|
setLocalErrors({});
|
||||||
})
|
})
|
||||||
@ -60,9 +67,29 @@ const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete })
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleToggleDiscountType = (id, newType) => {
|
||||||
|
const discount = discounts.find(discount => discount.id === id);
|
||||||
|
if (!discount) return;
|
||||||
|
|
||||||
|
const updatedData = {
|
||||||
|
...discount,
|
||||||
|
discount_type: newType
|
||||||
|
};
|
||||||
|
|
||||||
|
handleEdit(id, updatedData)
|
||||||
|
.then(() => {
|
||||||
|
setDiscounts(prevDiscounts => prevDiscounts.map(discount => discount.id === id ? { ...discount, discount_type: updatedData.discount_type } : discount));
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
if (editingDiscount) {
|
if (name === 'discountType') {
|
||||||
|
setDiscountType(value);
|
||||||
|
} else if (editingDiscount) {
|
||||||
setFormData((prevData) => ({
|
setFormData((prevData) => ({
|
||||||
...prevData,
|
...prevData,
|
||||||
[name]: value,
|
[name]: value,
|
||||||
@ -97,13 +124,13 @@ const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete })
|
|||||||
switch (column) {
|
switch (column) {
|
||||||
case 'LIBELLE':
|
case 'LIBELLE':
|
||||||
return renderInputField('name', currentData.name, handleChange, 'Libellé de la réduction');
|
return renderInputField('name', currentData.name, handleChange, 'Libellé de la réduction');
|
||||||
case 'MONTANT':
|
case 'VALEUR':
|
||||||
return renderInputField('amount', currentData.amount, handleChange, 'Montant');
|
return renderInputField('amount', currentData.amount, handleChange, discount.discount_type === 0 ? 'Montant' : 'Pourcentage');
|
||||||
case 'DESCRIPTION':
|
case 'DESCRIPTION':
|
||||||
return renderInputField('description', currentData.description, handleChange, 'Description');
|
return renderInputField('description', currentData.description, handleChange, 'Description');
|
||||||
case 'ACTIONS':
|
case 'ACTIONS':
|
||||||
return (
|
return (
|
||||||
<div className="flex space-x-2">
|
<div className="flex justify-center space-x-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => (isEditing ? handleUpdateDiscount(editingDiscount, formData) : handleSaveNewDiscount())}
|
onClick={() => (isEditing ? handleUpdateDiscount(editingDiscount, formData) : handleSaveNewDiscount())}
|
||||||
@ -127,8 +154,27 @@ const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete })
|
|||||||
switch (column) {
|
switch (column) {
|
||||||
case 'LIBELLE':
|
case 'LIBELLE':
|
||||||
return discount.name;
|
return discount.name;
|
||||||
case 'MONTANT':
|
case 'VALEUR':
|
||||||
return discount.amount + ' €';
|
return discount.discount_type === 0 ? `${discount.amount} €` : `${discount.amount} %`;
|
||||||
|
case 'TYPE DE REMISE':
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center space-y-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleToggleDiscountType(discount.id, 0)}
|
||||||
|
className={`text-${discount.discount_type === 0 ? 'emerald' : 'gray'}-500 hover:text-${discount.discount_type === 0 ? 'emerald' : 'gray'}-700`}
|
||||||
|
>
|
||||||
|
<EuroIcon className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleToggleDiscountType(discount.id, 1)}
|
||||||
|
className={`text-${discount.discount_type === 1 ? 'emerald' : 'gray'}-500 hover:text-${discount.discount_type === 1 ? 'emerald' : 'gray'}-700`}
|
||||||
|
>
|
||||||
|
<Percent className="w-5 h-5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
case 'DESCRIPTION':
|
case 'DESCRIPTION':
|
||||||
return discount.description;
|
return discount.description;
|
||||||
case 'ACTIONS':
|
case 'ACTIONS':
|
||||||
@ -168,7 +214,8 @@ const DiscountsSection = ({ discounts, handleCreate, handleEdit, handleDelete })
|
|||||||
data={newDiscount ? [newDiscount, ...discounts] : discounts}
|
data={newDiscount ? [newDiscount, ...discounts] : discounts}
|
||||||
columns={[
|
columns={[
|
||||||
{ name: 'LIBELLE', label: 'Libellé' },
|
{ name: 'LIBELLE', label: 'Libellé' },
|
||||||
{ name: 'MONTANT', label: 'Montant' },
|
{ name: 'VALEUR', label: 'Valeur' },
|
||||||
|
{ name: 'TYPE DE REMISE', label: 'Type de remise' },
|
||||||
{ name: 'DESCRIPTION', label: 'Description' },
|
{ name: 'DESCRIPTION', label: 'Description' },
|
||||||
{ name: 'ACTIONS', label: 'Actions' }
|
{ name: 'ACTIONS', label: 'Actions' }
|
||||||
]}
|
]}
|
||||||
|
|||||||
@ -1,29 +1,30 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import FeesSection from './FeesSection';
|
import RegistrationFeesSection from '@/components/Structure/Configuration/RegistrationFeesSection';
|
||||||
import DiscountsSection from './DiscountsSection';
|
import DiscountsSection from '@/components/Structure/Configuration/DiscountsSection';
|
||||||
import TuitionFeesSection from './TuitionFeesSection';
|
import TuitionFeesSection from '@/components/Structure/Configuration/TuitionFeesSection';
|
||||||
import { BE_SCHOOL_FEE_URL, BE_SCHOOL_DISCOUNT_URL, BE_SCHOOL_TUITION_FEE_URL } from '@/utils/Url';
|
import { BE_SCHOOL_FEE_URL, BE_SCHOOL_DISCOUNT_URL } from '@/utils/Url';
|
||||||
|
|
||||||
const FeesManagement = ({ fees, setFees, discounts, setDiscounts, tuitionFees, setTuitionFees, handleCreate, handleEdit, handleDelete }) => {
|
const FeesManagement = ({ discounts, setDiscounts, registrationFees, setRegistrationFees, tuitionFees, setTuitionFees, handleCreate, handleEdit, handleDelete }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-8xl mx-auto p-4 mt-6 space-y-6">
|
<div className="max-w-8xl mx-auto p-4 mt-6 space-y-6">
|
||||||
<div className="p-4 bg-white rounded-lg shadow-md">
|
<div className="p-4 bg-white rounded-lg shadow-md">
|
||||||
<DiscountsSection
|
<DiscountsSection
|
||||||
discounts={discounts}
|
discounts={discounts}
|
||||||
|
setDiscounts={setDiscounts}
|
||||||
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_DISCOUNT_URL}`, newData, setDiscounts)}
|
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_DISCOUNT_URL}`, newData, setDiscounts)}
|
||||||
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_DISCOUNT_URL}`, id, updatedData, setDiscounts)}
|
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_DISCOUNT_URL}`, id, updatedData, setDiscounts)}
|
||||||
handleDelete={(id) => handleDelete(`${BE_SCHOOL_DISCOUNT_URL}`, id, setDiscounts)}
|
handleDelete={(id) => handleDelete(`${BE_SCHOOL_DISCOUNT_URL}`, id, setDiscounts)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-white rounded-lg shadow-md">
|
<div className="p-4 bg-white rounded-lg shadow-md">
|
||||||
<FeesSection
|
<RegistrationFeesSection
|
||||||
fees={fees}
|
registrationFees={registrationFees}
|
||||||
setFees={setFees}
|
setRegistrationFees={setRegistrationFees}
|
||||||
discounts={discounts}
|
discounts={discounts}
|
||||||
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_FEE_URL}`, newData, setFees)}
|
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_FEE_URL}`, newData, setRegistrationFees)}
|
||||||
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_FEE_URL}`, id, updatedData, setFees)}
|
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_FEE_URL}`, id, updatedData, setRegistrationFees)}
|
||||||
handleDelete={(id) => handleDelete(`${BE_SCHOOL_FEE_URL}`, id, setFees)}
|
handleDelete={(id) => handleDelete(`${BE_SCHOOL_FEE_URL}`, id, setRegistrationFees)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 bg-white rounded-lg shadow-md">
|
<div className="p-4 bg-white rounded-lg shadow-md">
|
||||||
@ -31,10 +32,10 @@ const FeesManagement = ({ fees, setFees, discounts, setDiscounts, tuitionFees, s
|
|||||||
tuitionFees={tuitionFees}
|
tuitionFees={tuitionFees}
|
||||||
setTuitionFees={setTuitionFees}
|
setTuitionFees={setTuitionFees}
|
||||||
discounts={discounts}
|
discounts={discounts}
|
||||||
fees={fees}
|
registrationFees={registrationFees}
|
||||||
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_TUITION_FEE_URL}`, newData, setTuitionFees)}
|
handleCreate={(newData) => handleCreate(`${BE_SCHOOL_FEE_URL}`, newData, setTuitionFees)}
|
||||||
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_TUITION_FEE_URL}`, id, updatedData, setTuitionFees)}
|
handleEdit={(id, updatedData) => handleEdit(`${BE_SCHOOL_FEE_URL}`, id, updatedData, setTuitionFees)}
|
||||||
handleDelete={(id) => handleDelete(`${BE_SCHOOL_TUITION_FEE_URL}`, id, setTuitionFees)}
|
handleDelete={(id) => handleDelete(`${BE_SCHOOL_FEE_URL}`, id, setTuitionFees)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Plus, Trash, Edit3, Check, X } from 'lucide-react';
|
import { Plus, Trash, Edit3, Check, X, EyeOff, Eye } from 'lucide-react';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import InputTextIcon from '@/components/InputTextIcon';
|
import InputTextIcon from '@/components/InputTextIcon';
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
import SelectChoice from '@/components/SelectChoice';
|
import SelectChoice from '@/components/SelectChoice';
|
||||||
|
|
||||||
const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handleDelete }) => {
|
const RegistrationFeesSection = ({ registrationFees, setRegistrationFees, discounts, handleCreate, handleEdit, handleDelete }) => {
|
||||||
const [editingFee, setEditingFee] = useState(null);
|
const [editingFee, setEditingFee] = useState(null);
|
||||||
const [newFee, setNewFee] = useState(null);
|
const [newFee, setNewFee] = useState(null);
|
||||||
const [formData, setFormData] = useState({});
|
const [formData, setFormData] = useState({});
|
||||||
@ -29,8 +29,14 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
|
|
||||||
const handleSaveNewFee = () => {
|
const handleSaveNewFee = () => {
|
||||||
if (newFee.name && newFee.base_amount) {
|
if (newFee.name && newFee.base_amount) {
|
||||||
handleCreate(newFee)
|
const feeData = {
|
||||||
.then(() => {
|
...newFee,
|
||||||
|
type: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
handleCreate(feeData)
|
||||||
|
.then((createdFee) => {
|
||||||
|
setRegistrationFees([createdFee, ...registrationFees]);
|
||||||
setNewFee(null);
|
setNewFee(null);
|
||||||
setLocalErrors({});
|
setLocalErrors({});
|
||||||
})
|
})
|
||||||
@ -68,7 +74,7 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleActive = (id, isActive) => {
|
const handleToggleActive = (id, isActive) => {
|
||||||
const fee = fees.find(fee => fee.id === id);
|
const fee = registrationFees.find(fee => fee.id === id);
|
||||||
if (!fee) return;
|
if (!fee) return;
|
||||||
|
|
||||||
const updatedData = {
|
const updatedData = {
|
||||||
@ -78,7 +84,7 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
|
|
||||||
handleEdit(id, updatedData)
|
handleEdit(id, updatedData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setFees(prevFees => prevFees.map(fee => fee.id === id ? { ...fee, is_active: !isActive } : fee));
|
setRegistrationFees(prevFees => prevFees.map(fee => fee.id === id ? { ...fee, is_active: !isActive } : fee));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -107,7 +113,14 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
const calculateFinalAmount = (baseAmount, discountIds) => {
|
const calculateFinalAmount = (baseAmount, discountIds) => {
|
||||||
const totalDiscounts = discountIds.reduce((sum, discountId) => {
|
const totalDiscounts = discountIds.reduce((sum, discountId) => {
|
||||||
const discount = discounts.find(d => d.id === discountId);
|
const discount = discounts.find(d => d.id === discountId);
|
||||||
return discount ? sum + parseFloat(discount.amount) : sum;
|
if (discount) {
|
||||||
|
if (discount.discount_type === 0) { // Currency
|
||||||
|
return sum + parseFloat(discount.amount);
|
||||||
|
} else if (discount.discount_type === 1) { // Percent
|
||||||
|
return sum + (parseFloat(baseAmount) * parseFloat(discount.amount) / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const finalAmount = parseFloat(baseAmount) - totalDiscounts;
|
const finalAmount = parseFloat(baseAmount) - totalDiscounts;
|
||||||
@ -220,7 +233,7 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
onClick={() => handleToggleActive(fee.id, fee.is_active)}
|
onClick={() => handleToggleActive(fee.id, fee.is_active)}
|
||||||
className={`text-${fee.is_active ? 'gray' : 'green'}-500 hover:text-${fee.is_active ? 'gray' : 'green'}-700`}
|
className={`text-${fee.is_active ? 'gray' : 'green'}-500 hover:text-${fee.is_active ? 'gray' : 'green'}-700`}
|
||||||
>
|
>
|
||||||
{fee.is_active ? <X className="w-5 h-5" /> : <Check className="w-5 h-5" />}
|
{fee.is_active ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -240,7 +253,7 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Table
|
<Table
|
||||||
data={newFee ? [newFee, ...fees] : fees}
|
data={newFee ? [newFee, ...registrationFees] : registrationFees}
|
||||||
columns={[
|
columns={[
|
||||||
{ name: 'LIBELLE', label: 'Libellé' },
|
{ name: 'LIBELLE', label: 'Libellé' },
|
||||||
{ name: 'MONTANT DE BASE', label: 'Montant' },
|
{ name: 'MONTANT DE BASE', label: 'Montant' },
|
||||||
@ -264,4 +277,4 @@ const FeesSection = ({ fees, setFees, discounts, handleCreate, handleEdit, handl
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default FeesSection;
|
export default RegistrationFeesSection;
|
||||||
@ -1,11 +1,11 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Plus, Trash, Edit3, Check, X } from 'lucide-react';
|
import { Plus, Trash, Edit3, Check, X, EyeOff, Eye } from 'lucide-react';
|
||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import InputTextIcon from '@/components/InputTextIcon';
|
import InputTextIcon from '@/components/InputTextIcon';
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
import SelectChoice from '@/components/SelectChoice';
|
import SelectChoice from '@/components/SelectChoice';
|
||||||
|
|
||||||
const TuitionFeesSection = ({ tuitionFees, setTuitionFees, discounts, fees, handleCreate, handleEdit, handleDelete }) => {
|
const TuitionFeesSection = ({ tuitionFees, setTuitionFees, discounts, registrationFees, handleCreate, handleEdit, handleDelete }) => {
|
||||||
const [editingTuitionFee, setEditingTuitionFee] = useState(null);
|
const [editingTuitionFee, setEditingTuitionFee] = useState(null);
|
||||||
const [newTuitionFee, setNewTuitionFee] = useState(null);
|
const [newTuitionFee, setNewTuitionFee] = useState(null);
|
||||||
const [formData, setFormData] = useState({});
|
const [formData, setFormData] = useState({});
|
||||||
@ -39,7 +39,11 @@ const TuitionFeesSection = ({ tuitionFees, setTuitionFees, discounts, fees, hand
|
|||||||
newTuitionFee.base_amount &&
|
newTuitionFee.base_amount &&
|
||||||
newTuitionFee.payment_option >= 0
|
newTuitionFee.payment_option >= 0
|
||||||
) {
|
) {
|
||||||
handleCreate(newTuitionFee)
|
const tuitionFeeData = {
|
||||||
|
...newTuitionFee,
|
||||||
|
type: 1
|
||||||
|
};
|
||||||
|
handleCreate(tuitionFeeData)
|
||||||
.then((createdTuitionFee) => {
|
.then((createdTuitionFee) => {
|
||||||
setTuitionFees([createdTuitionFee, ...tuitionFees]);
|
setTuitionFees([createdTuitionFee, ...tuitionFees]);
|
||||||
setNewTuitionFee(null);
|
setNewTuitionFee(null);
|
||||||
@ -151,7 +155,14 @@ const TuitionFeesSection = ({ tuitionFees, setTuitionFees, discounts, fees, hand
|
|||||||
const calculateFinalAmount = (baseAmount, discountIds) => {
|
const calculateFinalAmount = (baseAmount, discountIds) => {
|
||||||
const totalDiscounts = discountIds.reduce((sum, discountId) => {
|
const totalDiscounts = discountIds.reduce((sum, discountId) => {
|
||||||
const discount = discounts.find(d => d.id === discountId);
|
const discount = discounts.find(d => d.id === discountId);
|
||||||
return discount ? sum + parseFloat(discount.amount) : sum;
|
if (discount) {
|
||||||
|
if (discount.discount_type === 0) { // Currency
|
||||||
|
return sum + parseFloat(discount.amount);
|
||||||
|
} else if (discount.discount_type === 1) { // Percent
|
||||||
|
return sum + (parseFloat(baseAmount) * parseFloat(discount.amount) / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
const finalAmount = parseFloat(baseAmount) - totalDiscounts;
|
const finalAmount = parseFloat(baseAmount) - totalDiscounts;
|
||||||
@ -238,7 +249,7 @@ const TuitionFeesSection = ({ tuitionFees, setTuitionFees, discounts, fees, hand
|
|||||||
onClick={() => handleToggleActive(tuitionFee.id, tuitionFee.is_active)}
|
onClick={() => handleToggleActive(tuitionFee.id, tuitionFee.is_active)}
|
||||||
className={`text-${tuitionFee.is_active ? 'gray' : 'green'}-500 hover:text-${tuitionFee.is_active ? 'gray' : 'green'}-700`}
|
className={`text-${tuitionFee.is_active ? 'gray' : 'green'}-500 hover:text-${tuitionFee.is_active ? 'gray' : 'green'}-700`}
|
||||||
>
|
>
|
||||||
{tuitionFee.is_active ? <X className="w-5 h-5" /> : <Check className="w-5 h-5" />}
|
{tuitionFee.is_active ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -39,8 +39,6 @@ export const BE_SCHOOL_FEE_URL = `${BASE_URL}/School/fee`;
|
|||||||
export const BE_SCHOOL_FEES_URL = `${BASE_URL}/School/fees`;
|
export const BE_SCHOOL_FEES_URL = `${BASE_URL}/School/fees`;
|
||||||
export const BE_SCHOOL_DISCOUNT_URL = `${BASE_URL}/School/discount`;
|
export const BE_SCHOOL_DISCOUNT_URL = `${BASE_URL}/School/discount`;
|
||||||
export const BE_SCHOOL_DISCOUNTS_URL = `${BASE_URL}/School/discounts`;
|
export const BE_SCHOOL_DISCOUNTS_URL = `${BASE_URL}/School/discounts`;
|
||||||
export const BE_SCHOOL_TUITION_FEE_URL = `${BASE_URL}/School/tuitionFee`;
|
|
||||||
export const BE_SCHOOL_TUITION_FEES_URL = `${BASE_URL}/School/tuitionFees`;
|
|
||||||
|
|
||||||
// GESTION MESSAGERIE
|
// GESTION MESSAGERIE
|
||||||
export const BE_GESTIONMESSAGERIE_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
|
export const BE_GESTIONMESSAGERIE_MESSAGES_URL = `${BASE_URL}/GestionMessagerie/messagerie`
|
||||||
|
|||||||
Reference in New Issue
Block a user