Skip to content

Commit

Permalink
Routing and styling refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Luis Doebbel committed Dec 3, 2024
1 parent 8029e9b commit 7e84bbd
Show file tree
Hide file tree
Showing 68 changed files with 941 additions and 674 deletions.
1 change: 1 addition & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dist
dist-ssr
*.local
.env
.yarn

# Editor directories and files
.vscode/*
Expand Down
5 changes: 3 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"sheet2i18n": "sheet2i18n src/sheet2i18n.config.cjs",
"sheet2i18n": "node ./sheet2i18n/index.cjs src/sheet2i18n.config.cjs",
"lint": "yarn lint:scripts && yarn lint:styles && yarn lint:editor && yarn prettier --write .",
"lint:scripts": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"lint:styles": "stylelint \"./src/**/*.(scss)\"",
Expand Down Expand Up @@ -48,16 +48,17 @@
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react": "^4.3.1",
"csv-parse": "^5.6.0",
"eclint": "^2.8.1",
"eslint": "^8.57.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.34.3",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"node-fetch": "^3.3.2",
"postcss": "^8.4.29",
"prettier": "^3.3.2",
"sass": "^1.77.6",
"sheet2i18n": "^1.1.2",
"stylelint": "^16.6.1",
"stylelint-config-prettier-scss": "^1.0.0",
"stylelint-config-standard-scss": "^13.1.0",
Expand Down
20 changes: 20 additions & 0 deletions frontend/sheet2i18n/index.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use strict";

const path = require("path");
const sheet2i18n = require("./sheet2i18n.cjs");

const [, , configPathArg] = process.argv;

const configPath = configPathArg || "sheet2i18n.config";
const currentDir = process.cwd();
const resolvedConfigPath = path.resolve(currentDir, configPath);

try {
sheet2i18n(resolvedConfigPath, currentDir);
} catch (error) {
console.error(
`Failed to execute sheet2i18n with config path: ${resolvedConfigPath}`,
);
console.error(error);
process.exit(1);
}
102 changes: 102 additions & 0 deletions frontend/sheet2i18n/sheet2i18n.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
const fs = require("fs").promises;
const path = require("path");
const parseCSV = require("csv-parse/sync");

/**
* Load CSV files, parse them, and generate JSON files for localization.
* @param {string} configPath - Path to the configuration file.
* @param {string} currentDir - Path to the root folder.
*/
async function loadCsv(configPath, currentDir) {
const { exportPath, tabsUrl, localesKey } = require(configPath);

console.log("[+] IMPORTING LOCALES");

try {
const fetch = (await import("node-fetch")).default;

const responses = await Promise.all(
tabsUrl.map(async (urltab) => {
const response = await fetch(urltab);
return await response.text();
}),
);

const resolvedExportPath = path.resolve(currentDir, exportPath);

const rows = responses.flatMap((response) => getParsedCSV(response));
await handleResponse(localesKey, rows, resolvedExportPath);
} catch (error) {
console.error("Error fetching or processing CSV files:", error);
}
}

/**
* Parse a CSV string into an array of objects.
* @param {string} file - CSV file content as a string.
* @returns {Object[]} Parsed CSV data.
*/
function getParsedCSV(file) {
return parseCSV.parse(file, {
columns: (header) => header.map((col) => col.split(" ")[0].toLowerCase()),
});
}

/**
* Handle the parsed CSV data and generate JSON files for each locale.
* @param {string[]} localesKey - Array of locale keys.
* @param {Object[]} rows - Parsed CSV data.
* @param {string} exportPath - Path to export JSON files.
*/
async function handleResponse(localesKey, rows, exportPath) {
await localesKey.forEach(async (localeKey) => {
const content = writeTranslation(localesKey, rows, localeKey);
await createJson(exportPath, localeKey, `{\n${content}\n}\n`);
});
}

