diff --git a/back/extensions/documentation/documentation/1.0.0/full_documentation.json b/back/extensions/documentation/documentation/1.0.0/full_documentation.json
index bfc8ed1e..a5563b59 100644
--- a/back/extensions/documentation/documentation/1.0.0/full_documentation.json
+++ b/back/extensions/documentation/documentation/1.0.0/full_documentation.json
@@ -14,7 +14,7 @@
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
- "x-generation-date": "03/07/2024 4:37:03 PM"
+ "x-generation-date": "03/10/2024 10:56:56 PM"
},
"x-strapi-config": {
"path": "/documentation",
diff --git a/web/components/Account/AccountMenu.tsx b/web/components/Account/AccountMenu.tsx
index 4d9cd3ee..195df344 100644
--- a/web/components/Account/AccountMenu.tsx
+++ b/web/components/Account/AccountMenu.tsx
@@ -155,7 +155,8 @@ const AccountMenu = ({ user }: { user: UsersPermissionsUser }) => {
(user?.type === 'place' &&
placeCampaigns?.length &&
applications?.length) ||
- (user?.type === 'company' && currentCampaign)
+ (user?.type === 'company' && currentCampaign && currentCampaign.mode !== "closed")
+
const displayMenu = ({ title, items, translationParams = {} }) => {
const isDisactivated = !isComplete && title === 'dashboard'
diff --git a/web/components/Account/Application/Company/ApplicationCompanyList.tsx b/web/components/Account/Application/Company/ApplicationCompanyList.tsx
index 2a78cc89..1d59a5a0 100644
--- a/web/components/Account/Application/Company/ApplicationCompanyList.tsx
+++ b/web/components/Account/Application/Company/ApplicationCompanyList.tsx
@@ -59,6 +59,7 @@ const ApplicationCompanyList = ({ applications = [] }: Props) => {
query?.disponibility as string,
])
queryClient.refetchQueries(['me'])
+ onClose()
} catch (e) {
errorToast(t('company.delete_error'))
}
diff --git a/web/components/Account/Application/Place/ApplicationDownloadAll.tsx b/web/components/Account/Application/Place/ApplicationDownloadAll.tsx
index 44e09ab0..85b282a7 100644
--- a/web/components/Account/Application/Place/ApplicationDownloadAll.tsx
+++ b/web/components/Account/Application/Place/ApplicationDownloadAll.tsx
@@ -1,18 +1,14 @@
import { Box, Button } from '@chakra-ui/react'
import { useTranslation } from 'next-i18next'
import { useRouter } from 'next/router'
-import { useState } from 'react'
import { useMyApplications } from '~hooks/useMyApplications'
import useSelectedCampaign from '~hooks/useSelectedCampaign'
-import useToast from '~hooks/useToast'
-import { handleDisponibilityDownload } from '~utils/pdf'
const ApplicationDownloadAll = () => {
const { selectedCampaign } = useSelectedCampaign()
- const { errorToast } = useToast()
const { t } = useTranslation('application')
const { query } = useRouter()
- const [isDownloading, setIsDownloading] = useState(false)
+
const { data: applications, isLoading, isFetching } = useMyApplications({
name: ['myApplications', query?.disponibility as string],
searchParams: { ...query, _sort: 'company.structureName:asc' },
@@ -28,31 +24,18 @@ const ApplicationDownloadAll = () => {
return (
diff --git a/web/components/Account/Application/Place/DetailDrawer/ApplicationDetailDrawer.tsx b/web/components/Account/Application/Place/DetailDrawer/ApplicationDetailDrawer.tsx
index e1a53ccd..70e2cda9 100644
--- a/web/components/Account/Application/Place/DetailDrawer/ApplicationDetailDrawer.tsx
+++ b/web/components/Account/Application/Place/DetailDrawer/ApplicationDetailDrawer.tsx
@@ -16,11 +16,12 @@ import ApplicationDetailHeader from '~components/Account/Application/Place/Detai
import { Application } from '~typings/api'
import ApplicationRightPanel from '~components/Account/Application/Place/DetailDrawer/ApplicationRightPanel'
-import { useState } from 'react'
+import { useEffect, useState } from 'react'
import { Document, Page } from 'react-pdf'
import useToast from '~hooks/useToast'
import { handleApplicationDownload } from '~utils/pdf'
+import ApplicationDetails from '~components/Account/Application/Place/DetailDrawer/ApplicationDetails'
const ApplicationDetailDrawer = ({
isOpen,
@@ -35,6 +36,7 @@ const ApplicationDetailDrawer = ({
}) => {
const { t } = useTranslation('application')
const { id } = application ?? {}
+ const [displayPdf, setDisplayPdf] = useState(false)
const [isDownloading, setIsDownloading] = useState(false)
const [scales, setScales] = useState([])
const { errorToast } = useToast()
@@ -55,27 +57,38 @@ const ApplicationDetailDrawer = ({
}
}
+ useEffect(() => {
+ setTimeout(() => {
+ setDisplayPdf(true)
+ }, 1500)
+ }, [id, isOpen])
+
if (!application) {
return null
}
return (
-
+ {
+ setDisplayPdf(false)
+ onClose()
+ }}
+ size="xl"
+ >
{t('place.detail.title', { id })}
-
-
@@ -86,47 +99,52 @@ const ApplicationDetailDrawer = ({
display="flex"
height="100%"
width="100%"
+ flexDirection="column"
>
- {
- setNumPages(numPages)
- }}
- loading={
-
- }
- style={{ height: '100%' }}
- >
- {Array.from(new Array(numPages), (el, index) => (
- {
- const viewport = page.getViewport({ scale: 1 })
- if (viewport) {
- const orientation =
- viewport.width > viewport.height
- ? 'landscape'
- : 'portrait'
- // Adjust the scale based on the orientation
- const scale = orientation === 'landscape' ? 0.7 : 1.0
- setScales((prevScales) => {
- const newScales = [...prevScales]
- newScales[index] = scale
- return newScales
- })
- }
- }}
- scale={scales[index] || 1.0}
- />
- ))}
-
+
+
+ {displayPdf && (
+ {
+ setNumPages(numPages)
+ }}
+ loading={
+
+ }
+ style={{ height: '100%' }}
+ >
+ {Array.from(new Array(numPages), (_el, index) => (
+ {
+ const viewport = page.getViewport({ scale: 1 })
+ if (viewport) {
+ const orientation =
+ viewport.width > viewport.height
+ ? 'landscape'
+ : 'portrait'
+ // Adjust the scale based on the orientation
+ const scale =
+ orientation === 'landscape' ? 0.7 : 1.0
+ setScales((prevScales) => {
+ const newScales = [...prevScales]
+ newScales[index] = scale
+ return newScales
+ })
+ }
+ }}
+ scale={scales[index] || 1.0}
+ />
+ ))}
+
+ )}
-
{
+ const { t } = useTranslation('place')
+
+ return (
+
+
+
+ }
+ >
+ {application?.references?.map((reference: Reference, index) => (
+
+
+ {t('campaignApplication.references.references_creation', {
+ index: index + 1,
+ })}
+
+ {`${reference?.title}, ${reference?.year}`}
+
+ {t('campaignApplication.references.references_actors_display', {
+ number: reference?.actors,
+ })}
+
+ {(Boolean(reference?.other)
+ ? [reference?.partners, reference?.other]
+ : reference?.partners
+ )?.join(', ')}
+
+
+
+ ))}
+
+
+
+
+ } spacing={4} mb={10}>
+
+ {Boolean(application?.already_supported) ? 'Oui' : 'Non'}
+
+
+ {application?.cv}
+
+
+
+
+
+ } spacing={4} mb={10}>
+
+ {application?.creation_title}
+
+
+ {application?.creation_dancers}
+
+
+ {application?.creation_summary}
+
+
+ {application?.creation_partnerships}
+
+
+ {application?.creation_techical_requirements}
+
+
+ {Boolean(application?.creation_accomodation)
+ ? t('campaignApplication.creation.yes')
+ : t('campaignApplication.creation.no')}
+
+
+
+
+ )
+}
+
+export default ApplicationDetails
diff --git a/web/components/Account/Application/Place/DetailDrawer/ApplicationSection.tsx b/web/components/Account/Application/Place/DetailDrawer/ApplicationSection.tsx
new file mode 100644
index 00000000..dc3f6405
--- /dev/null
+++ b/web/components/Account/Application/Place/DetailDrawer/ApplicationSection.tsx
@@ -0,0 +1,17 @@
+import { Text, VStack } from '@chakra-ui/react'
+import { ReactNode } from 'react-markdown'
+
+const ApplicationSection = ({
+ label,
+ children,
+}: {
+ label: ReactNode
+ children: ReactNode
+}) => (
+
+ {label}
+ {children}
+
+)
+
+export default ApplicationSection
diff --git a/web/package.json b/web/package.json
index c6e167ba..392f4dfb 100644
--- a/web/package.json
+++ b/web/package.json
@@ -25,6 +25,7 @@
"@mapbox/mapbox-sdk": "^0.12.1",
"@react-pdf/renderer": "1.6.17",
"@svgr/webpack": "^6.2.1",
+ "adm-zip": "^0.5.10",
"axios": "^0.21.1",
"babel-plugin-transform-require-ignore": "^0.1.1",
"date-fns": "^2.19.0",
diff --git a/web/pages/api/pdfs/all/[id].tsx b/web/pages/api/pdfs/all/[id].tsx
index 9233c930..41e11cde 100644
--- a/web/pages/api/pdfs/all/[id].tsx
+++ b/web/pages/api/pdfs/all/[id].tsx
@@ -3,8 +3,8 @@ import { renderToStream } from '@react-pdf/renderer'
import { client } from '~api/client-api'
import ApplicationDocument from '~components/pdfs/ApplicationDocument'
import { getSession } from 'next-auth/client'
-import PDFMerger from 'pdf-merger-js'
-import { formatDisponibilityPdfName, getBufferFromStream } from '~utils/pdf'
+import { formatDisponibilityZipName, getBufferFromStream } from '~utils/pdf'
+import AdmZip from "adm-zip"
const MultipleApplication = async (req, res) => {
const { id: disponibilityId } = req.query
@@ -31,34 +31,34 @@ const MultipleApplication = async (req, res) => {
const disponibility = applications?.[0]?.disponibility
const campaign = applications?.[0]?.campaign
- const merger = new PDFMerger()
- let finalPDF
+ const zip = new AdmZip();
for (const application of applications) {
+ const name = application.company?.structureName;
const stream = await renderToStream(
,
)
const streamBuffer = await getBufferFromStream(stream)
- await merger.add(streamBuffer)
+ await zip.addFile(`${name}/candidature.pdf`, streamBuffer);
if (application?.creation_file?.[0]?.url) {
const creationFile = await fetch(application?.creation_file?.[0]?.url)
- const creationFileArrayBuffer = await creationFile.arrayBuffer()
-
- await merger.add(creationFileArrayBuffer)
+
+ // @ts-ignore
+ const creationFileArrayBuffer = await creationFile.buffer()
+ await zip.addFile(`${name}/dossier-artistique.pdf`, creationFileArrayBuffer);
}
}
- finalPDF = await merger.saveAsBuffer()
+ const zipBuffer = zip.toBuffer();
- res.setHeader('Content-Type', 'application/pdf')
+ res.setHeader('Content-Type', 'application/zip')
res.setHeader(
'Content-Disposition',
- 'attachment; filename=' +
- // @ts-expect-error
- formatDisponibilityPdfName(disponibility, campaign),
+ // @ts-expect-error
+ 'attachment; filename=' + formatDisponibilityZipName(disponibility, campaign),
)
- res.send(finalPDF)
+ res.send(zipBuffer)
}
export default MultipleApplication
diff --git a/web/pages/api/pdfs/selected/[id].tsx b/web/pages/api/pdfs/selected/[id].tsx
index 8ded303f..bee73cf1 100644
--- a/web/pages/api/pdfs/selected/[id].tsx
+++ b/web/pages/api/pdfs/selected/[id].tsx
@@ -3,9 +3,8 @@ import { renderToStream } from '@react-pdf/renderer'
import { client } from '~api/client-api'
import ApplicationDocument from '~components/pdfs/ApplicationDocument'
import { getSession } from 'next-auth/client'
-import PDFMerger from 'pdf-merger-js'
-import { formatCampaignPdfName, getBufferFromStream } from '~utils/pdf'
-import DividerPage from '~components/pdfs/DividerPage'
+import { formatCampaignZipName, getBufferFromStream } from '~utils/pdf'
+import AdmZip from "adm-zip"
const SelectedCampaignApplications = async (req, res) => {
const { id: campaignId } = req.query
@@ -17,7 +16,7 @@ const SelectedCampaignApplications = async (req, res) => {
return
}
- let finalPDF
+ const zip = new AdmZip();
const { data: campaign } = await client.campaigns.campaignsDetail(campaignId)
try {
@@ -54,42 +53,37 @@ const SelectedCampaignApplications = async (req, res) => {
groupedApplications[userId].sort((a, b) => {
const aId = a.disponibility?.id || 0
const bId = b.disponibility?.id || 0
+
return aId - bId
})
}
- const merger = new PDFMerger()
-
const userIds = Object.keys(groupedApplications)
for (const userId of userIds) {
const applications = groupedApplications[userId]
const place =
applications[0]?.disponibility?.espace?.users_permissions_user
-
- const dividerStream = await renderToStream(
- ,
- )
- const dividerStreamBufffer = await getBufferFromStream(dividerStream)
- await merger.add(dividerStreamBufffer)
-
+ const name = place?.structureName
+
+
for (const application of applications) {
const stream = await renderToStream(
,
- )
+ )
+
const streamBuffer = await getBufferFromStream(stream)
- await merger.add(streamBuffer)
+ await zip.addFile(`${name}/candidature.pdf`, streamBuffer);
if (application?.creation_file?.[0]?.url) {
const creationFile = await fetch(application?.creation_file?.[0]?.url)
- const creationFileArrayBuffer = await creationFile.arrayBuffer()
-
- await merger.add(creationFileArrayBuffer)
+ // @ts-ignore
+ const creationFileArrayBuffer = await creationFile.buffer()
+
+ await zip.addFile(`${name}/dossier-artistique.pdf`, creationFileArrayBuffer);
}
}
}
-
- finalPDF = await merger.saveAsBuffer()
} catch (error) {
console.error(error)
res
@@ -98,12 +92,14 @@ const SelectedCampaignApplications = async (req, res) => {
return
}
- res.setHeader('Content-Type', 'application/pdf')
+ const zipBuffer = zip.toBuffer();
+
+ res.setHeader('Content-Type', 'application/zip')
res.setHeader(
'Content-Disposition',
- 'attachment; filename=' + formatCampaignPdfName(campaign),
+ 'attachment; filename=' + formatCampaignZipName(campaign),
)
- res.send(finalPDF)
+ res.send(zipBuffer)
}
export default SelectedCampaignApplications
diff --git a/web/pages/compte/mes-candidatures/index.tsx b/web/pages/compte/mes-candidatures/index.tsx
index 1bb5167b..c9618542 100644
--- a/web/pages/compte/mes-candidatures/index.tsx
+++ b/web/pages/compte/mes-candidatures/index.tsx
@@ -36,7 +36,15 @@ const CompanyApplications = ({ user }: Props) => {
}
}, [currentCampaign])
- if (!currentCampaign) return null
+ if (!currentCampaign) {
+ return null
+ }
+
+ if (currentCampaign?.mode === "closed") {
+ router.push(ROUTE_ACCOUNT)
+ return null
+ }
+
return (
diff --git a/web/public/locales/fr/place.json b/web/public/locales/fr/place.json
index 7ba354c4..02613dc2 100644
--- a/web/public/locales/fr/place.json
+++ b/web/public/locales/fr/place.json
@@ -465,7 +465,7 @@
},
"general": {
"title": " Informations générales",
- "subtitle": "Avez-vous déjà été soutenu·e par {{place}}?",
+ "subtitle": "Avez-vous déjà été soutenu·e par {{place}} ?",
"bio": "C.V. | Biographie du / de la chorégraphe",
"bioHelper": "(3000 signes maximum)"
},
diff --git a/web/theme/index.ts b/web/theme/index.ts
index 02624d0f..9e6936f4 100644
--- a/web/theme/index.ts
+++ b/web/theme/index.ts
@@ -104,6 +104,11 @@ const theme = extendTheme({
Divider,
Input,
Textarea,
+ Drawer: {
+ sizes: {
+ xl: { dialog: { maxW: '65rem' } },
+ },
+ },
},
textStyles: {
h1: {
diff --git a/web/utils/pdf.ts b/web/utils/pdf.ts
index 1b84e996..2f34dd4d 100644
--- a/web/utils/pdf.ts
+++ b/web/utils/pdf.ts
@@ -47,7 +47,7 @@ export const handleApplicationDownload = async ({
link.parentNode?.removeChild(link)
}
-export const formatDisponibilityPdfName = (
+export const formatDisponibilityZipName = (
disponibility: Disponibility,
campaign: Campaign,
) => {
@@ -60,35 +60,9 @@ export const formatDisponibilityPdfName = (
//@ts-expect-error
)}_${disponibility?.espace?.users_permissions_user?.structureName
?.split(' ')
- .join('_')}_${campaign?.title?.split(' ').join('_')}.pdf`
+ .join('_')}_${campaign?.title?.split(' ').join('_')}.zip`
}
-export const handleDisponibilityDownload = async ({
- disponibility,
- campaign,
- onError,
-}: {
- disponibility: Disponibility
- campaign: Campaign
- onError: () => void
-}) => {
- const res = await fetch(`/api/pdfs/all/${disponibility.id}`)
- if (!res.ok) {
- onError()
- }
- const blob = await res.blob()
- const url = window.URL.createObjectURL(blob)
- const link = document.createElement('a')
- link.href = url
- link.setAttribute(
- 'download',
- formatDisponibilityPdfName(disponibility, campaign),
- )
- document.body.appendChild(link)
- link.click()
- link.parentNode?.removeChild(link)
-}
-
-export const formatCampaignPdfName = (campaign: Campaign) => {
- return `${campaign?.title?.split(' ').join('_')}.pdf`
+export const formatCampaignZipName = (campaign: Campaign) => {
+ return `${campaign?.title?.split(' ').join('_')}.zip`
}
diff --git a/web/yarn.lock b/web/yarn.lock
index d1cb988a..b35e0ac1 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -2453,6 +2453,11 @@
resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.7.tgz#cb60565e69af9d132cac420a4bb94e6472847f6f"
integrity sha512-TlYNIa9XHCGYRqVrijiDVj72Sc4Yd9At0NYEaHm8Su94GwcsXRq5y1AhA8tZUVNXYRCNpGWuOWI4VQ+R58MgUw==
+adm-zip@^0.5.10:
+ version "0.5.10"
+ resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.10.tgz#4a51d5ab544b1f5ce51e1b9043139b639afff45b"
+ integrity sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==
+
ajv-keywords@^3.1.0, ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"