diff --git a/back/config/plugins.js b/back/config/plugins.js index 7525c97..49816e2 100644 --- a/back/config/plugins.js +++ b/back/config/plugins.js @@ -19,7 +19,7 @@ module.exports = ({ env }) => ({ }, }, upload: { - provider: process.env.NODE_ENV === 'development' ? 'local' : 'do', + provider: 'do', providerOptions: { key: process.env.DO_SPACE_ACCESS_KEY, secret: process.env.DO_SPACE_SECRET_KEY, diff --git a/web/components/Campaign/Places/Application/CampaignApplicationSchedule.tsx b/web/components/Campaign/Places/Application/CampaignApplicationSchedule.tsx index 7a9e1f9..5e1b911 100644 --- a/web/components/Campaign/Places/Application/CampaignApplicationSchedule.tsx +++ b/web/components/Campaign/Places/Application/CampaignApplicationSchedule.tsx @@ -46,7 +46,7 @@ const CampaignApplicationSchedule = ({ > {t('detail.campaign.slots_available')} - + {disponibilities?.map((disponibility) => ( diff --git a/web/components/Campaign/Places/Application/CampaignApplicationScheduleItem.tsx b/web/components/Campaign/Places/Application/CampaignApplicationScheduleItem.tsx index 08e631d..9f7e6cb 100644 --- a/web/components/Campaign/Places/Application/CampaignApplicationScheduleItem.tsx +++ b/web/components/Campaign/Places/Application/CampaignApplicationScheduleItem.tsx @@ -1,6 +1,7 @@ import { Checkbox, HStack, VStack, Text } from '@chakra-ui/react' import { useTranslation } from 'next-i18next' import { useContext, useMemo } from 'react' +import useCampaignContext from '~components/Campaign/useCampaignContext' import BookingScheduleContext from '~components/Place/Booking/BookingScheduleContext' import { useCurrentUser } from '~hooks/useCurrentUser' import { Disponibility } from '~typings/api' @@ -20,6 +21,7 @@ const CampaignApplicationScheduleItem = ({ }: { disponibility: Disponibility }) => { + const { currentCampaign } = useCampaignContext() const { canApply, applications, data: user } = useCurrentUser() const { selected, setSelected } = useContext(BookingScheduleContext) const { t } = useTranslation('place') @@ -77,12 +79,17 @@ const CampaignApplicationScheduleItem = ({ [selected, disponibility], ) - const isDisabled = - !!user && - (!canApply || - applications?.find( - (application) => application?.disponibility === disponibility.id, - )) + const hasAlreadyApplied = applications?.find( + (application) => application?.disponibility === disponibility.id, + ) + + const hasReachedMax = + !selected + ?.map((s) => s?.extendedProps?.id.toString()) + ?.includes(disponibility.id.toString()) && + selected?.length + applications?.length >= currentCampaign?.applications_max + + const isDisabled = !!user && (!canApply || hasAlreadyApplied || hasReachedMax) const handleClick = (e) => { if (!isDisabled) { diff --git a/web/components/Campaign/Places/Application/LockedApplications.tsx b/web/components/Campaign/Places/Application/LockedApplications.tsx index fe23902..a10095a 100644 --- a/web/components/Campaign/Places/Application/LockedApplications.tsx +++ b/web/components/Campaign/Places/Application/LockedApplications.tsx @@ -1,38 +1,96 @@ import { Box, Text } from '@chakra-ui/react' import { useTranslation } from 'next-i18next' +import { useContext, useMemo } from 'react' import useCampaignContext from '~components/Campaign/useCampaignContext' import Link from '~components/Link' +import BookingScheduleContext from '~components/Place/Booking/BookingScheduleContext' import { ROUTE_ACCOUNT_MY_APPLICATIONS } from '~constants' import { useCurrentUser } from '~hooks/useCurrentUser' +import { Disponibility } from '~typings/api' -const LockedApplications = () => { +const LockedApplications = ({ + disponibilities, +}: { + disponibilities: Disponibility[] +}) => { const { t } = useTranslation('place') - const { data: user, canApply, applications } = useCurrentUser() + const { + data: user, + canApply, + applications, + remainingApplications, + } = useCurrentUser() const { currentCampaign } = useCampaignContext() - if (!canApply && user?.type === 'company') + const { selected } = useContext(BookingScheduleContext) + + const unselectedDisponibilities = useMemo( + () => + disponibilities + .map((d) => d?.id) + ?.filter( + (d) => + !selected + ?.map((s) => s?.extendedProps?.id.toString()) + ?.includes(d.toString()), + ), + [disponibilities, selected], + ) + const hasReachedMax = + selected?.length + applications?.length >= + currentCampaign?.applications_max && unselectedDisponibilities?.length > 0 + + if (hasReachedMax) { + const plural = remainingApplications === 1 ? 'singular' : 'plural' + return ( + + + {t(`detail.campaign.locked_application_start_remaining_${plural}`, { + nb: remainingApplications, + })} + + + {t(`detail.campaign.locked_application_middle`, { + title: currentCampaign?.title, + })} + + + + {t(`detail.campaign.locked_application_cta_${plural}`)} + + + + {t(`detail.campaign.locked_application_remaining_end`)} + + + ) + } + + if (!canApply && user?.type === 'company') { + const plural = applications?.length === 1 ? 'singular' : 'plural' return ( - {t('detail.campaign.locked_application_start', { + {t(`detail.campaign.locked_application_start_${plural}`, { nb: applications?.length, })} - {t('detail.campaign.locked_application_middle', { + {t(`detail.campaign.locked_application_middle`, { title: currentCampaign?.title, })} - {t('detail.campaign.locked_application_cta')} + {t(`detail.campaign.locked_application_cta_${plural}`)} - {t('detail.campaign.locked_application_end')} + {t(`detail.campaign.locked_application_end`)} ) + } return null } diff --git a/web/public/locales/fr/place.json b/web/public/locales/fr/place.json index f45b84f..137c875 100644 --- a/web/public/locales/fr/place.json +++ b/web/public/locales/fr/place.json @@ -351,10 +351,15 @@ "no_scene_grid": "Pas de grille scénique possible.", "closed_on": "(fermeture le {{days}})" }, - "locked_application_start": "Vous avez déjà postulé à {{nb}} créneaux", + "locked_application_start_plural": "Vous avez déjà postulé à {{nb}} créneaux", + "locked_application_start_remaining_plural": "Vous pouvez encore postuler à {{nb}} créneaux", + "locked_application_start_singular": "Vous avez déjà postulé à {{nb}} créneau", + "locked_application_start_remaining_singular": "Vous pouvez encore postuler à {{nb}} créneau", "locked_application_middle": "pour cette session du dispositif {{title}}.", - "locked_application_cta": "Annulez l’une de vos candidatures en attente", - "locked_application_end": "pour pouvoir postuler aux créneaux de cet espace." + "locked_application_cta_plural": "Annulez l’une de vos candidatures en attente", + "locked_application_cta_singular": "Annulez votre candidature en attente", + "locked_application_end": "pour pouvoir postuler à un ou plusieurs des créneaux de cet espace.", + "locked_application_remaining_end": "pour pouvoir postuler à plus de créneaux de cet espace." }, "back": "Retour à la recherche", "seeMap": "Voir sur la carte",