ki integration
This commit is contained in:
101
client/src/lib/session.tsx
Normal file
101
client/src/lib/session.tsx
Normal file
@@ -0,0 +1,101 @@
|
||||
import { createContext, useCallback, useContext, useEffect, useState, type ReactNode } from 'react';
|
||||
|
||||
import {
|
||||
abmelden as abmeldenApi,
|
||||
aktuellesKonto,
|
||||
brandSicherstellen,
|
||||
eigeneBrand,
|
||||
type Brand,
|
||||
type Konto,
|
||||
} from './auth';
|
||||
import { ordnerListe, type Ordner } from './folders';
|
||||
|
||||
type Session = {
|
||||
/** true, solange noch nicht feststeht, ob jemand angemeldet ist. */
|
||||
laedt: boolean;
|
||||
konto: Konto | null;
|
||||
brand: Brand | null;
|
||||
/**
|
||||
* Der aktive Ordner bestimmt, welches Wissen in den Prompt wandert. Er ist
|
||||
* deshalb App-Zustand und kein Bildschirm-lokaler Wert (app-aufbau.md §2.2) –
|
||||
* sonst generiert der Nutzer im falschen Scope und versteht das Ergebnis nicht.
|
||||
*/
|
||||
aktiverOrdner: Ordner | null;
|
||||
ordner: Ordner[];
|
||||
setzeAktivenOrdner: (o: Ordner | null) => void;
|
||||
ordnerNeuLaden: () => Promise<void>;
|
||||
neuLaden: () => Promise<void>;
|
||||
ausloggen: () => Promise<void>;
|
||||
};
|
||||
|
||||
const Ctx = createContext<Session | null>(null);
|
||||
|
||||
export function SessionProvider({ children }: { children: ReactNode }) {
|
||||
const [laedt, setLaedt] = useState(true);
|
||||
const [konto, setKonto] = useState<Konto | null>(null);
|
||||
const [brand, setBrand] = useState<Brand | null>(null);
|
||||
const [ordner, setOrdner] = useState<Ordner[]>([]);
|
||||
const [aktiverOrdner, setzeAktivenOrdner] = useState<Ordner | null>(null);
|
||||
|
||||
const ordnerFuer = useCallback(async (b: Brand | null) => {
|
||||
if (!b) {
|
||||
setOrdner([]);
|
||||
setzeAktivenOrdner(null);
|
||||
return;
|
||||
}
|
||||
const liste = await ordnerListe(b.$id);
|
||||
setOrdner(liste);
|
||||
setzeAktivenOrdner((bisher) => {
|
||||
if (bisher) return liste.find((o) => o.$id === bisher.$id) ?? liste[0] ?? null;
|
||||
return liste.find((o) => o.ist_default) ?? liste[0] ?? null;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const neuLaden = useCallback(async () => {
|
||||
const k = await aktuellesKonto();
|
||||
setKonto(k);
|
||||
if (!k) {
|
||||
setBrand(null);
|
||||
await ordnerFuer(null);
|
||||
setLaedt(false);
|
||||
return;
|
||||
}
|
||||
// Konto ohne Brand kann entstehen, wenn die Registrierung mittendrin
|
||||
// abgebrochen ist – hier wird das stillschweigend nachgeholt.
|
||||
let b = await eigeneBrand();
|
||||
if (!b) b = await brandSicherstellen(k.name || k.email);
|
||||
setBrand(b);
|
||||
await ordnerFuer(b);
|
||||
setLaedt(false);
|
||||
}, [ordnerFuer]);
|
||||
|
||||
const ordnerNeuLaden = useCallback(() => ordnerFuer(brand), [brand, ordnerFuer]);
|
||||
|
||||
const ausloggen = useCallback(async () => {
|
||||
await abmeldenApi();
|
||||
setKonto(null);
|
||||
setBrand(null);
|
||||
setOrdner([]);
|
||||
setzeAktivenOrdner(null);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
void neuLaden();
|
||||
}, [neuLaden]);
|
||||
|
||||
return (
|
||||
<Ctx.Provider
|
||||
value={{
|
||||
laedt, konto, brand, ordner, aktiverOrdner,
|
||||
setzeAktivenOrdner, ordnerNeuLaden, neuLaden, ausloggen,
|
||||
}}>
|
||||
{children}
|
||||
</Ctx.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useSession(): Session {
|
||||
const v = useContext(Ctx);
|
||||
if (!v) throw new Error('useSession muss innerhalb von <SessionProvider> stehen.');
|
||||
return v;
|
||||
}
|
||||
Reference in New Issue
Block a user