Full-stack short-term rental management platform with: - React/Vite frontend with dark theme dashboard, performance, pricing, reservations, experiments, and settings pages - Fastify API server with auth, platform management, performance tracking, pricing, reservations, experiments, and weekly report endpoints - Playwright-based scraper service with Airbnb adapter (login with MFA, performance metrics, reservations, calendar pricing, price changes) - VRBO adapter scaffold and mock adapter for development - PostgreSQL with Drizzle ORM, migrations, and seed scripts - Job queue with worker for async scraping tasks - AES-256-GCM credential encryption for platform credentials - Session cookie persistence for scraper browser sessions - Docker Compose for PostgreSQL database Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react';
|
|
import { api, ApiError } from '@/lib/api';
|
|
|
|
interface AuthState {
|
|
isAuthenticated: boolean;
|
|
username: string | null;
|
|
isLoading: boolean;
|
|
}
|
|
|
|
export function useAuth() {
|
|
const [state, setState] = useState<AuthState>({
|
|
isAuthenticated: false,
|
|
username: null,
|
|
isLoading: true,
|
|
});
|
|
|
|
const checkSession = useCallback(async () => {
|
|
try {
|
|
const data = await api.me();
|
|
setState({ isAuthenticated: true, username: data.username, isLoading: false });
|
|
} catch {
|
|
setState({ isAuthenticated: false, username: null, isLoading: false });
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
checkSession();
|
|
}, [checkSession]);
|
|
|
|
const login = async (username: string, password: string) => {
|
|
try {
|
|
await api.login(username, password);
|
|
setState({ isAuthenticated: true, username, isLoading: false });
|
|
return true;
|
|
} catch (err) {
|
|
if (err instanceof ApiError) throw err;
|
|
throw new Error('Login failed');
|
|
}
|
|
};
|
|
|
|
const logout = async () => {
|
|
await api.logout();
|
|
setState({ isAuthenticated: false, username: null, isLoading: false });
|
|
};
|
|
|
|
return { ...state, login, logout, checkSession };
|
|
}
|