feat/Update_Controllers_to_Allow_for_Premium_Membership

This commit is contained in:
cesnimda
2026-08-03 09:17:28 +02:00
parent de937d25dc
commit c3f4a57195
187 changed files with 26062 additions and 991 deletions
@@ -0,0 +1,75 @@
import React, { useEffect, useState } from "react";
import { Alert, Box, Button, FormControlLabel, Paper, Skeleton, Switch, Typography } from "@mui/material";
import { api } from "../api";
import { useI18n } from "../i18n/I18nProvider";
import { useToast } from "../toast";
type AiSettings = {
enabled: boolean;
externalProcessingAllowed: boolean;
externalProcessingAvailable: boolean;
effectiveExternalProcessing: boolean;
provider: string;
};
export default function AiPrivacySettingsCard() {
const { t } = useI18n();
const { toast } = useToast();
const [settings, setSettings] = useState<AiSettings | null>(null);
const [failed, setFailed] = useState(false);
const [saving, setSaving] = useState(false);
useEffect(() => {
let active = true;
api.get<AiSettings>("/ai/settings")
.then((response) => { if (active) setSettings(response.data); })
.catch(() => { if (active) setFailed(true); });
return () => { active = false; };
}, []);
const save = async () => {
if (!settings) return;
setSaving(true);
setFailed(false);
try {
const response = await api.put<AiSettings>("/ai/settings", {
enabled: settings.enabled,
externalProcessingAllowed: settings.externalProcessingAllowed,
});
setSettings(response.data);
toast(t("settingsAiSaved"), "success");
} catch {
setFailed(true);
} finally {
setSaving(false);
}
};
return (
<Paper sx={{ p: 2.5, borderRadius: 4, border: "none" }}>
<Typography variant="overline" sx={{ color: "text.secondary", fontWeight: 800 }}>{t("settingsAiPrivacyTitle")}</Typography>
<Typography variant="body2" sx={{ color: "text.secondary", mt: 0.25, mb: 1.5 }}>{t("settingsAiPrivacyBody")}</Typography>
{failed ? <Alert severity="error" sx={{ mb: 1.5 }}>{t("settingsAiPrivacyUnavailable")}</Alert> : null}
{!settings ? <Skeleton variant="rounded" height={96} /> : <Box sx={{ display: "grid", gap: 1 }}>
<FormControlLabel
control={<Switch checked={settings.enabled} onChange={(event) => setSettings({ ...settings, enabled: event.target.checked })} />}
label={t("settingsAiEnabled")}
/>
<FormControlLabel
control={<Switch
checked={settings.externalProcessingAllowed}
disabled={!settings.externalProcessingAvailable && !settings.externalProcessingAllowed}
onChange={(event) => setSettings({ ...settings, externalProcessingAllowed: event.target.checked })}
/>}
label={t("settingsAiExternalAllowed")}
/>
<Typography variant="caption" sx={{ color: "text.secondary" }}>
{settings.externalProcessingAvailable
? t("settingsAiExternalAvailable")
: t("settingsAiExternalLocalOnly")}
</Typography>
<Box><Button variant="contained" disabled={saving} onClick={() => void save()}>{t("settingsAiSave")}</Button></Box>
</Box>}
</Paper>
);
}