feat: add oidc support with authentik
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
Users,
|
||||
FileText,
|
||||
TrendingUp,
|
||||
Shield,
|
||||
} from "lucide-react";
|
||||
|
||||
function SignInForm() {
|
||||
@@ -47,6 +48,15 @@ function SignInForm() {
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSocialSignIn() {
|
||||
setLoading(true);
|
||||
await authClient.signIn.sso({
|
||||
providerId: "authentik",
|
||||
callbackURL: callbackUrl,
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center relative overflow-hidden">
|
||||
{/* Blob Background */}
|
||||
@@ -129,6 +139,30 @@ function SignInForm() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
type="button"
|
||||
className="w-full h-11 relative rounded-xl"
|
||||
onClick={handleSocialSignIn}
|
||||
disabled={loading}
|
||||
>
|
||||
<Shield className="mr-2 h-4 w-4" />
|
||||
Sign in with Authentik
|
||||
</Button>
|
||||
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 flex items-center">
|
||||
<span className="w-full border-t border-border/50" />
|
||||
</div>
|
||||
<div className="relative flex justify-center text-xs uppercase">
|
||||
<span className="bg-background px-2 text-muted-foreground">
|
||||
Or continue with
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSignIn} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email">Email Address</Label>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { ModeSwitcher } from "./mode-switcher";
|
||||
import { ThemeSelector } from "./theme-selector";
|
||||
|
||||
export function AppearanceSettings() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<ModeSwitcher />
|
||||
<ThemeSelector />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useTheme } from "~/components/providers/theme-provider";
|
||||
import { Sun, Moon, Laptop } from "lucide-react";
|
||||
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs";
|
||||
|
||||
export function ModeSwitcher() {
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-1.5">
|
||||
<label className="font-medium">Appearance</label>
|
||||
<p className="text-muted-foreground text-xs leading-snug">
|
||||
{theme === "system"
|
||||
? "Follows system preference"
|
||||
: `Currently in ${theme} mode`}
|
||||
</p>
|
||||
</div>
|
||||
<Tabs
|
||||
value={theme}
|
||||
onValueChange={(value) => setTheme(value as "light" | "dark" | "system")}
|
||||
className="w-auto"
|
||||
>
|
||||
<TabsList>
|
||||
<TabsTrigger value="light">
|
||||
<Sun className="h-4 w-4" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="dark">
|
||||
<Moon className="h-4 w-4" />
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="system">
|
||||
<Laptop className="h-4 w-4" />
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -62,12 +62,12 @@ import { Textarea } from "~/components/ui/textarea";
|
||||
import { api } from "~/trpc/react";
|
||||
import { Switch } from "~/components/ui/switch";
|
||||
import { Slider } from "~/components/ui/slider";
|
||||
import { AppearanceSettings } from "./appearance-settings";
|
||||
import { useAnimationPreferences } from "~/components/providers/animation-preferences-provider";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
|
||||
|
||||
export function SettingsContent() {
|
||||
const { data: session } = authClient.useSession();
|
||||
// const session = { user: null } as any;
|
||||
const [name, setName] = useState("");
|
||||
const [deleteConfirmText, setDeleteConfirmText] = useState("");
|
||||
const [importData, setImportData] = useState("");
|
||||
@@ -294,7 +294,10 @@ export function SettingsContent() {
|
||||
if (profile?.name && !name) {
|
||||
setName(profile.name);
|
||||
}
|
||||
}, [profile?.name, name]);
|
||||
if (session?.user) {
|
||||
setName(session.user.name ?? "");
|
||||
}
|
||||
}, [session, profile?.name, name]);
|
||||
|
||||
// (Removed direct DOM mutation; provider handles applying preferences globally)
|
||||
|
||||
@@ -490,21 +493,7 @@ export function SettingsContent() {
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="preferences" className="space-y-8">
|
||||
{/* Appearance Settings */}
|
||||
<Card className="bg-card border-border border">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-foreground flex items-center gap-2">
|
||||
<Palette className="text-primary h-5 w-5" />
|
||||
Appearance
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Customize the look and feel of the application
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<AppearanceSettings />
|
||||
</CardContent>
|
||||
</Card>
|
||||
{/* Theme follows system preferences automatically via CSS media queries */}
|
||||
|
||||
{/* Accessibility & Animation */}
|
||||
<Card className="bg-card border-border border">
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { Check } from "lucide-react";
|
||||
import { cn } from "~/lib/utils";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "~/components/ui/tooltip";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import { useColorTheme } from "~/components/providers/color-theme-provider";
|
||||
|
||||
const themes = [
|
||||
{ name: "slate", hex: "#64748b" },
|
||||
{ name: "blue", hex: "#3b82f6" },
|
||||
{ name: "green", hex: "#22c55e" },
|
||||
{ name: "rose", hex: "#be123c" },
|
||||
{ name: "orange", hex: "#ea580c" },
|
||||
];
|
||||
|
||||
export function ThemeSelector() {
|
||||
const { colorTheme, setColorTheme } = useColorTheme();
|
||||
|
||||
return (
|
||||
<div className="space-y-1.5">
|
||||
<label className="font-medium">Theme</label>
|
||||
<p className="text-muted-foreground text-xs leading-snug">
|
||||
Select a theme for the application.
|
||||
</p>
|
||||
<div className="flex items-center gap-2 pt-2">
|
||||
<TooltipProvider>
|
||||
{themes.map((t) => (
|
||||
<Tooltip key={t.name}>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className={cn(
|
||||
"h-8 w-8 rounded-full border-2",
|
||||
colorTheme === t.name && "border-primary",
|
||||
)}
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
|
||||
onClick={() => setColorTheme(t.name as any)}
|
||||
style={{ backgroundColor: t.hex }}
|
||||
>
|
||||
{colorTheme === t.name && (
|
||||
<Check className="h-4 w-4 text-white" />
|
||||
)}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p className="capitalize">{t.name}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
))}
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+9
-13
@@ -6,8 +6,8 @@ import { Inter, Playfair_Display, Geist_Mono } from "next/font/google";
|
||||
import { TRPCReactProvider } from "~/trpc/react";
|
||||
import { Toaster } from "~/components/ui/sonner";
|
||||
import { AnimationPreferencesProvider } from "~/components/providers/animation-preferences-provider";
|
||||
import { ThemeProvider } from "~/components/providers/theme-provider";
|
||||
import { ColorThemeProvider } from "~/components/providers/color-theme-provider";
|
||||
|
||||
|
||||
import { UmamiScript } from "~/components/analytics/umami-script";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -51,17 +51,13 @@ export default function RootLayout({
|
||||
</div>
|
||||
|
||||
<TRPCReactProvider>
|
||||
<ThemeProvider>
|
||||
<ColorThemeProvider>
|
||||
<AnimationPreferencesProvider>
|
||||
<div className="relative z-10">
|
||||
{children}
|
||||
</div>
|
||||
</AnimationPreferencesProvider>
|
||||
<Toaster />
|
||||
<UmamiScript />
|
||||
</ColorThemeProvider>
|
||||
</ThemeProvider>
|
||||
<AnimationPreferencesProvider>
|
||||
<div className="relative z-10">
|
||||
{children}
|
||||
</div>
|
||||
</AnimationPreferencesProvider>
|
||||
<Toaster />
|
||||
<UmamiScript />
|
||||
</TRPCReactProvider>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user