Initial commit: STR Optimization Manager MVP
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>
This commit is contained in:
47
apps/frontend/src/hooks/useAuth.ts
Normal file
47
apps/frontend/src/hooks/useAuth.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user