Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add particulier flow config et mailing #79

Merged
merged 2 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 160 additions & 93 deletions components/bal-widget/bal-widget-config-form.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useMemo, useEffect } from "react";
import React, { useState, useMemo, useEffect, useRef } from "react";
import Tabs from "@codegouvfr/react-dsfr/Tabs";
import styled from "styled-components";
import { Input } from "@codegouvfr/react-dsfr/Input";
import { Button } from "@codegouvfr/react-dsfr/Button";
Expand Down Expand Up @@ -31,6 +32,7 @@ const StyledForm = styled.form`
}

.form-controls {
margin-top: 2rem;
display: flex;
align-items: center;

Expand All @@ -46,6 +48,8 @@ export const BALWidgetConfigForm = ({
formData,
setFormData,
}: BALWidgetConfigFormProps) => {
const tabRef = useRef(null);
const [selectedTabId, setSelectedTabId] = useState("communes");
const [apiDepotClients, setApiDepotClients] = useState<ClientApiDepotType[]>(
[]
);
Expand Down Expand Up @@ -76,6 +80,16 @@ export const BALWidgetConfigForm = ({
fetchData();
}, []);

// Add type="button" to all tabs buttons to avoid form submission
useEffect(() => {
if (tabRef.current) {
const tabBtns = tabRef.current.querySelectorAll(".fr-tabs__tab");
tabBtns.forEach((btn) => {
btn.setAttribute("type", "button");
});
}
}, [tabRef]);

const handleEdit =
(section: keyof BALWidgetConfig, property: string) =>
(e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
Expand Down Expand Up @@ -111,14 +125,14 @@ export const BALWidgetConfigForm = ({

return (
<StyledForm onSubmit={handleSubmit} className="fr-my-4w">
<h3>Configuration du widget</h3>
<h3>Configuration de BAL Widget</h3>
<section>
<h4>Globale</h4>
<Input
label="Titre du widget"
nativeInputProps={{
required: true,
value: formData.global.title,
value: formData.global?.title || "",
onChange: handleEdit("global", "title"),
}}
/>
Expand All @@ -128,109 +142,162 @@ export const BALWidgetConfigForm = ({
{
label: "Cacher le widget",
nativeInputProps: {
checked: formData.global.hideWidget,
checked: formData.global?.hideWidget || false,
onChange: handleToggle("global", "hideWidget"),
},
},
]}
/>
<MultiStringInput
label="Afficher le widget uniquement sur les pages :"
value={formData.global.showOnPages}
value={formData.global?.showOnPages || []}
onChange={(value) =>
handleEdit("global", "showOnPages")({ target: { value } } as any)
}
placeholder="Path de la page autorisée (/programme-bal)"
/>
</section>
<section>
<h4>Aide aux communes</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.communes.welcomeBlockTitle,
onChange: handleEdit("communes", "welcomeBlockTitle"),
}}
/>
<MultiSelectInput
label="Clients API Dépôt caducs"
value={formData.communes.outdatedApiDepotClients}
options={apiDepotClients.map((client) => ({
value: client._id,
label: client.nom,
}))}
placeholder="Sélectionner les clients API Dépôt caducs"
onChange={(value) =>
setFormData((state) => ({
...state,
communes: {
...state.communes,
outdatedApiDepotClients: value,
},
}))
}
/>
<MultiSelectInput
label="Sources moissonnées caduques"
value={formData.communes.outdatedHarvestSources}
options={harvestSources.map((source) => ({
value: source._id,
label: source.title,
}))}
placeholder="Sélectionner les sources moissonnées caduques"
onChange={(value) =>
setFormData((state) => ({
...state,
communes: {
...state.communes,
outdatedHarvestSources: value,
},
}))
}
/>
</section>
<section>
<h4>Gitbook</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.gitbook.welcomeBlockTitle,
onChange: handleEdit("gitbook", "welcomeBlockTitle"),
}}
/>
<MultiLinkInput
label="Articles populaires :"
placeholders={[
"Comment puis-je obtenir une adresse ?",
"Path Gitbook de l'article (/utiliser-la-ban/mon-article)",
]}
value={formData.gitbook.topArticles}
onChange={(value) =>
handleEdit("gitbook", "topArticles")({ target: { value } } as any)
}
/>
</section>
<section>
<h4>Formulaire de contact</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.contactUs.welcomeBlockTitle,
onChange: handleEdit("contactUs", "welcomeBlockTitle"),
}}
/>
<MultiStringInput
label="Sujets du formulaire de contact :"
placeholder="Je souhaite publier une BAL"
value={formData.contactUs.subjects}
onChange={(value) =>
handleEdit("contactUs", "subjects")({ target: { value } } as any)
}
/>
</section>
<Tabs
ref={tabRef}
selectedTabId={selectedTabId}
onTabChange={(e) => setSelectedTabId(e)}
tabs={[
{ tabId: "communes", label: "Communes" },
{ tabId: "particuliers", label: "Particuliers" },
]}
>
{selectedTabId === "communes" && (
<>
<section>
<h4>Aide aux communes</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.communes?.welcomeBlockTitle || "",
onChange: handleEdit("communes", "welcomeBlockTitle"),
}}
/>
<MultiSelectInput
label="Clients API Dépôt caducs"
value={formData.communes?.outdatedApiDepotClients || []}
options={apiDepotClients.map((client) => ({
value: client._id,
label: client.nom,
}))}
placeholder="Sélectionner les clients API Dépôt caducs"
onChange={(value) =>
setFormData((state) => ({
...state,
communes: {
...state.communes,
outdatedApiDepotClients: value,
},
}))
}
/>
<MultiSelectInput
label="Sources moissonnées caduques"
value={formData.communes?.outdatedHarvestSources || []}
options={harvestSources.map((source) => ({
value: source._id,
label: source.title,
}))}
placeholder="Sélectionner les sources moissonnées caduques"
onChange={(value) =>
setFormData((state) => ({
...state,
communes: {
...state.communes,
outdatedHarvestSources: value,
},
}))
}
/>
</section>
<section>
<h4>Gitbook pour les communes</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.gitbookCommunes?.welcomeBlockTitle || "",
onChange: handleEdit("gitbookCommunes", "welcomeBlockTitle"),
}}
/>
<MultiLinkInput
label="Articles populaires :"
placeholders={[
"Comment puis-je obtenir une adresse ?",
"Path Gitbook de l'article (/utiliser-la-ban/mon-article)",
]}
value={formData.gitbookCommunes?.topArticles || []}
onChange={(value) =>
handleEdit(
"gitbookCommunes",
"topArticles"
)({ target: { value } } as any)
}
/>
</section>
<section>
<h4>Formulaire de contact</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.contactUs?.welcomeBlockTitle || "",
onChange: handleEdit("contactUs", "welcomeBlockTitle"),
}}
/>
<MultiStringInput
label="Sujets du formulaire de contact :"
placeholder="Je souhaite publier une BAL"
value={formData.contactUs?.subjects || []}
onChange={(value) =>
handleEdit(
"contactUs",
"subjects"
)({ target: { value } } as any)
}
/>
</section>
</>
)}
{selectedTabId === "particuliers" && (
<>
<section>
<h4>Gitbook pour les particuliers</h4>
<Input
label="Titre sur la page d'accueil"
nativeInputProps={{
required: true,
value: formData.gitbookParticuliers?.welcomeBlockTitle || "",
onChange: handleEdit(
"gitbookParticuliers",
"welcomeBlockTitle"
),
}}
/>
<MultiLinkInput
label="Articles populaires :"
placeholders={[
"Comment puis-je obtenir une adresse ?",
"Path Gitbook de l'article (/utiliser-la-ban/mon-article)",
]}
value={formData.gitbookParticuliers?.topArticles || []}
onChange={(value) =>
handleEdit(
"gitbookParticuliers",
"topArticles"
)({ target: { value } } as any)
}
/>
</section>
</>
)}
</Tabs>

<div className="form-controls">
<Button disabled={!canPublish} type="submit" iconId="fr-icon-save-line">
Publier
Expand Down
27 changes: 18 additions & 9 deletions components/bal-widget/bal-widget-iframe.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,28 @@
import { useState, useEffect, useRef } from "react";
import { BALWidgetConfig } from "types/bal-widget";
import styled from "styled-components";

const BAL_WIDGET_URL = process.env.NEXT_PUBLIC_BAL_WIDGET_URL;

interface BALWidgetIFrameProps {
config: BALWidgetConfig;
}

const StyledIFrame = styled.iframe<{ $isOpen: boolean }>`
position: fixed;
bottom: 40px;
right: 40px;
z-index: 999;
${({ $isOpen }) =>
$isOpen ? "height: 600px; width: 450px;" : "height: 60px; width: 60px;"}

