mirror of
https://github.com/FranP-code/inbox-negotiator.git
synced 2025-10-13 00:42:26 +00:00
feat: enhance Navbar with user profile and configuration links
- Updated Navbar component to include a link to the configuration page. - Added a new Settings icon and link for user configuration. - Improved user session handling and UI updates based on authentication state. feat: implement OnboardingDialog for user setup - Created OnboardingDialog component to guide users through initial setup. - Added functionality to collect additional email addresses during onboarding. - Integrated toast notifications for error handling during email addition. feat: extend Supabase admin functions for user management - Added functions to retrieve user IDs and full user information by email. - Implemented error handling and logging for database operations. feat: update Supabase schema with new user features - Created new tables: user_profiles, additional_emails, and email_processing_usage. - Enabled Row Level Security (RLS) on new tables with appropriate policies. - Added triggers and functions for automatic user profile creation and email usage tracking. feat: create public users table for simplified access - Established a public.users table to mirror relevant auth.users data. - Implemented triggers to automatically populate public.users upon user creation. - Set up RLS policies to restrict access to user data. chore: add configuration files for Supabase local development - Included .gitignore and config.toml for local Supabase setup. - Configured email testing server and other development settings. feat: add configuration page for user settings - Created configuration.astro page to manage user settings. - Integrated AuthGuard to protect the configuration route.
This commit is contained in:
@@ -1,104 +1,118 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { supabase } from '../lib/supabase';
|
||||
import type { User } from '@supabase/supabase-js';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
||||
import { BarChart3, LogOut, User as UserIcon } from 'lucide-react';
|
||||
import { ModeToggle } from './ModeToggle';
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { supabase } from "../lib/supabase";
|
||||
import type { User } from "@supabase/supabase-js";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { BarChart3, LogOut, User as UserIcon, Settings } from "lucide-react";
|
||||
import { ModeToggle } from "./ModeToggle";
|
||||
|
||||
export function Navbar() {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
supabase.auth.getSession().then(({ data: { session } }) => {
|
||||
setUser(session?.user ?? null);
|
||||
});
|
||||
useEffect(() => {
|
||||
supabase.auth.getSession().then(({ data: { session } }) => {
|
||||
setUser(session?.user ?? null);
|
||||
});
|
||||
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange(
|
||||
(event, session) => {
|
||||
setUser(session?.user ?? null);
|
||||
}
|
||||
);
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange((event, session) => {
|
||||
setUser(session?.user ?? null);
|
||||
});
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, []);
|
||||
return () => subscription.unsubscribe();
|
||||
}, []);
|
||||
|
||||
const handleSignOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
window.location.href = '/';
|
||||
};
|
||||
const handleSignOut = async () => {
|
||||
await supabase.auth.signOut();
|
||||
window.location.href = "/";
|
||||
};
|
||||
|
||||
const getInitials = (email: string) => {
|
||||
return email.substring(0, 2).toUpperCase();
|
||||
};
|
||||
const getInitials = (email: string) => {
|
||||
return email.substring(0, 2).toUpperCase();
|
||||
};
|
||||
|
||||
return (
|
||||
<nav className="border-b bg-white dark:bg-background">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
<div className="flex items-center gap-3">
|
||||
<BarChart3 className="h-8 w-8 text-primary" />
|
||||
<a href="/" className="text-xl font-bold text-gray-900 dark:text-foreground">
|
||||
InboxNegotiator
|
||||
</a>
|
||||
</div>
|
||||
return (
|
||||
<nav className="border-b bg-white dark:bg-background">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
<div className="flex items-center gap-3">
|
||||
<BarChart3 className="h-8 w-8 text-primary" />
|
||||
<a
|
||||
href={user ? "/dashboard" : "/"}
|
||||
className="text-xl font-bold text-gray-900 dark:text-foreground"
|
||||
>
|
||||
InboxNegotiator
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4">
|
||||
<ModeToggle />
|
||||
{user ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarFallback className="text-xs">
|
||||
{getInitials(user.email || '')}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56" align="end">
|
||||
<div className="flex items-center justify-start gap-2 p-2">
|
||||
<div className="flex flex-col space-y-1 leading-none">
|
||||
<p className="font-medium text-sm">{user.user_metadata?.full_name || 'User'}</p>
|
||||
<p className="w-[200px] truncate text-xs text-muted-foreground">
|
||||
{user.email}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem asChild>
|
||||
<a href="/dashboard" className="flex items-center">
|
||||
<UserIcon className="mr-2 h-4 w-4" />
|
||||
Dashboard
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleSignOut}>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
Sign out
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" asChild>
|
||||
<a href="/login">Sign In</a>
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<a href="/signup">Get Started</a>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
<div className="flex items-center gap-4">
|
||||
<ModeToggle />
|
||||
{user ? (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="relative h-8 w-8 rounded-full"
|
||||
>
|
||||
<Avatar className="h-8 w-8">
|
||||
<AvatarFallback className="text-xs">
|
||||
{getInitials(user.email || "")}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-56" align="end">
|
||||
<div className="flex items-center justify-start gap-2 p-2">
|
||||
<div className="flex flex-col space-y-1 leading-none">
|
||||
<p className="font-medium text-sm">
|
||||
{user.user_metadata?.full_name || "User"}
|
||||
</p>
|
||||
<p className="w-[200px] truncate text-xs text-muted-foreground">
|
||||
{user.email}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem asChild>
|
||||
<a href="/dashboard" className="flex items-center">
|
||||
<UserIcon className="mr-2 h-4 w-4" />
|
||||
Dashboard
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem asChild>
|
||||
<a href="/configuration" className="flex items-center">
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
Configuration
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleSignOut}>
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
Sign out
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button variant="ghost" asChild>
|
||||
<a href="/login">Sign In</a>
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<a href="/signup">Get Started</a>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user