Automatisch-übersetzen-Button nur bei konfiguriertem DEEPL_API_KEY
Statt den Button immer anzuzeigen und erst nach Klick auf die fehlende Konfiguration hinzuweisen, wird er serverseitig anhand von process.env.DEEPL_API_KEY ein-/ausgeblendet (Gerichte, Allergene, Zusatzstoffe). Die dadurch überflüssige "translateUnavailable"- Meldung wurde aus allen drei Sprachen entfernt.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import DishManager from "@/components/DishManager";
|
import DishManager from "@/components/DishManager";
|
||||||
|
|
||||||
export default function GerichtePage() {
|
export default function GerichtePage() {
|
||||||
return <DishManager />;
|
return <DishManager translateEnabled={!!process.env.DEEPL_API_KEY} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import CodeListManager from "@/components/CodeListManager";
|
import CodeListManager from "@/components/CodeListManager";
|
||||||
|
|
||||||
export default function KennzeichnungPage() {
|
export default function KennzeichnungPage() {
|
||||||
|
const translateEnabled = !!process.env.DEEPL_API_KEY;
|
||||||
return (
|
return (
|
||||||
<div className="grid gap-6 lg:grid-cols-2">
|
<div className="grid gap-6 lg:grid-cols-2">
|
||||||
<CodeListManager table="allergens" />
|
<CodeListManager table="allergens" translateEnabled={translateEnabled} />
|
||||||
<CodeListManager table="additives" />
|
<CodeListManager table="additives" translateEnabled={translateEnabled} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import { useDict, useLocale } from "@/components/i18n/LocaleProvider";
|
|||||||
|
|
||||||
export default function CodeListManager({
|
export default function CodeListManager({
|
||||||
table,
|
table,
|
||||||
|
translateEnabled,
|
||||||
}: {
|
}: {
|
||||||
table: "allergens" | "additives";
|
table: "allergens" | "additives";
|
||||||
|
translateEnabled: boolean;
|
||||||
}) {
|
}) {
|
||||||
const supabase = useMemo(() => createClient(), []);
|
const supabase = useMemo(() => createClient(), []);
|
||||||
const dict = useDict();
|
const dict = useDict();
|
||||||
@@ -34,9 +36,9 @@ export default function CodeListManager({
|
|||||||
namePl: string;
|
namePl: string;
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [translateState, setTranslateState] = useState<
|
const [translateState, setTranslateState] = useState<"idle" | "busy" | "done">(
|
||||||
"idle" | "busy" | "done" | "unavailable"
|
"idle"
|
||||||
>("idle");
|
);
|
||||||
|
|
||||||
const load = useCallback(async () => {
|
const load = useCallback(async () => {
|
||||||
const { data, error } = await supabase.from(table).select("*").order("sort");
|
const { data, error } = await supabase.from(table).select("*").order("sort");
|
||||||
@@ -115,10 +117,6 @@ export default function CodeListManager({
|
|||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (!res.ok) throw new Error(data?.error ?? `Fehler (${res.status})`);
|
if (!res.ok) throw new Error(data?.error ?? `Fehler (${res.status})`);
|
||||||
if (data.configured === false) {
|
|
||||||
setTranslateState("unavailable");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setEditing((prev) =>
|
setEditing((prev) =>
|
||||||
prev ? { ...prev, nameEn: data.en ?? prev.nameEn, namePl: data.pl ?? prev.namePl } : prev
|
prev ? { ...prev, nameEn: data.en ?? prev.nameEn, namePl: data.pl ?? prev.namePl } : prev
|
||||||
);
|
);
|
||||||
@@ -191,28 +189,25 @@ export default function CodeListManager({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
{translateEnabled && (
|
||||||
<button
|
<div>
|
||||||
type="button"
|
<button
|
||||||
className="btn btn-neutral"
|
type="button"
|
||||||
onClick={autoTranslate}
|
className="btn btn-neutral"
|
||||||
disabled={translateState === "busy" || !editing.name.trim()}
|
onClick={autoTranslate}
|
||||||
>
|
disabled={translateState === "busy" || !editing.name.trim()}
|
||||||
{translateState === "busy"
|
>
|
||||||
? dict.dishManager.translating
|
{translateState === "busy"
|
||||||
: dict.dishManager.autoTranslate}
|
? dict.dishManager.translating
|
||||||
</button>
|
: dict.dishManager.autoTranslate}
|
||||||
{translateState === "done" && (
|
</button>
|
||||||
<span className="ml-2 text-sm text-green-700">
|
{translateState === "done" && (
|
||||||
{dict.dishManager.translated}
|
<span className="ml-2 text-sm text-green-700">
|
||||||
</span>
|
{dict.dishManager.translated}
|
||||||
)}
|
</span>
|
||||||
{translateState === "unavailable" && (
|
)}
|
||||||
<span className="ml-2 text-sm text-gray-500">
|
</div>
|
||||||
{dict.dishManager.translateUnavailable}
|
)}
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button type="submit" className="btn btn-add">
|
<button type="submit" className="btn btn-add">
|
||||||
{dict.common.save}
|
{dict.common.save}
|
||||||
|
|||||||
+27
-30
@@ -29,7 +29,11 @@ const EMPTY_FORM: DishForm = {
|
|||||||
additives: [],
|
additives: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function DishManager() {
|
export default function DishManager({
|
||||||
|
translateEnabled,
|
||||||
|
}: {
|
||||||
|
translateEnabled: boolean;
|
||||||
|
}) {
|
||||||
const supabase = useMemo(() => createClient(), []);
|
const supabase = useMemo(() => createClient(), []);
|
||||||
const dict = useDict();
|
const dict = useDict();
|
||||||
const locale = useLocale();
|
const locale = useLocale();
|
||||||
@@ -42,9 +46,9 @@ export default function DishManager() {
|
|||||||
const [selected, setSelected] = useState<Set<string>>(new Set());
|
const [selected, setSelected] = useState<Set<string>>(new Set());
|
||||||
const [bulkBusy, setBulkBusy] = useState(false);
|
const [bulkBusy, setBulkBusy] = useState(false);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [translateState, setTranslateState] = useState<
|
const [translateState, setTranslateState] = useState<"idle" | "busy" | "done">(
|
||||||
"idle" | "busy" | "done" | "unavailable"
|
"idle"
|
||||||
>("idle");
|
);
|
||||||
|
|
||||||
// Live-Suche: filtert die Liste bereits während des Tippens
|
// Live-Suche: filtert die Liste bereits während des Tippens
|
||||||
const visible = useMemo(() => {
|
const visible = useMemo(() => {
|
||||||
@@ -199,10 +203,6 @@ export default function DishManager() {
|
|||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
if (!res.ok) throw new Error(data?.error ?? `Fehler (${res.status})`);
|
if (!res.ok) throw new Error(data?.error ?? `Fehler (${res.status})`);
|
||||||
if (data.configured === false) {
|
|
||||||
setTranslateState("unavailable");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setForm((prev) =>
|
setForm((prev) =>
|
||||||
prev ? { ...prev, nameEn: data.en ?? prev.nameEn, namePl: data.pl ?? prev.namePl } : prev
|
prev ? { ...prev, nameEn: data.en ?? prev.nameEn, namePl: data.pl ?? prev.namePl } : prev
|
||||||
);
|
);
|
||||||
@@ -296,28 +296,25 @@ export default function DishManager() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
{translateEnabled && (
|
||||||
<button
|
<div>
|
||||||
type="button"
|
<button
|
||||||
className="btn btn-neutral"
|
type="button"
|
||||||
onClick={autoTranslate}
|
className="btn btn-neutral"
|
||||||
disabled={translateState === "busy" || !form.name.trim()}
|
onClick={autoTranslate}
|
||||||
>
|
disabled={translateState === "busy" || !form.name.trim()}
|
||||||
{translateState === "busy"
|
>
|
||||||
? dict.dishManager.translating
|
{translateState === "busy"
|
||||||
: dict.dishManager.autoTranslate}
|
? dict.dishManager.translating
|
||||||
</button>
|
: dict.dishManager.autoTranslate}
|
||||||
{translateState === "done" && (
|
</button>
|
||||||
<span className="ml-2 text-sm text-green-700">
|
{translateState === "done" && (
|
||||||
{dict.dishManager.translated}
|
<span className="ml-2 text-sm text-green-700">
|
||||||
</span>
|
{dict.dishManager.translated}
|
||||||
)}
|
</span>
|
||||||
{translateState === "unavailable" && (
|
)}
|
||||||
<span className="ml-2 text-sm text-gray-500">
|
</div>
|
||||||
{dict.dishManager.translateUnavailable}
|
)}
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ChipPicker
|
<ChipPicker
|
||||||
label={dict.codeList.allergensTitle}
|
label={dict.codeList.allergensTitle}
|
||||||
|
|||||||
@@ -88,8 +88,6 @@ const de = {
|
|||||||
autoTranslate: "Automatisch übersetzen",
|
autoTranslate: "Automatisch übersetzen",
|
||||||
translating: "Übersetze…",
|
translating: "Übersetze…",
|
||||||
translated: "Übersetzt.",
|
translated: "Übersetzt.",
|
||||||
translateUnavailable:
|
|
||||||
"Automatische Übersetzung ist nicht eingerichtet. Bitte Englisch/Polnisch manuell ausfüllen.",
|
|
||||||
priceLabel: "Preis in €",
|
priceLabel: "Preis in €",
|
||||||
pricePlaceholder: "3,50",
|
pricePlaceholder: "3,50",
|
||||||
searchPlaceholder: "Gericht suchen…",
|
searchPlaceholder: "Gericht suchen…",
|
||||||
@@ -346,8 +344,6 @@ const en: Dict = {
|
|||||||
autoTranslate: "Auto-translate",
|
autoTranslate: "Auto-translate",
|
||||||
translating: "Translating…",
|
translating: "Translating…",
|
||||||
translated: "Translated.",
|
translated: "Translated.",
|
||||||
translateUnavailable:
|
|
||||||
"Automatic translation is not set up. Please fill in English/Polish manually.",
|
|
||||||
priceLabel: "Price in €",
|
priceLabel: "Price in €",
|
||||||
pricePlaceholder: "3.50",
|
pricePlaceholder: "3.50",
|
||||||
searchPlaceholder: "Search dishes…",
|
searchPlaceholder: "Search dishes…",
|
||||||
@@ -602,8 +598,6 @@ const pl: Dict = {
|
|||||||
autoTranslate: "Przetłumacz automatycznie",
|
autoTranslate: "Przetłumacz automatycznie",
|
||||||
translating: "Tłumaczenie…",
|
translating: "Tłumaczenie…",
|
||||||
translated: "Przetłumaczono.",
|
translated: "Przetłumaczono.",
|
||||||
translateUnavailable:
|
|
||||||
"Automatyczne tłumaczenie nie jest skonfigurowane. Wypełnij angielski/polski ręcznie.",
|
|
||||||
priceLabel: "Cena w €",
|
priceLabel: "Cena w €",
|
||||||
pricePlaceholder: "3,50",
|
pricePlaceholder: "3,50",
|
||||||
searchPlaceholder: "Szukaj dania…",
|
searchPlaceholder: "Szukaj dania…",
|
||||||
|
|||||||
Reference in New Issue
Block a user