@media screen and (max-width: 450px) {
bottom: 10px;
right: 10px;
${({ $isOpen }) => $isOpen && "width: calc(100% - 20px);"}
}
`;

function BALWidgetIFrame({ config }: BALWidgetIFrameProps) {
const balWidgetRef = useRef<HTMLIFrameElement>(null);
const [isBalWidgetOpen, setIsBalWidgetOpen] = useState(false);
Expand Down Expand Up @@ -52,17 +68,10 @@ function BALWidgetIFrame({ config }: BALWidgetIFrameProps) {
}, [isBalWidgetOpen]);

return (
<iframe
<StyledIFrame
ref={balWidgetRef}
src={BAL_WIDGET_URL}
width={isBalWidgetOpen ? 450 : 60}
height={isBalWidgetOpen ? 800 : 60}
style={{
position: "fixed",
bottom: 40,
right: 40,
zIndex: 999,
}}
$isOpen={isBalWidgetOpen}
/>
);
}
Expand Down
6 changes: 5 additions & 1 deletion pages/bal-widget/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ const defaultConfig: BALWidgetConfig = {
outdatedApiDepotClients: [],
outdatedHarvestSources: [],
},
gitbook: {
gitbookCommunes: {
welcomeBlockTitle: "Ces articles pourraient vous aider",
topArticles: [],
},
contactUs: {
welcomeBlockTitle: "Nous contacter",
subjects: [],
},
gitbookParticuliers: {
welcomeBlockTitle: "Ces articles pourraient vous aider",
topArticles: [],
},
};

const BALWidgetPage = ({ config: baseConfig }: BALWidgetPageProps) => {
Expand Down
10 changes: 10 additions & 0 deletions server/lib/bal-widget/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,14 @@ BALWidgetRoutes.post("/send-mail", async (req, res) => {
}
});

BALWidgetRoutes.post("/send-mail-to-commune", async (req, res) => {
try {
await MailerService.sendSignalementToCommune(req.body);
res.json(true);
} catch (err) {
console.error(err);
res.status(500).json({ error: err.message });
}
});

module.exports = BALWidgetRoutes;
Loading
Loading