feat/Update_Controllers_to_Allow_for_Premium_Membership
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user