/**
* Write translation content for a specific locale.
* @param {string[]} localesKey - Array of locale keys.
* @param {Object[]} rows - Parsed CSV data.
* @param {string} locale - Current locale key.
* @returns {string} Translation content as a JSON string.
*/
function writeTranslation(localesKey, rows, locale) {
const fallback =
localesKey[(localesKey.indexOf(locale) + 1) % localesKey.length];

return rows
.map((row) => {
let { key } = row;
if (!key) return;

key = key.replace(/\s+/g, "");

const newRow =
row[locale]?.replace(/"/g, "'").replace(/(?:\r\n|\r|\n)/g, "<br>") ||
row[fallback];

return newRow ? ` "${key}": "${newRow}"` : undefined;
})
.filter(Boolean)
.join(",\n");
}

/**
* Create a JSON file with the given content.
* @param {string} exportPath - Path to export JSON files.
* @param {string} locale - Locale key.
* @param {string} content - JSON content as a string.
*/
async function createJson(exportPath, locale, content) {
try {
const filePath = `${exportPath}/${locale}.json`;
await fs.writeFile(filePath, content);
console.log(`JSON in ${locale} is saved.`);
} catch (error) {
console.error(`Error saving JSON for ${locale}:`, error);
}
}

module.exports = loadCsv;
4 changes: 2 additions & 2 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Loading from "@components/loading/Loading";
import CookieConsent from "@containers/cookieConsent/CookieConsent";
import { hasConsent } from "@containers/cookieConsent/cookieConsentHelper";
import CookieConsent from "@components/cookieConsent/CookieConsent";
import { hasConsent } from "@components/cookieConsent/cookieConsentHelper";
import Router from "@routes/Router";
import "@shared/i18n";
import "@styles/index.scss";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import cookieTypes from "@containers/cookieConsent/cookieConsent.config";
import cookieTypes from "./cookieConsent.config";
import {
COOKIE_CONSENT_DURATION,
getCookieConsentPreferences,
setCookiePreferencesInStorage,
} from "@containers/cookieConsent/cookieConsentHelper";
import ICookiePreferences from "@containers/cookieConsent/interfaces/ICookiePreferences";
} from "./cookieConsentHelper";
import ICookiePreferences from "./interfaces/ICookiePreferences";
import { useCallback, useEffect, useState } from "react";
import CookieBanner from "./cookieBanner/CookieBanner";
import CookieModal from "./cookieModal/CookieModal";
Expand Down Expand Up @@ -53,6 +53,7 @@ export default function CookieConsent() {
cookiePreferences={cookiePreferences}
setCookiePreferences={setCookiePreferences}
/>

<CookieBanner
showBanner={cookieBannerOpen}
openModal={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ export default function CookieBanner({
<Slide in={showBanner}>
<div
className={classes["cookie-banner"]}
sx={(theme) => ({ bottom: theme.spacing(2) })}
sx={(theme) => ({
bottom: theme.spacing(2),
zIndex: theme.zIndex.cookieBanner,
})}
>
<StyledContainer className={classes["container"]}>
<div
Expand All @@ -73,11 +76,19 @@ export default function CookieBanner({
<div>
<CookieIcon />
</div>
<div className="flex-column">
<Typography variant="body2" className="mb-xxs">
<div
sx={{
display: "flex",
flexDirection: "column",
}}
>
<Typography
variant="body2"
sx={{ marginBottom: "var(--mui-customProperties-spacing-xxs)" }}
>
{t("cookie_banner__description")}
</Typography>
<div className="mr-a">
<div sx={{ marginRight: "auto" }}>
<Link
href={t("cookie_consent_link")}
underline="always"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ICookiePreferences from "@containers/cookieConsent/interfaces/ICookiePreferences";
import ICookiePreferences from "./interfaces/ICookiePreferences";

export const COOKIE_PREFERENCES = "COOKIE_PREFERENCES";
export const COOKIE_CONSENT_DURATION = 1000 * 60 * 60 * 24 * 365;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Switch from "@components/switch/Switch";
import Table from "@components/table/Table";
import TableRow from "@components/tableRow/TableRow";
import Typography from "@mui/material/Typography";
import ICookieSection from "@containers/cookieConsent/interfaces/ICookieSection";
import ICookieSection from "@components/cookieConsent/interfaces/ICookieSection";
import CloseIcon from "@icons/CloseIcon";
import {
Dispatch,
Expand Down Expand Up @@ -64,10 +64,23 @@ export default function CookieModal({
);

return (
<Dialog open={open} onClose={closeModal} maxWidth="xs">
<div className="m-lg">
<div className="flex-column gap-md mb-md">
<div className="flex align-center justify-between">
<Dialog open={open} onClose={closeModal} maxWidth="sm">
<div sx={(theme) => ({ margin: theme.customProperties.spacing.lg })}>
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.md,
marginBottom: theme.customProperties.spacing.md,
})}
>
<div
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<Typography variant="h5">{t("cookie_modal__title")}</Typography>
<IconButton aria-label={t("global__close")} onClick={closeModal}>
<CloseIcon />
Expand All @@ -80,7 +93,7 @@ export default function CookieModal({
{t("cookie_modal__description_2")}
</Typography>
<Link
className="mr-a"
sx={(theme) => ({ marginRight: theme.customProperties.spacing.a })}
href={t("cookie_consent_link")}
underline="always"
external
Expand All @@ -90,7 +103,13 @@ export default function CookieModal({
</Typography>
</Link>
</div>
<div className="flex-column gap-lg">
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.lg,
})}
>
<Typography variant="body2">
{t("cookie_modal__description_3")}
</Typography>
Expand All @@ -103,7 +122,12 @@ export default function CookieModal({
onChange={handleExpand(index)}
>
<AccordionSummary>
<Typography variant="h6" className="mr-a">
<Typography
variant="h6"
sx={(theme) => ({
marginRight: theme.customProperties.spacing.a,
})}
>
{t(cookieType.title)}
</Typography>
<Switch
Expand All @@ -121,13 +145,20 @@ export default function CookieModal({
<Typography
variant="body2"
key={index}
className="mx-md mb-md"
sx={(theme) => ({
marginX: theme.customProperties.spacing.md,
marginBottom: theme.customProperties.spacing.md,
})}
>
{t(description)}
</Typography>
))}
{cookieType.cookies && (
<div className="m-md">
<div
sx={(theme) => ({
margin: theme.customProperties.spacing.md,
})}
>
<Table
columnTitles={[
t("cookie_modal__cookie_name"),
Expand All @@ -152,7 +183,14 @@ export default function CookieModal({
))}
</div>

<div className="flex-column justify-center gap-sm">
<div
sx={(theme) => ({
display: "flex",
flexDirection: "column",
gap: theme.customProperties.spacing.sm,
justifyContent: "center",
})}
>
<Button variant="contained" onClick={handleAcceptSelection}>
{t("cookie_modal__allow_selection")}
</Button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function DebugBanner() {
const pages = [
{
name: t(homeRoute.name),
to: homeRoute.paths[t("locale__key")],
to: `${homeRoute.paths[t("locale__key")]}`,
},
{
name: t(uikitRoute.name),
Expand All @@ -42,11 +42,13 @@ export default function DebugBanner() {
}

return (
<div className={"container"}>
<div
className={classes["container"]}
sx={(theme) => ({
zIndex: theme.zIndex.debugBanner,
})}
>
<div
sx={(theme) => ({
zIndex: theme.zIndex.debugBanner,
})}
className={classNames(classes["content"], {
[classes["local"]]: __ENV__ === "local",
[classes["dev"]]: __ENV__ === "dev",
Expand All @@ -63,9 +65,7 @@ export default function DebugBanner() {
))}
</div>

<Button size="small" onClick={closeBanner}>
{t("global__hide")}
</Button>
<Button onClick={closeBanner}>{t("global__hide")}</Button>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ export default function FieldHelperText({
}

return (
<Typography variant="caption" className="mt-xxs ml-md">
<Typography
variant="caption"
sx={(theme) => ({
marginTop: theme.customProperties.spacing.xxs,
marginLeft: theme.customProperties.spacing.md,
})}
>
{helperText}
</Typography>
);
Expand Down
Loading

0 comments on commit 7e84bbd

Please sign in to comment.