Add Supabase client setup and authentication functions

This commit is contained in:
2026-01-20 17:14:50 +00:00
parent dc4712d371
commit 9cd34d3ff1
7 changed files with 235 additions and 57 deletions

View File

@@ -2,6 +2,20 @@ import { RouterProvider } from 'react-router-dom';
import { router } from './routes';
const App = () => <RouterProvider router={router} />;
import { useEffect } from 'react'
import { signIn } from './lib/auth'
useEffect(() => {
;(async () => {
try {
await signIn('TEU_EMAIL', 'TUA_PASSWORD')
console.log('LOGIN OK')
} catch (e: any) {
console.log('LOGIN ERRO:', e.message)
}
})()
}, [])
export default App;

View File

@@ -1,38 +1,42 @@
import { Link, useNavigate } from 'react-router-dom';
import { MapPin, ShoppingCart, User, LogOut, Menu, X } from 'lucide-react';
import { Button } from '../ui/button';
import { useApp } from '../../context/AppContext';
import { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom'
import { MapPin, ShoppingCart, User, LogOut, Menu, X } from 'lucide-react'
import { useApp } from '../../context/AppContext'
import { useState } from 'react'
export const Header = () => {
const { user, cart, logout } = useApp();
const navigate = useNavigate();
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
const { user, cart, logout } = useApp()
const navigate = useNavigate()
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const handleLogout = () => {
logout();
navigate('/');
setMobileMenuOpen(false);
};
logout()
navigate('/')
setMobileMenuOpen(false)
}
return (
<header className="sticky top-0 z-30 bg-white/80 backdrop-blur-md border-b border-slate-200/60 shadow-sm">
<div className="mx-auto flex h-16 max-w-5xl items-center justify-between px-4">
<Link to="/" className="text-xl font-bold bg-gradient-to-r from-indigo-600 to-blue-700 bg-clip-text text-transparent hover:from-indigo-700 hover:to-blue-800 transition-all">
<Link
to="/"
className="text-xl font-bold bg-gradient-to-r from-indigo-600 to-blue-700 bg-clip-text text-transparent hover:from-indigo-700 hover:to-blue-800 transition-all"
onClick={() => setMobileMenuOpen(false)}
>
Smart Agenda
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center gap-4">
<Link
to="/explorar"
<Link
to="/explorar"
className="flex items-center gap-1.5 text-sm font-medium text-slate-700 hover:text-indigo-600 transition-colors px-3 py-1.5 rounded-lg hover:bg-indigo-50"
>
<MapPin size={16} />
<span>Barbearias</span>
</Link>
<Link
to="/carrinho"
<Link
to="/carrinho"
className="relative text-slate-700 hover:text-indigo-600 transition-colors p-2 rounded-lg hover:bg-indigo-50"
>
<ShoppingCart size={18} />
@@ -42,27 +46,34 @@ export const Header = () => {
</span>
)}
</Link>
{user ? (
<div className="flex items-center gap-2">
<button
onClick={() => navigate(user.role === 'barbearia' ? '/painel' : '/perfil')}
<button
onClick={() => navigate(user.role === 'barbearia' ? '/painel' : '/perfil')}
className="flex items-center gap-1.5 text-sm font-medium text-slate-700 hover:text-indigo-600 transition-colors px-3 py-1.5 rounded-lg hover:bg-indigo-50"
type="button"
>
<User size={16} />
<span className="max-w-[120px] truncate">{user.name}</span>
</button>
<button
onClick={handleLogout}
className="p-2 text-slate-600 hover:text-rose-600 hover:bg-rose-50 rounded-lg transition-colors"
title="Sair"
type="button"
>
<LogOut size={16} />
</button>
</div>
) : (
<Button asChild variant="outline" size="sm">
<Link to="/login">Entrar</Link>
</Button>
<Link
to="/login"
className="inline-flex items-center justify-center rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm font-medium text-slate-800 shadow-sm hover:bg-slate-50 transition-colors"
>
Entrar
</Link>
)}
</nav>
@@ -70,6 +81,7 @@ export const Header = () => {
<button
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
className="md:hidden p-2 text-slate-700 hover:text-amber-600 hover:bg-amber-50 rounded-lg transition-colors"
type="button"
>
{mobileMenuOpen ? <X size={20} /> : <Menu size={20} />}
</button>
@@ -87,6 +99,7 @@ export const Header = () => {
<MapPin size={16} />
Barbearias
</Link>
<Link
to="/carrinho"
onClick={() => setMobileMenuOpen(false)}
@@ -100,39 +113,42 @@ export const Header = () => {
</span>
)}
</Link>
{user ? (
<>
<button
onClick={() => {
navigate(user.role === 'barbearia' ? '/painel' : '/perfil');
setMobileMenuOpen(false);
navigate(user.role === 'barbearia' ? '/painel' : '/perfil')
setMobileMenuOpen(false)
}}
className="w-full flex items-center gap-2 text-sm font-medium text-slate-700 hover:text-amber-600 transition-colors px-3 py-2 rounded-lg hover:bg-amber-50 text-left"
type="button"
>
<User size={16} />
{user.name}
</button>
<button
onClick={handleLogout}
className="w-full flex items-center gap-2 text-sm font-medium text-rose-600 hover:bg-rose-50 transition-colors px-3 py-2 rounded-lg text-left"
type="button"
>
<LogOut size={16} />
Sair
</button>
</>
) : (
<Button asChild variant="solid" size="sm" className="w-full">
<Link to="/login" onClick={() => setMobileMenuOpen(false)}>Entrar</Link>
</Button>
<Link
to="/login"
onClick={() => setMobileMenuOpen(false)}
className="inline-flex w-full items-center justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 transition-colors"
>
Entrar
</Link>
)}
</nav>
</div>
)}
</header>
);
};
)
}

29
web/src/lib/auth.ts Normal file
View File

@@ -0,0 +1,29 @@
import { supabase } from './supabase'
export async function signIn(email: string, password: string) {
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
})
if (error) throw error
return data
}
export async function signUp(email: string, password: string) {
const { data, error } = await supabase.auth.signUp({
email,
password,
})
if (error) throw error
return data
}
export async function signOut() {
const { error } = await supabase.auth.signOut()
if (error) throw error
}
export async function getUser() {
const { data } = await supabase.auth.getUser()
return data.user
}

7
web/src/lib/supabase.ts Normal file
View File

@@ -0,0 +1,7 @@
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = 'https://jqklhhpyykzrktikjnmb.supabase.co'
const supabaseAnonKey =
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Impxa2xoaHB5eWt6cmt0aWtqbm1iIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjgzODQ0MDgsImV4cCI6MjA4Mzk2MDQwOH0.QsPuBnyUtRPSavlqKj3IGR9c8juT02LY_hSi-j3c6M0'
export const supabase = createClient(supabaseUrl, supabaseAnonKey)