ultisuite-client/components/admin/settings/sections/nextcloud-section.tsx
2026-06-07 21:55:42 +02:00

128 lines
4.7 KiB
TypeScript

"use client"
import { OrgSettingsSection } from "@/components/admin/settings/org-settings-form"
import { DeployLockedHint, useDeployFieldLocked } from "@/components/admin/settings/deploy-locked-hint"
import { useOrgSettingsStore } from "@/lib/admin-settings/org-settings-store"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
export function NextcloudSection() {
const nextcloud = useOrgSettingsStore((s) => s.nextcloud)
const setNextcloud = useOrgSettingsStore((s) => s.setNextcloud)
const effective = useOrgSettingsStore((s) => s.meta?.effective.nextcloud)
const enabledLocked = useDeployFieldLocked("nextcloud", "enabled")
const urlLocked = useDeployFieldLocked("nextcloud", "base_url")
const userLocked = useDeployFieldLocked("nextcloud", "admin_user")
const passLocked = useDeployFieldLocked("nextcloud", "admin_password")
const enabled = enabledLocked ? (effective?.enabled ?? nextcloud.enabled) : nextcloud.enabled
const baseURL = urlLocked ? (effective?.base_url ?? nextcloud.base_url) : nextcloud.base_url
const adminUser = userLocked ? (effective?.admin_user ?? nextcloud.admin_user) : nextcloud.admin_user
return (
<OrgSettingsSection
title="Nextcloud"
description="Connexion au serveur Nextcloud pour drive, agenda, contacts et Talk."
policySection="nextcloud"
>
<Card>
<CardHeader className="pb-3">
<div className="flex items-center justify-between gap-4">
<div>
<CardTitle className="text-sm font-medium">Intégration Nextcloud</CardTitle>
<CardDescription>Variables NEXTCLOUD_* côté serveur.</CardDescription>
{enabledLocked ? <DeployLockedHint section="nextcloud" field="enabled" /> : null}
</div>
<Switch
checked={enabled}
disabled={enabledLocked}
onCheckedChange={(v) => setNextcloud({ enabled: v })}
/>
</div>
</CardHeader>
<CardContent className="grid gap-4 sm:grid-cols-2">
<div className="sm:col-span-2">
<Label>URL de base</Label>
<Input
className="mt-1 h-9"
value={baseURL}
disabled={urlLocked}
onChange={(e) => setNextcloud({ base_url: e.target.value })}
placeholder="https://cloud.example.com"
/>
</div>
<div>
<Label>Utilisateur admin</Label>
<Input
className="mt-1 h-9"
value={adminUser}
disabled={userLocked}
onChange={(e) => setNextcloud({ admin_user: e.target.value })}
/>
</div>
<div>
<Label>Mot de passe admin</Label>
<Input
className="mt-1 h-9"
type="password"
value={nextcloud.admin_password}
disabled={passLocked}
onChange={(e) => setNextcloud({ admin_password: e.target.value })}
placeholder={passLocked ? "Défini via NC_ADMIN_PASSWORD" : undefined}
/>
</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-sm font-medium">Services activés</CardTitle>
<CardDescription>Modules suite exposés aux utilisateurs.</CardDescription>
</CardHeader>
<CardContent className="space-y-3">
<ServiceToggle
label="UltiDrive (fichiers)"
checked={nextcloud.drive_enabled}
onChange={(drive_enabled) => setNextcloud({ drive_enabled })}
/>
<ServiceToggle
label="Agenda"
checked={nextcloud.calendar_enabled}
onChange={(calendar_enabled) => setNextcloud({ calendar_enabled })}
/>
<ServiceToggle
label="Contacts"
checked={nextcloud.contacts_enabled}
onChange={(contacts_enabled) => setNextcloud({ contacts_enabled })}
/>
<ServiceToggle
label="Talk (visio)"
checked={nextcloud.talk_enabled}
onChange={(talk_enabled) => setNextcloud({ talk_enabled })}
/>
</CardContent>
</Card>
</OrgSettingsSection>
)
}
function ServiceToggle({
label,
checked,
onChange,
}: {
label: string
checked: boolean
onChange: (v: boolean) => void
}) {
return (
<label className="flex items-center justify-between gap-4 rounded-lg border p-3">
<span className="text-sm font-medium">{label}</span>
<Switch checked={checked} onCheckedChange={onChange} />
</label>
)
}