Skip to content

Commit 56de590

Browse files
committed
Merge branch 'main' into searchbar
2 parents 8dad9e6 + 04d4f4c commit 56de590

File tree

4 files changed

+246
-1743
lines changed

4 files changed

+246
-1743
lines changed

app/root.tsx

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import type {
33
LoaderFunctionArgs,
44
MetaFunction,
55
} from "@remix-run/node";
6-
import { json } from "@remix-run/node";
76
import {
87
Links,
98
Meta,
@@ -12,14 +11,14 @@ import {
1211
ScrollRestoration,
1312
useLoaderData,
1413
} from "@remix-run/react";
14+
import { ReactNode, useEffect, useState } from "react";
1515
import { useTranslation } from "react-i18next";
16-
import * as gtag from "~/utils/gtag.client";
1716
import { getSeo } from "~/seo";
18-
import { gdprConsent } from "./cookies";
19-
import { ReactNode, useEffect, useState } from "react";
17+
import * as gtag from "~/utils/gtag.client";
2018
import BasicCatchBoundary from "./components/BasicErrorBoundary";
21-
import styles from "./styles/app.css?url";
2219
import { CookieBanner } from "./components/CookieBanner";
20+
import { gdprConsent } from "./cookies";
21+
import styles from "./styles/app.css?url";
2322

2423
let [seoMeta, seoLinks] = getSeo();
2524

@@ -70,7 +69,7 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
7069
let { locale = "de" } = params;
7170
const cookieHeader = request.headers.get("Cookie");
7271
const cookie = (await gdprConsent.parse(cookieHeader)) || {};
73-
return json({ locale, track: cookie.gdprConsent });
72+
return { locale, track: cookie.gdprConsent };
7473
}
7574

7675
export function useChangeLanguage(locale: string) {
@@ -82,17 +81,15 @@ export function useChangeLanguage(locale: string) {
8281

8382
export default function App() {
8483
let { locale, track } = useLoaderData<typeof loader>();
85-
const [shouldTrack, setShouldTrack] = useState(track);
84+
const [shouldTrack, setShouldTrack] = useState(false);
8685

8786
useEffect(() => {
8887
setShouldTrack(track);
8988
}, [track]);
9089

91-
useEffect(() => {
92-
if (shouldTrack) {
93-
gtag.init();
94-
}
95-
}, [shouldTrack]);
90+
if (shouldTrack) {
91+
gtag.init();
92+
}
9693

9794
useChangeLanguage(locale);
9895

@@ -118,4 +115,4 @@ export default function App() {
118115

119116
export function ErrorBoundary() {
120117
return <BasicCatchBoundary />;
121-
}
118+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import type { ActionFunctionArgs } from "@remix-run/node";
2+
import { Form, useActionData } from "@remix-run/react";
3+
import { getCoaches } from "~/utils/contentful";
4+
5+
export async function action({ request }: ActionFunctionArgs) {
6+
const formData = await request.formData();
7+
const pw = formData.get("pw");
8+
9+
console.log({ pw, envPw: process.env.CSV_DOWNLOAD_PW });
10+
11+
if (pw !== process.env.CSV_DOWNLOAD_PW) {
12+
return { error: "wrong password", body: null };
13+
}
14+
const coaches = await getCoaches();
15+
16+
const csvHeader = "Name,E-Mail,Webseite,Telefon,Sprachen,Geschlechter,\n";
17+
18+
const csvBody = coaches
19+
.map(
20+
(coach) =>
21+
`${coach.fields?.name ?? ""},${coach.fields?.email ?? ""},${coach.fields?.url ?? ""},${coach.fields?.phone ?? ""},${coach.fields?.languages?.join("; ") ?? ""},${coach.fields.gender?.join("; ") ?? ""},`,
22+
)
23+
.join("\n");
24+
25+
const csv = `${csvHeader}${csvBody}`;
26+
27+
return { body: csv, error: null };
28+
}
29+
30+
export default function Component() {
31+
const actionData = useActionData<typeof action>();
32+
33+
const error = actionData?.error ?? null;
34+
35+
const downloadCSV = () => {
36+
if (!actionData?.body) return;
37+
const csvData = new Blob([actionData?.body], { type: "text/csv" });
38+
const csvURL = URL.createObjectURL(csvData);
39+
const link = document.createElement("a");
40+
link.href = csvURL;
41+
link.download = `coaches-data.csv`;
42+
document.body.appendChild(link);
43+
link.click();
44+
document.body.removeChild(link);
45+
};
46+
47+
return (
48+
<div className="container mx-auto max-w-6xl py-40 px-2 md:px-4 lg:px-8">
49+
<div className="flex flex-col gap-12">
50+
<h1 className="text-3xl">Daten herunterladen</h1>
51+
<Form
52+
reloadDocument
53+
method="POST"
54+
className="flex flex-col gap-4 max-w-md"
55+
>
56+
<label className="flex flex-col gap-2">
57+
<span>Download-Passwort</span>
58+
<input
59+
className="p-2 rounded-sm border border-slate-400 active:border-vsp-500"
60+
name="pw"
61+
type="password"
62+
/>
63+
{error ? (
64+
<span className="text-red-600 text-sm">
65+
Falsches Passwort, sorry!
66+
</span>
67+
) : null}
68+
</label>
69+
<button
70+
type="submit"
71+
className="font-inherit inline-flex items-center justify-center rounded-md py-2 px-4 text-white no-underline transition-opacity duration-300 hover:opacity-90 focus:opacity-90 active:opacity-90 md:text-lg bg-vsp-500"
72+
>
73+
Download anfragen
74+
</button>
75+
</Form>
76+
{actionData?.body ? (
77+
<button
78+
type="button"
79+
onClick={() => {
80+
downloadCSV();
81+
}}
82+
className="font-inherit inline-flex items-center justify-center rounded-md py-2 px-4 text-white no-underline transition-opacity duration-300 hover:opacity-90 focus:opacity-90 active:opacity-90 md:text-lg bg-vsp-500"
83+
>
84+
CSV herunterladen
85+
</button>
86+
) : null}
87+
</div>
88+
</div>
89+
);
90+
}

0 commit comments

Comments
 (0)