mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
fix: Correction de l'affichage des numéros de téléphone [#41]
This commit is contained in:
@ -11,13 +11,13 @@ from Subscriptions.models import (
|
|||||||
)
|
)
|
||||||
from Auth.models import Profile, ProfileRole
|
from Auth.models import Profile, ProfileRole
|
||||||
from School.models import (
|
from School.models import (
|
||||||
FeeType,
|
FeeType,
|
||||||
Speciality,
|
Speciality,
|
||||||
Teacher,
|
Teacher,
|
||||||
SchoolClass,
|
SchoolClass,
|
||||||
PaymentMode,
|
PaymentMode,
|
||||||
PaymentModeType,
|
PaymentModeType,
|
||||||
PaymentPlan,
|
PaymentPlan,
|
||||||
PaymentPlanType,
|
PaymentPlanType,
|
||||||
DiscountType
|
DiscountType
|
||||||
)
|
)
|
||||||
@ -371,7 +371,7 @@ class Command(BaseCommand):
|
|||||||
"first_name": fake.first_name(),
|
"first_name": fake.first_name(),
|
||||||
"birth_date": fake.date_of_birth().strftime('%Y-%m-%d'),
|
"birth_date": fake.date_of_birth().strftime('%Y-%m-%d'),
|
||||||
"address": fake.address(),
|
"address": fake.address(),
|
||||||
"phone": fake.phone_number(),
|
"phone":"+33122334455",
|
||||||
"profession": fake.job()
|
"profession": fake.job()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -231,7 +231,7 @@ class RegistrationTemplate(models.Model):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_files_from_rf(register_form_id):
|
def get_files_from_rf(register_form_id):
|
||||||
"""
|
"""
|
||||||
|
|||||||
94
Front-End/package-lock.json
generated
94
Front-End/package-lock.json
generated
@ -27,7 +27,7 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-phone-number-input": "^3.4.8",
|
"react-international-phone": "^4.5.0",
|
||||||
"react-tooltip": "^5.28.0"
|
"react-tooltip": "^5.28.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -2147,11 +2147,6 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/country-flag-icons": {
|
|
||||||
"version": "1.5.18",
|
|
||||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.18.tgz",
|
|
||||||
"integrity": "sha512-z+Uzesi8u8IdkViqqbzzbkf3+a7WJpcET5B7sPwTg7GXqPYpVEgNlZ/FC3l8KO4mEf+mNkmzKLppKTN4PlCJEQ=="
|
|
||||||
},
|
|
||||||
"node_modules/cross-spawn": {
|
"node_modules/cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@ -3628,26 +3623,6 @@
|
|||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/input-format": {
|
|
||||||
"version": "0.3.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/input-format/-/input-format-0.3.14.tgz",
|
|
||||||
"integrity": "sha512-gHMrgrbCgmT4uK5Um5eVDUohuV9lcs95ZUUN9Px2Y0VIfjTzT2wF8Q3Z4fwLFm7c5Z2OXCm53FHoovj6SlOKdg==",
|
|
||||||
"dependencies": {
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=18.1.0",
|
|
||||||
"react-dom": ">=18.1.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"react": {
|
|
||||||
"optional": true
|
|
||||||
},
|
|
||||||
"react-dom": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/internal-slot": {
|
"node_modules/internal-slot": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||||
@ -4275,11 +4250,6 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/libphonenumber-js": {
|
|
||||||
"version": "1.12.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
|
|
||||||
"integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw=="
|
|
||||||
},
|
|
||||||
"node_modules/lilconfig": {
|
"node_modules/lilconfig": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||||
@ -5249,6 +5219,7 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@ -5366,27 +5337,19 @@
|
|||||||
"react": "^18.3.1"
|
"react": "^18.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-international-phone": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-international-phone/-/react-international-phone-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-wjwHv+VfiwM49B5/6El4Z5vZKmf3ILpUeiOCI9X+b0Dq4g5nL8gROcwCdVcTXywxznbDSoxSassBX3i9tPZX6g==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-is": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
"node_modules/react-phone-number-input": {
|
|
||||||
"version": "3.4.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.12.tgz",
|
|
||||||
"integrity": "sha512-Raob77KdtLGm49iC6nuOX9qy6Mg16idkgC7Y1mHmvG2WBYoauHpzxYNlfmFskQKeiztrJIwPhPzBhjFwjenNCA==",
|
|
||||||
"dependencies": {
|
|
||||||
"classnames": "^2.5.1",
|
|
||||||
"country-flag-icons": "^1.5.17",
|
|
||||||
"input-format": "^0.3.10",
|
|
||||||
"libphonenumber-js": "^1.11.20",
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8",
|
|
||||||
"react-dom": ">=16.8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-remove-scroll": {
|
"node_modules/react-remove-scroll": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
|
||||||
@ -8266,11 +8229,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
|
||||||
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="
|
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="
|
||||||
},
|
},
|
||||||
"country-flag-icons": {
|
|
||||||
"version": "1.5.18",
|
|
||||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.5.18.tgz",
|
|
||||||
"integrity": "sha512-z+Uzesi8u8IdkViqqbzzbkf3+a7WJpcET5B7sPwTg7GXqPYpVEgNlZ/FC3l8KO4mEf+mNkmzKLppKTN4PlCJEQ=="
|
|
||||||
},
|
|
||||||
"cross-spawn": {
|
"cross-spawn": {
|
||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
@ -9349,14 +9307,6 @@
|
|||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"input-format": {
|
|
||||||
"version": "0.3.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/input-format/-/input-format-0.3.14.tgz",
|
|
||||||
"integrity": "sha512-gHMrgrbCgmT4uK5Um5eVDUohuV9lcs95ZUUN9Px2Y0VIfjTzT2wF8Q3Z4fwLFm7c5Z2OXCm53FHoovj6SlOKdg==",
|
|
||||||
"requires": {
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"internal-slot": {
|
"internal-slot": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
|
||||||
@ -9795,11 +9745,6 @@
|
|||||||
"type-check": "~0.4.0"
|
"type-check": "~0.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"libphonenumber-js": {
|
|
||||||
"version": "1.12.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
|
|
||||||
"integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw=="
|
|
||||||
},
|
|
||||||
"lilconfig": {
|
"lilconfig": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
|
||||||
@ -10425,6 +10370,7 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@ -10499,23 +10445,17 @@
|
|||||||
"scheduler": "^0.23.2"
|
"scheduler": "^0.23.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-international-phone": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-international-phone/-/react-international-phone-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-wjwHv+VfiwM49B5/6El4Z5vZKmf3ILpUeiOCI9X+b0Dq4g5nL8gROcwCdVcTXywxznbDSoxSassBX3i9tPZX6g==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"react-is": {
|
"react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||||
},
|
},
|
||||||
"react-phone-number-input": {
|
|
||||||
"version": "3.4.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-phone-number-input/-/react-phone-number-input-3.4.12.tgz",
|
|
||||||
"integrity": "sha512-Raob77KdtLGm49iC6nuOX9qy6Mg16idkgC7Y1mHmvG2WBYoauHpzxYNlfmFskQKeiztrJIwPhPzBhjFwjenNCA==",
|
|
||||||
"requires": {
|
|
||||||
"classnames": "^2.5.1",
|
|
||||||
"country-flag-icons": "^1.5.17",
|
|
||||||
"input-format": "^0.3.10",
|
|
||||||
"libphonenumber-js": "^1.11.20",
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"react-remove-scroll": {
|
"react-remove-scroll": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz",
|
||||||
|
|||||||
@ -29,7 +29,7 @@
|
|||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
"react-dnd-html5-backend": "^16.0.1",
|
"react-dnd-html5-backend": "^16.0.1",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-phone-number-input": "^3.4.8",
|
"react-international-phone": "^4.5.0",
|
||||||
"react-tooltip": "^5.28.0"
|
"react-tooltip": "^5.28.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import Popup from '@/components/Popup';
|
|||||||
import Loader from '@/components/Loader';
|
import Loader from '@/components/Loader';
|
||||||
import AlertWithModal from '@/components/AlertWithModal';
|
import AlertWithModal from '@/components/AlertWithModal';
|
||||||
import DropdownMenu from "@/components/DropdownMenu";
|
import DropdownMenu from "@/components/DropdownMenu";
|
||||||
import { formatPhoneNumber } from '@/utils/Telephone';
|
|
||||||
import { MoreVertical, Send, Edit, Archive, FileText, CircleCheck, Plus, XCircle } from 'lucide-react';
|
import { MoreVertical, Send, Edit, Archive, FileText, CircleCheck, Plus, XCircle } from 'lucide-react';
|
||||||
import Modal from '@/components/Modal';
|
import Modal from '@/components/Modal';
|
||||||
import InscriptionForm from '@/components/Inscription/InscriptionForm'
|
import InscriptionForm from '@/components/Inscription/InscriptionForm'
|
||||||
@ -50,6 +49,7 @@ import {
|
|||||||
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
import DjangoCSRFToken from '@/components/DjangoCSRFToken'
|
||||||
import { useCsrfToken } from '@/context/CsrfContext';
|
import { useCsrfToken } from '@/context/CsrfContext';
|
||||||
import logger from '@/utils/logger';
|
import logger from '@/utils/logger';
|
||||||
|
import { PhoneLabel } from '@/components/PhoneLabel';
|
||||||
|
|
||||||
export default function Page({ params: { locale } }) {
|
export default function Page({ params: { locale } }) {
|
||||||
const t = useTranslations('subscriptions');
|
const t = useTranslations('subscriptions');
|
||||||
@ -103,7 +103,7 @@ export default function Page({ params: { locale } }) {
|
|||||||
setIsOpenAddGuardian(true);
|
setIsOpenAddGuardian(true);
|
||||||
setStudent(eleveSelected);
|
setStudent(eleveSelected);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCloseAddGuardian = () => {
|
const handleCloseAddGuardian = () => {
|
||||||
setIsOpenAddGuardian(false);
|
setIsOpenAddGuardian(false);
|
||||||
};
|
};
|
||||||
@ -285,7 +285,7 @@ useEffect(() => {
|
|||||||
fetchRegistrationTemplateMaster()
|
fetchRegistrationTemplateMaster()
|
||||||
.then((data)=> {setTemplateMasters(data)})
|
.then((data)=> {setTemplateMasters(data)})
|
||||||
.catch((err)=>{ err = err.message; logger.debug(err);});
|
.catch((err)=>{ err = err.message; logger.debug(err);});
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setReloadFetch(false);
|
setReloadFetch(false);
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ useEffect(()=>{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateStatusAction = (id, newStatus) => {
|
const updateStatusAction = (id, newStatus) => {
|
||||||
logger.debug(`Mise à jour du statut du dossier d'inscription avec l'ID : ${id} vers le statut : ${newStatus}`);
|
logger.debug(`Mise à jour du statut du dossier d'inscription avec l'ID : ${id} vers le statut : ${newStatus}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSearchChange = (event) => {
|
const handleSearchChange = (event) => {
|
||||||
@ -427,7 +427,7 @@ useEffect(()=>{
|
|||||||
profession: updatedData.guardianProfession
|
profession: updatedData.guardianProfession
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
||||||
return [{
|
return [{
|
||||||
profile_role_data: {
|
profile_role_data: {
|
||||||
@ -531,7 +531,7 @@ useEffect(()=>{
|
|||||||
profession: updatedData.guardianProfession
|
profession: updatedData.guardianProfession
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
// Si aucun profil existant n'est trouvé, créer un nouveau profil
|
||||||
return [{
|
return [{
|
||||||
profile_role_data: {
|
profile_role_data: {
|
||||||
@ -614,7 +614,7 @@ useEffect(()=>{
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// Combine actions for the specific status and default actions
|
// Combine actions for the specific status and default actions
|
||||||
return [...(actions[row.status] || []), ...(row.status !== 6 ? actions.default : [])];
|
return [...(actions[row.status] || []), ...(row.status !== 6 ? actions.default : [])];
|
||||||
};
|
};
|
||||||
@ -641,7 +641,7 @@ const columns = [
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{ name: t('phone'), transform: (row) => formatPhoneNumber(row.student.guardians[0]?.phone) },
|
{ name: t('phone'), transform: (row) => <PhoneLabel phoneNumber={row.student.guardians[0]?.phone} /> },
|
||||||
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
|
{ name: t('lastUpdateDate'), transform: (row) => row.formatted_last_update},
|
||||||
{ name: t('registrationFileStatus'), transform: (row) => (
|
{ name: t('registrationFileStatus'), transform: (row) => (
|
||||||
<div className="flex justify-center items-center h-full">
|
<div className="flex justify-center items-center h-full">
|
||||||
|
|||||||
@ -1,40 +1,32 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import React from 'react';
|
||||||
|
import { PhoneInput } from 'react-international-phone';
|
||||||
|
import 'react-international-phone/style.css';
|
||||||
export default function InputPhone({ name, label, value, onChange, errorMsg, placeholder, className, required }) {
|
|
||||||
const inputRef = useRef(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (inputRef.current) {
|
|
||||||
inputRef.current.focus();
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleChange = (e) => {
|
|
||||||
const newValue = e.target.value;
|
|
||||||
onChange(newValue);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
export default function InputPhone({ name, label, value, onChange, errorMsg, className, required }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={`${className}`}>
|
||||||
<div className={`mb-4 ${className}`}>
|
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
|
||||||
<label htmlFor={name} className="block text-sm font-medium text-gray-700">
|
{label}
|
||||||
{label}
|
{required && <span className="text-red-500 ml-1">*</span>}
|
||||||
{required && <span className="text-red-500 ml-1">*</span>}
|
</label>
|
||||||
</label>
|
|
||||||
<div className={`mt-1 flex items-center border border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} hover:border-gray-400 focus-within:border-gray-500`}>
|
<PhoneInput
|
||||||
<input
|
defaultCountry="fr"
|
||||||
type="tel"
|
value={value}
|
||||||
name={name}
|
onChange={(phone) => onChange(phone)}
|
||||||
ref={inputRef}
|
inputProps={{
|
||||||
className="flex-1 px-3 py-2 block w-full sm:text-sm focus:ring-0 rounded-md border-none outline-none"
|
name: name,
|
||||||
value={typeof value === 'string' ? value : ''}
|
required: required,
|
||||||
onChange={handleChange}
|
}}
|
||||||
placeholder={placeholder}
|
className="!w-full mt-1 !h-[38px]"
|
||||||
/>
|
containerClassName="!w-full !h-[36px] !flex !items-center !rounded-md"
|
||||||
</div>
|
inputClassName={`flex-1 px-3 py-2 block w-full sm:text-sm border-none focus:ring-0 outline-none !rounded-r-md !outline-none items-center !border !border-gray-200 rounded-md ${errorMsg ? 'border-red-500' : ''} hover:border-gray-400 focus-within:border-gray-500` }
|
||||||
{errorMsg && <p className="mt-2 text-sm text-red-600">{errorMsg}</p>}
|
buttonClassName="!h-[38px] !flex !items-center !justify-center !rounded-l-md !border border-gray-200 !border-r-0"
|
||||||
</div>
|
/>
|
||||||
</>
|
|
||||||
)
|
{errorMsg && (
|
||||||
|
<p className="mt-2 text-sm text-red-600">{errorMsg}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,8 @@ import SectionTitle from '@/components/SectionTitle';
|
|||||||
import ProgressStep from '@/components/ProgressStep';
|
import ProgressStep from '@/components/ProgressStep';
|
||||||
import logger from '@/utils/logger';
|
import logger from '@/utils/logger';
|
||||||
import Popup from '@/components/Popup';
|
import Popup from '@/components/Popup';
|
||||||
|
import InputPhone from '../InputPhone';
|
||||||
|
import { PhoneLabel } from '../PhoneLabel';
|
||||||
|
|
||||||
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, profiles, onSubmit, currentStep, groups, showOnlyStep2 = false }) => {
|
const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, registrationFees, tuitionFees, profiles, onSubmit, currentStep, groups, showOnlyStep2 = false }) => {
|
||||||
const [formData, setFormData] = useState(() => {
|
const [formData, setFormData] = useState(() => {
|
||||||
@ -66,7 +68,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
|
|
||||||
const isStep1Valid = formData.studentLastName && formData.studentFirstName;
|
const isStep1Valid = formData.studentLastName && formData.studentFirstName;
|
||||||
const isStep2Valid = (
|
const isStep2Valid = (
|
||||||
formData.selectedGuardians.length > 0 ||
|
formData.selectedGuardians.length > 0 ||
|
||||||
(!formData.emailError && formData.guardianEmail.length > 0 && filteredStudents.length === 0)
|
(!formData.emailError && formData.guardianEmail.length > 0 && filteredStudents.length === 0)
|
||||||
);
|
);
|
||||||
const isStep3Valid = formData.selectedRegistrationFees?.length > 0;
|
const isStep3Valid = formData.selectedRegistrationFees?.length > 0;
|
||||||
@ -127,7 +129,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
|
|
||||||
const validateAndSubmit = async () => {
|
const validateAndSubmit = async () => {
|
||||||
const existingProfile = profiles.find(profile => profile.email === formData.guardianEmail);
|
const existingProfile = profiles.find(profile => profile.email === formData.guardianEmail);
|
||||||
|
|
||||||
if (existingProfile) {
|
if (existingProfile) {
|
||||||
console.log('existingProfile : ', existingProfile);
|
console.log('existingProfile : ', existingProfile);
|
||||||
await setFormData((prevData) => ({
|
await setFormData((prevData) => ({
|
||||||
@ -137,7 +139,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
existingProfileId: existingProfile.id,
|
existingProfileId: existingProfile.id,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utiliser la dernière version de formData via formDataRef
|
// Utiliser la dernière version de formData via formDataRef
|
||||||
logger.debug('Submitting form data:', formDataRef.current);
|
logger.debug('Submitting form data:', formDataRef.current);
|
||||||
onSubmit(formDataRef.current);
|
onSubmit(formDataRef.current);
|
||||||
@ -146,7 +148,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
const nextStep = async () => {
|
const nextStep = async () => {
|
||||||
if (step === 2) {
|
if (step === 2) {
|
||||||
const existingProfile = profiles.find(profile => profile.email === formData.guardianEmail);
|
const existingProfile = profiles.find(profile => profile.email === formData.guardianEmail);
|
||||||
|
|
||||||
if (existingProfile) {
|
if (existingProfile) {
|
||||||
console.log('existingProfile : ', existingProfile);
|
console.log('existingProfile : ', existingProfile);
|
||||||
await setFormData((prevData) => ({
|
await setFormData((prevData) => ({
|
||||||
@ -157,7 +159,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!showOnlyStep2 && step < steps.length) {
|
if (!showOnlyStep2 && step < steps.length) {
|
||||||
setStep(step + 1);
|
setStep(step + 1);
|
||||||
}
|
}
|
||||||
@ -184,16 +186,16 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
const selectedGuardians = isSelected
|
const selectedGuardians = isSelected
|
||||||
? prevData.selectedGuardians.filter(id => id !== guardianId) // Retirer le guardian si déjà sélectionné
|
? prevData.selectedGuardians.filter(id => id !== guardianId) // Retirer le guardian si déjà sélectionné
|
||||||
: [...prevData.selectedGuardians, guardianId]; // Ajouter le guardian s'il n'est pas sélectionné
|
: [...prevData.selectedGuardians, guardianId]; // Ajouter le guardian s'il n'est pas sélectionné
|
||||||
|
|
||||||
// Mettre à jour l'email uniquement si un guardian est sélectionné
|
// Mettre à jour l'email uniquement si un guardian est sélectionné
|
||||||
const updatedGuardianEmail = isSelected ? '' : guardianEmail;
|
const updatedGuardianEmail = isSelected ? '' : guardianEmail;
|
||||||
|
|
||||||
// Si aucun guardian n'est sélectionné, réinitialiser le tableau des élèves
|
// Si aucun guardian n'est sélectionné, réinitialiser le tableau des élèves
|
||||||
if (selectedGuardians.length === 0) {
|
if (selectedGuardians.length === 0) {
|
||||||
setFilteredStudents(students); // Réafficher tous les élèves
|
setFilteredStudents(students); // Réafficher tous les élèves
|
||||||
setSelectedEleve(null);
|
setSelectedEleve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...prevData,
|
...prevData,
|
||||||
selectedGuardians,
|
selectedGuardians,
|
||||||
@ -361,11 +363,9 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full mt-4"
|
className="w-full mt-4"
|
||||||
/>
|
/>
|
||||||
<InputTextIcon
|
<InputPhone
|
||||||
name="guardianPhone"
|
name="guardianPhone"
|
||||||
type="tel"
|
label={t('Numéro de téléphone (optionnel)')}
|
||||||
IconItem={Phone}
|
|
||||||
placeholder="Numéro de téléphone (optionnel)"
|
|
||||||
value={formData.guardianPhone}
|
value={formData.guardianPhone}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
className="w-full mt-4"
|
className="w-full mt-4"
|
||||||
@ -385,7 +385,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
setFormData((prevData) => ({
|
setFormData((prevData) => ({
|
||||||
...prevData,
|
...prevData,
|
||||||
guardianEmail: email,
|
guardianEmail: email,
|
||||||
emailError:
|
emailError:
|
||||||
email.length > 0 && // Le champ de mail est non null
|
email.length > 0 && // Le champ de mail est non null
|
||||||
(!emailRegex.test(email) && filteredStudents.length === 0) // Format invalide ou aucun résultat
|
(!emailRegex.test(email) && filteredStudents.length === 0) // Format invalide ou aucun résultat
|
||||||
? "Format d'email invalide ou aucun élève trouvé"
|
? "Format d'email invalide ou aucun élève trouvé"
|
||||||
@ -661,7 +661,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td className="px-4 py-2 border">{formData.guardianEmail}</td>
|
<td className="px-4 py-2 border">{formData.guardianEmail}</td>
|
||||||
<td className="px-4 py-2 border">{formData.guardianPhone}</td>
|
<td className="px-4 py-2 border"><PhoneLabel phoneNumber={formData.guardianPhone} /></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -781,7 +781,7 @@ const InscriptionForm = ( { students, registrationDiscounts, tuitionDiscounts, r
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Popup
|
<Popup
|
||||||
visible={popupVisible}
|
visible={popupVisible}
|
||||||
message={popupMessage}
|
message={popupMessage}
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import React from 'react';
|
|||||||
import SelectChoice from '@/components/SelectChoice';
|
import SelectChoice from '@/components/SelectChoice';
|
||||||
|
|
||||||
export default function PaymentMethodSelector({ formData, title, name, updateFormField, selected, paymentModes, paymentModesOptions, amount, getError }) {
|
export default function PaymentMethodSelector({ formData, title, name, updateFormField, selected, paymentModes, paymentModesOptions, amount, getError }) {
|
||||||
console.log(paymentModes)
|
//console.log(paymentModes)
|
||||||
console.log(selected)
|
//console.log(selected)
|
||||||
return (
|
return (
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
<div className="bg-white p-6 rounded-lg shadow-sm border border-gray-200">
|
||||||
{/* Titre */}
|
{/* Titre */}
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import InputPhone from '@/components/InputPhone';
|
|||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import 'react-phone-number-input/style.css'
|
|
||||||
import { Trash2, Plus } from 'lucide-react';
|
import { Trash2, Plus } from 'lucide-react';
|
||||||
|
|
||||||
export default function ResponsableInputFields({guardians, onGuardiansChange, addGuardian, deleteGuardian, errors = []}) {
|
export default function ResponsableInputFields({guardians, onGuardiansChange, addGuardian, deleteGuardian, errors = []}) {
|
||||||
|
|||||||
7
Front-End/src/components/PhoneLabel.js
Normal file
7
Front-End/src/components/PhoneLabel.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { formatPhoneNumber } from "@/utils/Telephone";
|
||||||
|
|
||||||
|
export function PhoneLabel({phoneNumber}){
|
||||||
|
return (
|
||||||
|
<a className="text-sm font-semibold text-gray-800" href={"tel:"+phoneNumber}>{formatPhoneNumber(phoneNumber)}</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,36 +1,49 @@
|
|||||||
|
|
||||||
const localePrefixes = {
|
/**
|
||||||
"fr-FR": "+33",
|
*
|
||||||
// Ajoutez d'autres locales et leurs préfixes ici
|
* @param {*} phoneString au format E.164
|
||||||
};
|
* @param {*} toFormat L=Country code, X=Number Format="LX XX XX XX XX"
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export function formatPhoneNumber(phoneString, fromFormat = 'XX-XX-XX-XX-XX', toFormat = 'LX-XX-XX-XX-XX', locale = "fr-FR") {
|
export function formatPhoneNumber(phoneString, toFormat = 'LX XX XX XX XX') {
|
||||||
if (!phoneString) return;
|
if (!phoneString) return;
|
||||||
// Extraire les chiffres du numéro de téléphone
|
// Vérifier si le numéro est au format international
|
||||||
const digits = phoneString.replace(/\D/g, '');
|
if(!validateE164PhoneNumber(phoneString)){
|
||||||
|
return phoneString;
|
||||||
// Déterminer le préfixe international en fonction de la locale
|
|
||||||
|
|
||||||
|
|
||||||
let prefix = localePrefixes[locale] || '';
|
|
||||||
|
|
||||||
// Si le format d'entrée commence par 'L', détecter la locale
|
|
||||||
if (fromFormat.startsWith('L')) {
|
|
||||||
const detectedPrefix = phoneString.match(/^\+\d+/);
|
|
||||||
if (detectedPrefix) {
|
|
||||||
prefix = detectedPrefix[0];
|
|
||||||
phoneString = phoneString.replace(prefix, '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
const matches = phoneString.match(/^\+(\d{1,3})(\d{9})$/);
|
||||||
|
if (!matches) return phoneString;
|
||||||
|
|
||||||
// Remplacer 'L' par le préfixe et 'X' par les chiffres du numéro de téléphone
|
const [_, countryCode, number] = matches;
|
||||||
|
const prefix = `+${countryCode}`;
|
||||||
|
const digits = number;
|
||||||
|
|
||||||
|
// Initialiser le numéro formaté avec le préfixe
|
||||||
let formattedNumber = toFormat.replace('L', prefix);
|
let formattedNumber = toFormat.replace('L', prefix);
|
||||||
|
|
||||||
let digitIndex = 0;
|
let digitIndex = 0;
|
||||||
|
|
||||||
formattedNumber = formattedNumber.replace(/X/g, () => {
|
|
||||||
|
// Remplacer les X par les chiffres
|
||||||
|
formattedNumber = formattedNumber.replace(/X/g, (match, offset) => {
|
||||||
|
// Si c'est le dernier groupe de X, mettre tous les chiffres restants
|
||||||
|
if (offset === formattedNumber.lastIndexOf('X') - match.length + 1) {
|
||||||
|
const remainingDigits = digits.substring(digitIndex);
|
||||||
|
digitIndex += remainingDigits.length;
|
||||||
|
return remainingDigits;
|
||||||
|
}
|
||||||
|
// Sinon, mettre un seul chiffre
|
||||||
return digits[digitIndex++] || '';
|
return digits[digitIndex++] || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
return formattedNumber;
|
return formattedNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fonction pour valider un numéro de téléphone au format E.164
|
||||||
|
// Le format E.164 est un format international pour les numéros de téléphone
|
||||||
|
// qui commence par un signe '+' suivi du code pays et du numéro de téléphone
|
||||||
|
// Par exemple : +33123456789 pour un numéro français
|
||||||
|
export function validateE164PhoneNumber(phoneNumber) {
|
||||||
|
const regEx = /^\+[1-9]\d{9,14}$/;
|
||||||
|
return regEx.test(phoneNumber);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user