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",