wrongmove/crawler/frontend/src/App.tsx

122 lines
4.2 KiB
TypeScript
Raw Normal View History

import type { User } from 'oidc-client-ts';
import { useEffect, useState } from 'react';
import './App.css';
import { AppSidebar } from './AppSidebar';
import { getUser, handleCallback, logout } from './auth/authService';
import LoginModal from './components/LoginModal';
import { Map } from './components/Map';
import { Parameters, type ParameterValues } from './components/Parameters';
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from './components/ui/breadcrumb';
import { Button } from './components/ui/button';
import { Separator } from './components/ui/separator';
import { SidebarInset, SidebarProvider, SidebarTrigger } from './components/ui/sidebar';
function App() {
const [listingData, setListingData] = useState({});
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
// Check if this is a callback from Authentik (after login)
if (window.location.pathname === '/callback') {
handleCallback().then(() => {
window.location.href = '/'; // Redirect to home after login
});
return;
}
// Load user data
getUser().then(setUser);
}, []);
const [isParametersModalOpen, setIsParametersModalOpen] = useState(true)
const [error, setError] = useState('')
const [queryParameters, setQueryParameters] = useState<ParameterValues | null>(null)
const fetchData = async (parameters: ParameterValues) => {
const accessToken = user?.access_token;
const queryString = new URLSearchParams();
queryString.append('listing_type', parameters.listing_type)
if (parameters.max_price) {
queryString.append("max_price", parameters.max_price.toString());
}
try {
const response = await fetch("/api/listing_geojson?" + queryString,
{
method: 'GET',
headers: {
'Authorization': `Bearer ${accessToken}`, // Pass the token
'Content-Type': 'application/json',
},
}
);
if (!response.ok) throw new Error('Error: ' + response.json());
const data: Response = await response.json();
return data;
} catch (err) {
setError('Failed to fetch data: ' + err);
alert(JSON.stringify(err))
} finally {
}
};
const onSubmit = async (parameters: ParameterValues) => {
// Fetch listing data
setQueryParameters(parameters)
const data = await fetchData(parameters);
console.log(data)
if (data) {
setListingData(data);
}
setIsParametersModalOpen(false)
}
if (!user) {
return <LoginModal isOpen={user === null} />
}
return (
<>
<SidebarProvider defaultOpen={false}>
<AppSidebar />
<SidebarInset>
<header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
<SidebarTrigger className="-ml-1" />
<Separator
orientation="vertical"
className="mr-2 data-[orientation=vertical]:h-4"
/>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem className="hidden md:block">
<BreadcrumbLink href="#">
Building Your Application
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator className="hidden md:block" />
<BreadcrumbItem>
<BreadcrumbPage>Data Fetching</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</header>
<div className="flex flex-col h-screen w-full">
<div className="flex gap-2 p-2 bg-gray-100">
<h1>Welcome, {user.profile.name}!</h1>
<Button onClick={logout}>Logout</Button>
<Parameters onSubmit={onSubmit} isOpen={isParametersModalOpen} />
</div>
{Object.keys(listingData).length > 0 &&
<div className="flex-1 w-full relative" style={{ minHeight: 0, marginBottom: '8rem' }}>
<Map listingData={listingData} queryParameters={queryParameters} />
</div>
}
</div>
</SidebarInset>
</SidebarProvider>
</>
)
}
export default App