mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-29 07:53:23 +00:00
fix: Ajout du mode Visu
This commit is contained in:
@ -11,6 +11,7 @@ export default function FilesToUpload({
|
||||
uploadedFiles,
|
||||
onFileUpload,
|
||||
onFileDelete,
|
||||
enable = true,
|
||||
}) {
|
||||
const [selectedFile, setSelectedFile] = useState(null); // État pour le fichier sélectionné
|
||||
const [actionType, setActionType] = useState(null);
|
||||
@ -124,41 +125,43 @@ export default function FilesToUpload({
|
||||
>
|
||||
<Eye className="w-5 h-5" />
|
||||
</button>
|
||||
<button
|
||||
className="flex items-center justify-center w-8 h-8 rounded-full text-red-500 hover:text-red-700"
|
||||
onClick={() => {
|
||||
setRemovePopupVisible(true);
|
||||
setRemovePopupMessage(
|
||||
`Êtes-vous sûr(e) de vouloir supprimer le fichier "${row.master_name}" ?`
|
||||
);
|
||||
setRemovePopupOnConfirm(() => () => {
|
||||
onFileDelete(row.id)
|
||||
.then(() => {
|
||||
setPopupMessage(
|
||||
`Le fichier "${row.master_name}" a été supprimé avec succès.`
|
||||
);
|
||||
setPopupVisible(true);
|
||||
setRemovePopupVisible(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(
|
||||
'Erreur lors de la suppression du fichier :',
|
||||
error
|
||||
);
|
||||
setPopupMessage(
|
||||
`Erreur lors de la suppression du fichier "${row.master_name}".`
|
||||
);
|
||||
setPopupVisible(true);
|
||||
setRemovePopupVisible(false);
|
||||
});
|
||||
setActionType(null);
|
||||
setSelectedFile(null);
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Trash2 className="w-5 h-5" />
|
||||
</button>
|
||||
{enable && (
|
||||
<button
|
||||
className="flex items-center justify-center w-8 h-8 rounded-full text-red-500 hover:text-red-700"
|
||||
onClick={() => {
|
||||
setRemovePopupVisible(true);
|
||||
setRemovePopupMessage(
|
||||
`Êtes-vous sûr(e) de vouloir supprimer le fichier "${row.master_name}" ?`
|
||||
);
|
||||
setRemovePopupOnConfirm(() => () => {
|
||||
onFileDelete(row.id)
|
||||
.then(() => {
|
||||
setPopupMessage(
|
||||
`Le fichier "${row.master_name}" a été supprimé avec succès.`
|
||||
);
|
||||
setPopupVisible(true);
|
||||
setRemovePopupVisible(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(
|
||||
'Erreur lors de la suppression du fichier :',
|
||||
error
|
||||
);
|
||||
setPopupMessage(
|
||||
`Erreur lors de la suppression du fichier "${row.master_name}".`
|
||||
);
|
||||
setPopupVisible(true);
|
||||
setRemovePopupVisible(false);
|
||||
});
|
||||
setActionType(null);
|
||||
setSelectedFile(null);
|
||||
});
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Trash2 className="w-5 h-5" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{!uploadedFile && (
|
||||
@ -218,7 +221,7 @@ export default function FilesToUpload({
|
||||
border: 'none',
|
||||
}}
|
||||
/>
|
||||
) : actionType === 'upload' ? (
|
||||
) : actionType === 'upload' && enable ? (
|
||||
<FileUpload
|
||||
selectionMessage={`Téléversez le fichier ${selectedFile.master_name}`}
|
||||
onFileSelect={(file) => handleUpload(file, selectedFile)}
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
fetchRegistrationPaymentPlans,
|
||||
fetchTuitionPaymentPlans,
|
||||
} from '@/app/actions/schoolAction';
|
||||
import { BASE_URL } from '@/utils/Url';
|
||||
import { BASE_URL, FE_PARENTS_HOME_URL } from '@/utils/Url';
|
||||
import logger from '@/utils/logger';
|
||||
import FilesToUpload from '@/components/Inscription/FilesToUpload';
|
||||
import { DocusealForm } from '@docuseal/react';
|
||||
@ -27,6 +27,7 @@ import SiblingInputFields from '@/components/Inscription/SiblingInputFields';
|
||||
import PaymentMethodSelector from '@/components/Inscription/PaymentMethodSelector';
|
||||
import ProgressStep from '@/components/ProgressStep';
|
||||
import { CheckCircle, Hourglass } from 'lucide-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
/**
|
||||
* Composant de formulaire d'inscription partagé
|
||||
@ -42,6 +43,7 @@ export default function InscriptionFormShared({
|
||||
selectedEstablishmentId,
|
||||
onSubmit,
|
||||
errors = {}, // Nouvelle prop pour les erreurs
|
||||
enable = true,
|
||||
}) {
|
||||
// États pour gérer les données du formulaire
|
||||
const [formData, setFormData] = useState({
|
||||
@ -85,6 +87,20 @@ export default function InscriptionFormShared({
|
||||
// État pour suivre l'index du fichier en cours
|
||||
const [currentTemplateIndex, setCurrentTemplateIndex] = useState(0);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// Mettre à jour les états en fonction de la valeur de `enable`
|
||||
useEffect(() => {
|
||||
if (!enable) {
|
||||
setIsPage1Valid(true);
|
||||
setIsPage2Valid(true);
|
||||
setIsPage3Valid(true);
|
||||
setIsPage4Valid(true);
|
||||
setIsPage5Valid(true);
|
||||
setIsPage6Valid(true);
|
||||
}
|
||||
}, [enable]);
|
||||
|
||||
useEffect(() => {
|
||||
// Trouver le premier template non signé
|
||||
const firstUnsignedIndex = schoolFileTemplates.findIndex(
|
||||
@ -465,10 +481,7 @@ export default function InscriptionFormShared({
|
||||
setStep={setCurrentPage}
|
||||
isStepValid={isStepValid}
|
||||
/>
|
||||
<div
|
||||
className="flex-1 overflow-y-auto mt-12 "
|
||||
style={{ maxHeight: 'calc(100vh - 400px)' }}
|
||||
>
|
||||
<div className="flex-1 h-full mt-12 ">
|
||||
{/* Page 1 : Informations sur l'élève */}
|
||||
{currentPage === 1 && (
|
||||
<StudentInfoForm
|
||||
@ -482,6 +495,7 @@ export default function InscriptionFormShared({
|
||||
setIsPageValid={setIsPage1Valid}
|
||||
hasInteracted={hasInteracted}
|
||||
setHasInteracted={setHasInteracted}
|
||||
enable={enable}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -492,6 +506,7 @@ export default function InscriptionFormShared({
|
||||
setGuardians={setGuardians}
|
||||
errors={errors}
|
||||
setIsPageValid={setIsPage2Valid}
|
||||
enable={enable}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -503,6 +518,7 @@ export default function InscriptionFormShared({
|
||||
setFormData={setFormData}
|
||||
errors={errors.siblings || []}
|
||||
setIsPageValid={setIsPage3Valid}
|
||||
enable={enable}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -518,6 +534,7 @@ export default function InscriptionFormShared({
|
||||
tuitionPaymentPlans={tuitionPaymentPlans}
|
||||
errors={errors}
|
||||
setIsPageValid={setIsPage4Valid}
|
||||
enable={enable}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@ -605,66 +622,67 @@ export default function InscriptionFormShared({
|
||||
)}
|
||||
|
||||
{/* Dernière page : Section Fichiers parents */}
|
||||
{currentPage === 5 && (
|
||||
{currentPage === 6 && (
|
||||
<FilesToUpload
|
||||
parentFileTemplates={parentFileTemplates}
|
||||
uploadedFiles={uploadedFiles}
|
||||
onFileUpload={handleFileUpload}
|
||||
onFileDelete={handleDeleteFile}
|
||||
enable={enable}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Boutons de contrôle */}
|
||||
<div className="flex justify-center space-x-4 mt-12">
|
||||
{currentPage > 1 && (
|
||||
{enable ? (
|
||||
<>
|
||||
{currentPage > 1 && (
|
||||
<Button
|
||||
text="Précédent"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviousPage();
|
||||
}}
|
||||
primary
|
||||
/>
|
||||
)}
|
||||
{currentPage < steps.length && (
|
||||
<Button
|
||||
text="Suivant"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleNextPage();
|
||||
}}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid) ||
|
||||
(currentPage === 5 && !isPage5Valid) ||
|
||||
(currentPage === 6 && !isPage6Valid)
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid) ||
|
||||
(currentPage === 5 && !isPage5Valid) ||
|
||||
(currentPage === 6 && !isPage6Valid)
|
||||
}
|
||||
primary
|
||||
name="Next"
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
text="Précédent"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handlePreviousPage();
|
||||
}}
|
||||
onClick={() => router.push(FE_PARENTS_HOME_URL)}
|
||||
text="Quitter"
|
||||
primary
|
||||
/>
|
||||
)}
|
||||
{currentPage < steps.length && (
|
||||
<Button
|
||||
text="Suivant"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleNextPage();
|
||||
}}
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid) ||
|
||||
(currentPage === 5 && !isPage5Valid)
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={
|
||||
(currentPage === 1 && !isPage1Valid) ||
|
||||
(currentPage === 2 && !isPage2Valid) ||
|
||||
(currentPage === 3 && !isPage3Valid) ||
|
||||
(currentPage === 4 && !isPage4Valid) ||
|
||||
(currentPage === 5 && !isPage5Valid)
|
||||
}
|
||||
primary
|
||||
name="Next"
|
||||
/>
|
||||
)}
|
||||
{currentPage === steps.length && (
|
||||
<Button
|
||||
onClick={handleSubmit}
|
||||
text="Valider"
|
||||
primary
|
||||
className={`px-4 py-2 rounded-md shadow-sm focus:outline-none ${
|
||||
currentPage === 6 && !isPage6Valid
|
||||
? 'bg-gray-300 text-gray-700 cursor-not-allowed'
|
||||
: 'bg-emerald-500 text-white hover:bg-emerald-600'
|
||||
}`}
|
||||
disabled={currentPage === 6 && !isPage6Valid}
|
||||
className="bg-emerald-500 text-white hover:bg-emerald-600"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -11,6 +11,7 @@ export default function PaymentMethodSelector({
|
||||
tuitionPaymentPlans,
|
||||
errors,
|
||||
setIsPageValid,
|
||||
enable = true,
|
||||
}) {
|
||||
useEffect(() => {
|
||||
const isValid = !Object.keys(formData).some(
|
||||
@ -94,6 +95,7 @@ export default function PaymentMethodSelector({
|
||||
errorMsg={getError('registration_payment')}
|
||||
errorLocalMsg={getLocalError('registration_payment')}
|
||||
required
|
||||
disabled={!enable}
|
||||
/>
|
||||
|
||||
<RadioList
|
||||
@ -122,6 +124,7 @@ export default function PaymentMethodSelector({
|
||||
}}
|
||||
fieldName="registration_payment_plan"
|
||||
className="mt-4"
|
||||
disabled={!enable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -155,6 +158,7 @@ export default function PaymentMethodSelector({
|
||||
errorMsg={getError('tuition_payment')}
|
||||
errorLocalMsg={getLocalError('tuition_payment')}
|
||||
required
|
||||
disabled={!enable}
|
||||
/>
|
||||
|
||||
<RadioList
|
||||
@ -179,6 +183,7 @@ export default function PaymentMethodSelector({
|
||||
getError('tuition_payment_plan') ||
|
||||
getLocalError('tuition_payment_plan')
|
||||
}
|
||||
disabled={!enable}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -11,6 +11,7 @@ export default function ResponsableInputFields({
|
||||
setGuardians,
|
||||
errors,
|
||||
setIsPageValid,
|
||||
enable = true,
|
||||
}) {
|
||||
const t = useTranslations('ResponsableInputFields');
|
||||
const { selectedEstablishmentId } = useEstablishment();
|
||||
@ -145,6 +146,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('last_name')}
|
||||
errorLocalMsg={getLocalError(index, 'last_name')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="prenomResponsable"
|
||||
@ -157,6 +159,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('first_name')}
|
||||
errorLocalMsg={getLocalError(index, 'first_name')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -176,6 +179,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('associated_profile_email')}
|
||||
errorLocalMsg={getLocalError(index, 'associated_profile_email')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
<InputPhone
|
||||
name="telephoneResponsable"
|
||||
@ -187,6 +191,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('phone')}
|
||||
errorLocalMsg={getLocalError(index, 'phone')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -202,6 +207,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('birth_date')}
|
||||
errorLocalMsg={getLocalError(index, 'birth_date')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="professionResponsable"
|
||||
@ -214,6 +220,7 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('profession')}
|
||||
errorLocalMsg={getLocalError(index, 'profession')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -229,29 +236,32 @@ export default function ResponsableInputFields({
|
||||
errorMsg={getError('address')}
|
||||
errorLocalMsg={getLocalError(index, 'address')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Plus
|
||||
className={`w-8 h-8 ${
|
||||
guardians.length >= MAX_GUARDIANS
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-green-500 cursor-pointer hover:text-green-700'
|
||||
} transition-colors border-2 ${
|
||||
guardians.length >= MAX_GUARDIANS
|
||||
? 'border-gray-400'
|
||||
: 'border-green-500 hover:border-green-700'
|
||||
} rounded-full p-1`}
|
||||
onClick={(e) => {
|
||||
if (guardians.length < MAX_GUARDIANS) {
|
||||
addGuardian(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{enable && (
|
||||
<div className="flex justify-center">
|
||||
<Plus
|
||||
className={`w-8 h-8 ${
|
||||
guardians.length >= MAX_GUARDIANS
|
||||
? 'text-gray-400 cursor-not-allowed'
|
||||
: 'text-green-500 cursor-pointer hover:text-green-700'
|
||||
} transition-colors border-2 ${
|
||||
guardians.length >= MAX_GUARDIANS
|
||||
? 'border-gray-400'
|
||||
: 'border-green-500 hover:border-green-700'
|
||||
} rounded-full p-1`}
|
||||
onClick={(e) => {
|
||||
if (guardians.length < MAX_GUARDIANS) {
|
||||
addGuardian(e);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ export default function SiblingInputFields({
|
||||
setFormData,
|
||||
errors,
|
||||
setIsPageValid,
|
||||
enable = true,
|
||||
}) {
|
||||
const getError = (index, field) => {
|
||||
return errors[index]?.[field]?.[0];
|
||||
@ -121,6 +122,7 @@ export default function SiblingInputFields({
|
||||
errorMsg={getError('last_name')}
|
||||
errorLocalMsg={getLocalError(index, 'last_name')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="first_name"
|
||||
@ -133,6 +135,7 @@ export default function SiblingInputFields({
|
||||
errorMsg={getError('first_name')}
|
||||
errorLocalMsg={getLocalError(index, 'first_name')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -148,17 +151,20 @@ export default function SiblingInputFields({
|
||||
errorMsg={getError('birth_date')}
|
||||
errorLocalMsg={getLocalError(index, 'birth_date')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="flex justify-center">
|
||||
<Plus
|
||||
className="w-8 h-8 text-green-500 cursor-pointer hover:text-green-700 transition-colors border-2 border-green-500 hover:border-green-700 rounded-full p-1"
|
||||
onClick={addSibling}
|
||||
/>
|
||||
</div>
|
||||
{enable && (
|
||||
<div className="flex justify-center">
|
||||
<Plus
|
||||
className="w-8 h-8 text-green-500 cursor-pointer hover:text-green-700 transition-colors border-2 border-green-500 hover:border-green-700 rounded-full p-1"
|
||||
onClick={addSibling}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -36,6 +36,7 @@ export default function StudentInfoForm({
|
||||
setIsPageValid,
|
||||
hasInteracted,
|
||||
setHasInteracted,
|
||||
enable = true,
|
||||
}) {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
@ -181,6 +182,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('last_name')}
|
||||
errorLocalMsg={getLocalError('last_name')}
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="first_name"
|
||||
@ -190,6 +192,7 @@ export default function StudentInfoForm({
|
||||
errorMsg={getError('first_name')}
|
||||
errorLocalMsg={getLocalError('first_name')}
|
||||
required
|
||||
enable={enable}
|
||||
/>
|
||||
<SelectChoice
|
||||
name="gender"
|
||||
@ -201,6 +204,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('gender')}
|
||||
errorLocalMsg={getLocalError('gender')}
|
||||
disabled={!enable}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
@ -213,6 +217,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('birth_date')}
|
||||
errorLocalMsg={getLocalError('birth_date')}
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="birth_place"
|
||||
@ -222,6 +227,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('birth_place')}
|
||||
errorLocalMsg={getLocalError('birth_place')}
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="birth_postal_code"
|
||||
@ -231,6 +237,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('birth_postal_code')}
|
||||
errorLocalMsg={getLocalError('birth_postal_code')}
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
@ -242,6 +249,7 @@ export default function StudentInfoForm({
|
||||
onChange={(e) => onChange('nationality', e.target.value)}
|
||||
errorMsg={getError('nationality')}
|
||||
errorLocalMsg={getLocalError('nationality')}
|
||||
enable={enable}
|
||||
/>
|
||||
<InputText
|
||||
name="address"
|
||||
@ -251,6 +259,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('address')}
|
||||
errorLocalMsg={getLocalError('address')}
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
@ -262,6 +271,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('attending_physician')}
|
||||
errorLocalMsg={getLocalError('attending_physician')}
|
||||
enable={enable}
|
||||
/>
|
||||
<SelectChoice
|
||||
name="level"
|
||||
@ -273,6 +283,7 @@ export default function StudentInfoForm({
|
||||
required
|
||||
errorMsg={getError('level')}
|
||||
errorLocalMsg={getLocalError('level')}
|
||||
disabled={!enable}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-1 gap-8">
|
||||
@ -281,6 +292,7 @@ export default function StudentInfoForm({
|
||||
onFileSelect={(file) => handlePhotoUpload(file)}
|
||||
existingFile={formData.photo}
|
||||
errorMsg={getError('photo')}
|
||||
enable={enable}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user