Skip to content

Commit

Permalink
Feature/v1 api (#847)
Browse files Browse the repository at this point in the history
* feat: Initialize API v1 for Ingredients

* feat(i18n): Added translations for tooltip

* feat(SCSS): Upgraded to newer SCSS version
  • Loading branch information
philipbrembeck authored Oct 27, 2024
1 parent 7aa9a50 commit 9cbaade
Show file tree
Hide file tree
Showing 42 changed files with 638 additions and 405 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"scripts": {
"preinstall": "npx only-allow pnpm",
"dev": "next dev --turbopack",
"dev": "next dev",
"build": "next build",
"start": "next start -p 1030",
"stage": "next start -p 1031",
Expand All @@ -25,7 +25,7 @@
"dependencies": {
"@ducanh2912/next-pwa": "^10.2.9",
"@ericblade/quagga2": "^1.8.4",
"@frontendnetwork/veganify": "^1.2.9",
"@frontendnetwork/veganify": "^1.3.0",
"@types/node": "22.8.1",
"@types/react-dom": "npm:[email protected]",
"jest-worker": "^29.7.0",
Expand Down
10 changes: 5 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions src/components/IngredientsCheck/IngredientsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,21 @@ export function IngredientsForm() {
vegan: null,
surelyVegan: [],
notVegan: [],
maybeVegan: [],
maybeNotVegan: [],
unknown: [],
});
const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false);

async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
setResult({ vegan: null, surelyVegan: [], notVegan: [], maybeVegan: [] });
setResult({
vegan: null,
surelyVegan: [],
notVegan: [],
maybeNotVegan: [],
unknown: [],
});
setError(null);

const formData = new FormData(event.currentTarget);
Expand Down
46 changes: 32 additions & 14 deletions src/components/IngredientsCheck/IngredientsList.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
import React from "react";
import { IconClassType } from "./models/Tooltip";
import { TranslationFunction } from "./models/TranslateFunction";
import { TooltipClient } from "./shared/Tooltip";

export function IngredientList({
items,
iconClass,
}: {
interface IngredientListProps {
items: string[];
iconClass: string;
}) {
iconClass: IconClassType;
t: TranslationFunction;
}

export function IngredientList({ items, iconClass, t }: IngredientListProps) {
const tooltipMessages = {
"maybe-vegan": t("maybe_vegan"),
"unknown-vegan": t("unknown_vegan"),
} as const;

const shouldShowTooltip =
iconClass.includes("maybe-vegan") || iconClass.includes("unknown-vegan");
const tooltipBaseClass = iconClass.split(
" "
)[0] as keyof typeof tooltipMessages;
const tooltipMessage = shouldShowTooltip
? tooltipMessages[tooltipBaseClass]
: "";

return (
<>
{items.map((item) => (
<div className="Grid" key={item}>
<div className="Grid-cell description">
{item.charAt(0).toUpperCase() + item.slice(1)}
</div>
<div className="Grid-cell icons">
<span className={iconClass}></span>
<TooltipClient message={tooltipMessage as string} key={item}>
<div className="Grid">
<div className="Grid-cell description">
{item.charAt(0).toUpperCase() + item.slice(1)}
</div>
<div className="Grid-cell icons">
<span className={iconClass}></span>
</div>
</div>
</div>
</TooltipClient>
))}
</>
);
Expand Down
24 changes: 16 additions & 8 deletions src/components/IngredientsCheck/ResultsDisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { IngredientList } from "./IngredientsList";
import { IngredientResult } from "./models/IngredientResult";
import { TranslationFunction } from "./models/TranslateFunction";
import { SourceInfo } from "./SourceInfo";

export function ResultDisplay({
result,
t,
}: {
interface ResultDisplayProps {
result: IngredientResult;
t: (key: string, values?: Record<string, string>) => string;
}) {
t: TranslationFunction;
}

export function ResultDisplay({ result, t }: ResultDisplayProps) {
return (
<div id="result">
<div className="">
Expand All @@ -28,14 +28,22 @@ export function ResultDisplay({
<IngredientList
items={result.notVegan}
iconClass="non-vegan icon-cancel"
t={t}
/>
<IngredientList
items={result.unknown}
iconClass="unknown-vegan icon-help"
t={t}
/>
<IngredientList
items={result.maybeVegan}
iconClass="maybe-vegan icon-help"
items={result.maybeNotVegan}
iconClass="maybe-vegan icon-attention-alt"
t={t}
/>
<IngredientList
items={result.surelyVegan}
iconClass="vegan icon-ok"
t={t}
/>
<SourceInfo t={t} />
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/IngredientsCheck/models/IngredientResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ export interface IngredientResult {
vegan: boolean | null;
surelyVegan: string[];
notVegan: string[];
maybeVegan: string[];
maybeNotVegan: string[];
unknown: string[];
}
10 changes: 10 additions & 0 deletions src/components/IngredientsCheck/models/Tooltip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type IconClassType =
| "vegan icon-ok"
| "non-vegan icon-cancel"
| "unknown-vegan icon-help"
| "maybe-vegan icon-attention-alt";

export interface TooltipMessages {
"maybe-vegan": string;
"unkown-vegan": string;
}
4 changes: 4 additions & 0 deletions src/components/IngredientsCheck/models/TranslateFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type TranslationFunction = (
key: string,
values?: Record<string, string>
) => string;
32 changes: 32 additions & 0 deletions src/components/IngredientsCheck/shared/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"use client";

import { useState } from "react";

interface TooltipProps {
message: string;
children: React.ReactNode;
}

export function TooltipClient({ message, children }: TooltipProps) {
const [isVisible, setIsVisible] = useState(false);

if (!message) {
return children;
}

return (
<div
className="tooltip-wrapper"
onMouseEnter={() => setIsVisible(true)}
onMouseLeave={() => setIsVisible(false)}
>
{children}
{isVisible && (
<div className="tooltip">
{message}
<div className="tooltip-arrow"></div>
</div>
)}
</div>
);
}
Loading

0 comments on commit 9cbaade

Please sign in to comment.