diff --git a/web/components/Account/Application/Company/ApplicationCompanyList.tsx b/web/components/Account/Application/Company/ApplicationCompanyList.tsx index dbad50d6..b7b983cd 100644 --- a/web/components/Account/Application/Company/ApplicationCompanyList.tsx +++ b/web/components/Account/Application/Company/ApplicationCompanyList.tsx @@ -58,7 +58,10 @@ const ApplicationCompanyList = ({ applications = [] }: Props) => { {t('company.title', { title: currentCampaign?.title })} - + {t('company.table.head.number')} diff --git a/web/components/Account/Application/Company/ApplicationsHelpers/ApplicationCompanyHelper.tsx b/web/components/Account/Application/Company/ApplicationsHelpers/ApplicationCompanyHelper.tsx index 11fa2644..153f9e37 100644 --- a/web/components/Account/Application/Company/ApplicationsHelpers/ApplicationCompanyHelper.tsx +++ b/web/components/Account/Application/Company/ApplicationsHelpers/ApplicationCompanyHelper.tsx @@ -1,21 +1,30 @@ -import { Box, Button, Stack, Text } from '@chakra-ui/react' -import { useTranslation } from 'next-i18next' import useCampaignContext from '~components/Campaign/useCampaignContext' -import { ROUTE_PLACES } from '~constants' import { useCurrentUser } from '~hooks/useCurrentUser' -import { format } from '~utils/date' -import Link from '~components/Link' import OpenApplications from '~components/Account/Application/Company/ApplicationsHelpers/OpenApplications' import ClosedApplications from '~components/Account/Application/Company/ApplicationsHelpers/ClosedApplications' +import { getEndDateTime } from '~components/Campaign/CampaignProvider' +import FullApplications from '~components/Account/Application/Company/ApplicationsHelpers/FullApplications' const ApplicationCompanyHelper = () => { - const { remainingApplications } = useCurrentUser() + const { remainingApplications, applications } = useCurrentUser() const { currentCampaign } = useCampaignContext() - const { t } = useTranslation('application') + const today = new Date() + + if ( + applications.length > 0 && + !remainingApplications && + currentCampaign.mode === 'applications' + ) { + return + } + if (remainingApplications > 0 && currentCampaign.mode === 'applications') return - if (currentCampaign.mode === 'preselections') { + if ( + today <= getEndDateTime(currentCampaign.preselection_end) && + today >= getEndDateTime(currentCampaign.application_end) + ) { return } return null diff --git a/web/components/Account/Application/Company/ApplicationsHelpers/FullApplications.tsx b/web/components/Account/Application/Company/ApplicationsHelpers/FullApplications.tsx new file mode 100644 index 00000000..ebc361cc --- /dev/null +++ b/web/components/Account/Application/Company/ApplicationsHelpers/FullApplications.tsx @@ -0,0 +1,36 @@ +import { Box, Stack, Text } from '@chakra-ui/react' +import { useTranslation } from 'next-i18next' +import useCampaignContext from '~components/Campaign/useCampaignContext' +import { format } from '~utils/date' + +const FullApplications = ({ numApplications }: { numApplications: number }) => { + const { currentCampaign } = useCampaignContext() + const { t } = useTranslation('application') + + return ( + + + + + {t(`company.helper.full_start${numApplications > 1 ? 's' : ''}`)} + + + {t('company.helper.full_end', { + date: format(currentCampaign.preselection_end), + })} + + + + + ) +} + +export default FullApplications diff --git a/web/components/Account/Application/Company/ApplicationsHelpers/OpenApplications.tsx b/web/components/Account/Application/Company/ApplicationsHelpers/OpenApplications.tsx index eaec0175..a9009232 100644 --- a/web/components/Account/Application/Company/ApplicationsHelpers/OpenApplications.tsx +++ b/web/components/Account/Application/Company/ApplicationsHelpers/OpenApplications.tsx @@ -43,6 +43,8 @@ const OpenApplications = ({ size="lg" whiteSpace={'break-spaces'} textAlign="center" + p={4} + height="auto" > {t('company.helper.cta')} diff --git a/web/components/Account/Application/ConfirmButton.tsx b/web/components/Account/Application/ConfirmButton.tsx index bed21b3d..4e08bbf5 100644 --- a/web/components/Account/Application/ConfirmButton.tsx +++ b/web/components/Account/Application/ConfirmButton.tsx @@ -27,7 +27,7 @@ const ConfirmButton = ({ const { isOpen, onClose, onToggle } = useDisclosure() return ( - + {children} diff --git a/web/components/Account/Application/Place/ApplicationPlaceList.tsx b/web/components/Account/Application/Place/ApplicationPlaceList.tsx index 9a2c6cda..633dc7b5 100644 --- a/web/components/Account/Application/Place/ApplicationPlaceList.tsx +++ b/web/components/Account/Application/Place/ApplicationPlaceList.tsx @@ -14,6 +14,7 @@ import Cell from '~components/Account/Booking/Cell' import useCampaignContext from '~components/Campaign/useCampaignContext' import ApplicationPlaceHelper from '~components/Account/Application/Place/ApplicationsHelpers/ApplicationPlaceHelper' import ApplicationPlaceListItem from '~components/Account/Application/Place/ApplicationPlaceListItem' +import useSelectedCampaign from '~hooks/useSelectedCampaign' interface Props { applications: Application[] @@ -24,11 +25,10 @@ const Divider = (props: DividerProps) => ( ) const ApplicationPlaceList = ({ applications = [] }: Props) => { - const { currentCampaign } = useCampaignContext() const { t } = useTranslation('application') const [list, setList] = useState([]) const [isDesc, setDesc] = useState(true) - + const { selectedCampaign } = useSelectedCampaign() useEffect(() => { setList(applications) setDesc(true) @@ -44,8 +44,11 @@ const ApplicationPlaceList = ({ applications = [] }: Props) => { {t('place.table.head.number')} @@ -73,7 +76,7 @@ const ApplicationPlaceList = ({ applications = [] }: Props) => { {t('place.table.head.creation')} - {currentCampaign?.mode === 'preselections' && ( + {['preselections', 'closed']?.includes(selectedCampaign?.mode) && ( diff --git a/web/components/Account/Application/Place/ApplicationPlaceListItem.tsx b/web/components/Account/Application/Place/ApplicationPlaceListItem.tsx index 7f2fa069..4a085f95 100644 --- a/web/components/Account/Application/Place/ApplicationPlaceListItem.tsx +++ b/web/components/Account/Application/Place/ApplicationPlaceListItem.tsx @@ -4,20 +4,15 @@ import { Text, Button, IconButton, HStack } from '@chakra-ui/react' import { useTranslation } from 'next-i18next' import Cell from '~components/Account/Booking/Cell' import Link from '~components/Link' -import useCampaignContext from '~components/Campaign/useCampaignContext' import DownloadApplication from 'public/assets/img/downloadApplication.svg' -import { useRouter } from 'next/router' +import useSelectedCampaign from '~hooks/useSelectedCampaign' interface Props { application: Application } const ApplicationPlaceListItem = ({ application }: Props) => { - const { allPlaceCampaigns } = useCampaignContext() - const { query } = useRouter() - const selectedCampaign = allPlaceCampaigns?.find( - (c) => c.id.toString() === query.campaign.toString(), - ) + const { selectedCampaign } = useSelectedCampaign() const { t } = useTranslation('application') return ( @@ -45,9 +40,8 @@ const ApplicationPlaceListItem = ({ application }: Props) => { {application?.creation_title} - - - {['preselections', 'closed']?.includes(selectedCampaign?.mode) ? ( + {['preselections', 'closed']?.includes(selectedCampaign?.mode) && ( + { {t('place.table.buttons.details')} - ) : ( - '' - )} - + + )} ) } diff --git a/web/components/Account/Application/Place/ApplicationsHelpers/ApplicationPlaceHelper.tsx b/web/components/Account/Application/Place/ApplicationsHelpers/ApplicationPlaceHelper.tsx index 8fc26a86..2fe05cf0 100644 --- a/web/components/Account/Application/Place/ApplicationsHelpers/ApplicationPlaceHelper.tsx +++ b/web/components/Account/Application/Place/ApplicationsHelpers/ApplicationPlaceHelper.tsx @@ -1,25 +1,20 @@ -import useCampaignContext from '~components/Campaign/useCampaignContext' import MissingSelections from '~components/Account/Application/Place/ApplicationsHelpers/MissingSelections' import ConfirmSelections from '~components/Account/Application/Place/ApplicationsHelpers/ConfirmSelections' import ValidatedSelections from '~components/Account/Application/Place/ApplicationsHelpers/ValidatedSelections' import { Application } from '~typings/api' -import { useRouter } from 'next/router' import ClosedCampaign from '~components/Account/Application/Place/ApplicationsHelpers/ClosedCampaign' +import useSelectedCampaign from '~hooks/useSelectedCampaign' const ApplicationPlaceHelper = ({ applications, }: { applications: Application[] }) => { - const { allPlaceCampaigns } = useCampaignContext() const preselections = applications?.filter( (application) => application?.status === 'preselected', ).length - const { query } = useRouter() - const selectedCampaign = allPlaceCampaigns?.find( - (c) => c.id.toString() === query.campaign.toString(), - ) + const { selectedCampaign } = useSelectedCampaign() const missingPreselections = selectedCampaign?.preselections_max - preselections diff --git a/web/components/Account/Application/Place/ApplicationsHelpers/MissingSelections.tsx b/web/components/Account/Application/Place/ApplicationsHelpers/MissingSelections.tsx index 9ed4ac63..af5a42be 100644 --- a/web/components/Account/Application/Place/ApplicationsHelpers/MissingSelections.tsx +++ b/web/components/Account/Application/Place/ApplicationsHelpers/MissingSelections.tsx @@ -1,8 +1,8 @@ import { Box, HStack, Text } from '@chakra-ui/react' import { useTranslation } from 'next-i18next' -import useCampaignContext from '~components/Campaign/useCampaignContext' import { format } from '~utils/date' import PreselectionsWarning from 'public/assets/img/preselectionsWarning.svg' +import useSelectedCampaign from '~hooks/useSelectedCampaign' const MissingSelections = ({ missingPreselections, @@ -10,7 +10,7 @@ const MissingSelections = ({ missingPreselections: number }) => { const { t } = useTranslation('application') - const { currentCampaign } = useCampaignContext() + const { selectedCampaign } = useSelectedCampaign() return ( @@ -20,7 +20,7 @@ const MissingSelections = ({ {t('place.helper.preselection_start', { - date: format(currentCampaign?.preselection_end), + date: format(selectedCampaign?.preselection_end), })} diff --git a/web/components/Account/Application/Place/CampaignSelector/CampaignSelector.tsx b/web/components/Account/Application/Place/CampaignSelector/CampaignSelector.tsx index 6ac25309..883bd28c 100644 --- a/web/components/Account/Application/Place/CampaignSelector/CampaignSelector.tsx +++ b/web/components/Account/Application/Place/CampaignSelector/CampaignSelector.tsx @@ -5,6 +5,7 @@ import { useEffect } from 'react' import CampaignSelectorField from '~components/Account/Application/Place/CampaignSelector/CampaignSelectorField' import useCampaignContext from '~components/Campaign/useCampaignContext' import { ROUTE_ACCOUNT_APPLICATIONS } from '~constants' +import useSelectedCampaign from '~hooks/useSelectedCampaign' const CampaignSelector = ({ children }) => { const router = useRouter() @@ -21,9 +22,7 @@ const CampaignSelector = ({ children }) => { } }, [allPlaceCampaigns]) - const selectedCampaign = allPlaceCampaigns?.find( - (c) => c.id?.toString() === campaign?.toString(), - ) + const { selectedCampaign } = useSelectedCampaign() if (!selectedCampaign) return null diff --git a/web/components/Campaign/CampaignProvider.tsx b/web/components/Campaign/CampaignProvider.tsx index 9416c531..f1cbad1c 100644 --- a/web/components/Campaign/CampaignProvider.tsx +++ b/web/components/Campaign/CampaignProvider.tsx @@ -9,6 +9,20 @@ interface ICampaignProvider { children: React.ReactNode } +export const getStartDateTime = (date) => { + const newDate = new Date(date) + newDate.setHours(0) + newDate.setMinutes(1) + return newDate +} + +export const getEndDateTime = (date) => { + const newDate = new Date(date) + newDate.setHours(23) + newDate.setMinutes(59) + return newDate +} + const CampaignProvider = ({ children }: ICampaignProvider) => { const today = new Date() const { data: user } = useCurrentUser() @@ -40,21 +54,21 @@ const CampaignProvider = ({ children }: ICampaignProvider) => { const getCampaignMode = (campaign) => { if ( - today >= new Date(campaign.disponibility_start) && - today <= new Date(campaign.disponibility_end) + today >= getStartDateTime(campaign.disponibility_start) && + today <= getEndDateTime(campaign.disponibility_end) ) { return 'disponibilities' } else if ( - today >= new Date(campaign.application_start) && - today <= new Date(campaign.application_end) + today >= getStartDateTime(campaign.application_start) && + today <= getEndDateTime(campaign.application_end) ) { return 'applications' } else if ( - today >= new Date(campaign.preselection_start) && - today <= new Date(campaign.preselection_end) + today >= getStartDateTime(campaign.preselection_start) && + today <= getEndDateTime(campaign.preselection_end) ) { return 'preselections' - } else if (today >= new Date(campaign.preselection_end)) { + } else if (today >= getEndDateTime(campaign.preselection_end)) { return 'closed' } return null @@ -106,15 +120,15 @@ const CampaignProvider = ({ children }: ICampaignProvider) => { (currentCampaign?.mode === 'disponibilities' && isCampaignPlace) || currentCampaign?.mode === 'applications' - console.log( - activeCampaigns, - currentCampaign, - isCampaignPlace, - hasActiveCampaign, - isLoading, - allPlaceCampaigns, - isLoadingAllPlaceCampaigns, - ) + // console.log( + // activeCampaigns, + // currentCampaign, + // isCampaignPlace, + // hasActiveCampaign, + // isLoading, + // allPlaceCampaigns, + // isLoadingAllPlaceCampaigns, + // ) return ( { return ( @@ -26,6 +27,7 @@ const MenuItem = ({ href, text }) => { const FooterMenu = () => { const [session, loading] = useSession() const { t } = useTranslation() + const { currentCampaign } = useCampaignContext() return ( @@ -54,6 +56,12 @@ const FooterMenu = () => { + {currentCampaign && currentCampaign?.chart_url && ( + + )} ) diff --git a/web/components/MobileMenu.tsx b/web/components/MobileMenu.tsx index 1593932a..d4e38fdc 100644 --- a/web/components/MobileMenu.tsx +++ b/web/components/MobileMenu.tsx @@ -114,7 +114,9 @@ const MobileMenu = ({ colorMode }: Props) => { /> ) : ( @@ -122,6 +124,12 @@ const MobileMenu = ({ colorMode }: Props) => { )} + {currentCampaign && currentCampaign?.article_link && ( + + )} diff --git a/web/components/Navigation/Header.tsx b/web/components/Navigation/Header.tsx index fadfdbbb..cb32213e 100644 --- a/web/components/Navigation/Header.tsx +++ b/web/components/Navigation/Header.tsx @@ -89,7 +89,9 @@ const Header = ({ colorMode }: Props) => { {t('nav.places_regular')} - {t('nav.places_emergence')} + {t('nav.places_emergence', { + title: currentCampaign?.title, + })} @@ -108,6 +110,12 @@ const Header = ({ colorMode }: Props) => { }} /> + {currentCampaign && currentCampaign?.article_link && ( + + )} diff --git a/web/hooks/useSelectedCampaign.tsx b/web/hooks/useSelectedCampaign.tsx new file mode 100644 index 00000000..dcc44d62 --- /dev/null +++ b/web/hooks/useSelectedCampaign.tsx @@ -0,0 +1,14 @@ +import { useRouter } from 'next/router' +import useCampaignContext from '~components/Campaign/useCampaignContext' + +const useSelectedCampaign = () => { + const { allPlaceCampaigns } = useCampaignContext() + const { query } = useRouter() + const selectedCampaign = allPlaceCampaigns?.find( + (c) => c.id.toString() === query.campaign.toString(), + ) + + return { selectedCampaign } +} + +export default useSelectedCampaign diff --git a/web/pages/compte/candidatures/index.tsx b/web/pages/compte/candidatures/index.tsx index f4265ec5..d8e90c33 100644 --- a/web/pages/compte/candidatures/index.tsx +++ b/web/pages/compte/candidatures/index.tsx @@ -5,24 +5,18 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations' import { requireAuth } from '~utils/auth' import { NextSeo } from 'next-seo' import { useTranslation } from 'next-i18next' -import useCampaignContext from '~components/Campaign/useCampaignContext' import { Box } from '@chakra-ui/react' -import { useRouter } from 'next/router' import PlacesAdminCampaignHelper from '~components/Campaign/Places/Admin/PlacesAdminCampaignHelper' import CampaignSelector from '~components/Account/Application/Place/CampaignSelector/CampaignSelector' import DisponibilitiesSelector from '~components/Account/Application/Place/DisponibilitiesSelector/DisponibilitiesSelector' +import useSelectedCampaign from '~hooks/useSelectedCampaign' const PlaceApplications = () => { const { t } = useTranslation('application') const { t: tAccount } = useTranslation('account') - const { allPlaceCampaigns } = useCampaignContext() - const router = useRouter() - const { campaign } = router.query - const selectedCampaign = allPlaceCampaigns?.find( - (c) => c?.id?.toString() === campaign?.toString(), - ) + const { selectedCampaign } = useSelectedCampaign() - if (allPlaceCampaigns) + if (selectedCampaign) return ( <> @@ -30,9 +24,7 @@ const PlaceApplications = () => { c?.id.toString() === campaign?.toString(), - )?.title, + title: selectedCampaign?.title, })} description={t(`place.helper.open_applications_end`)} /> diff --git a/web/pages/compte/mes-candidatures/index.tsx b/web/pages/compte/mes-candidatures/index.tsx index b74f3baa..3b65aba5 100644 --- a/web/pages/compte/mes-candidatures/index.tsx +++ b/web/pages/compte/mes-candidatures/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { SSRConfig } from 'next-i18next' import { GetServerSideProps } from 'next' import { serverSideTranslations } from 'next-i18next/serverSideTranslations' @@ -11,13 +11,16 @@ import { useMyApplications } from '~hooks/useMyApplications' import InfoCompanyApplications from '~components/Account/Info/InfoCompanyApplications' import ApplicationCompanyList from '~components/Account/Application/Company/ApplicationCompanyList' import useCampaignContext from '~components/Campaign/useCampaignContext' +import { useRouter } from 'next/router' +import { ROUTE_ACCOUNT } from '~constants' interface Props { user: UsersPermissionsUser } const CompanyApplications = ({ user }: Props) => { + const router = useRouter() const { t } = useTranslation('account') - const { currentCampaign } = useCampaignContext() + const { currentCampaign, isLoading: isLoadingCampaign } = useCampaignContext() const { data: applications, isLoading } = useMyApplications({ campaignId: currentCampaign?.id, options: { enabled: !!currentCampaign?.id }, @@ -27,6 +30,13 @@ const CompanyApplications = ({ user }: Props) => { 'disponibility.campaign': currentCampaign?.id, }, }) + + useEffect(() => { + if (!currentCampaign && !isLoadingCampaign) { + router.push(ROUTE_ACCOUNT) + } + }, [currentCampaign]) + if (!currentCampaign) return null return ( diff --git a/web/public/locales/fr/application.json b/web/public/locales/fr/application.json index 95bd3074..a8d2a58f 100644 --- a/web/public/locales/fr/application.json +++ b/web/public/locales/fr/application.json @@ -18,8 +18,11 @@ "starts": "Il est encore possible de déposer {{num}} candidatures,", "end": " avant le {{date}}.", "cta": "Voir les espaces partenaires", - "closed_start": "Le créneau de candidatures pour le dispositif {{title}} est maintenant clôturé,", - "closed_end": "la décision de chaque lieu sera connue d’ici au {{date}}. En cas de sélection, le lieu prendra contact directement avec vous hors de cette plateforme." + "closed_start": "La période de candidature au dispositif {{title}} est maintenant clôturée.", + "closed_end": "La décision de chaque lieu sera connue d’ici au {{date}}. En cas de sélection, le lieu prendra contact directement avec vous hors de cette plateforme.", + "full_start": "Votre candidature est déposée pour le dispositif {{title}}.", + "full_starts": "Vos candidatures sont déposées pour le dispositif {{title}}.", + "full_end": "La décision de chaque lieu sera connue d’ici au {{date}}. En cas de sélection, le lieu prendra contact directement avec vous par email. Merci pour votre participation." }, "delete_error": "Une erreur est survenue lors de la suppression de votre candidature", "delete_success": "Votre candidature a bien été supprimée" diff --git a/web/public/locales/fr/common.json b/web/public/locales/fr/common.json index e8c1a4ca..88642f47 100644 --- a/web/public/locales/fr/common.json +++ b/web/public/locales/fr/common.json @@ -21,8 +21,10 @@ "signin": "Connexion", "cgu": "Conditions générales d'utilisation", "policy": "Chartes StudioD", - "places_emergence": "Dispositif émergence", - "places_regular": "Créneaux solidaires" + "places_emergence": "Créneaux {{title}}", + "places_regular": "Créneaux solidaires", + "campaign": "Dispositif {{title}}", + "campaign_chart": "Charte StudioD – {{title}}" }, "error": "Une erreur est survenue", "success": "Enregistrement réussi",