131 lines
4.5 KiB
TypeScript
131 lines
4.5 KiB
TypeScript
|
|
import React, { useEffect, useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import {
|
|
Breadcrumb,
|
|
BreadcrumbItem,
|
|
BreadcrumbLink,
|
|
BreadcrumbList,
|
|
BreadcrumbPage,
|
|
BreadcrumbSeparator,
|
|
} from '@/components/ui/breadcrumb';
|
|
import { Button } from '@/components/ui/button';
|
|
import { toast } from '@/hooks/use-toast';
|
|
import { StartESILogin, ESILoggedIn, ListCharacters, ToggleCharacterWaypointEnabled } from 'wailsjs/go/main/App';
|
|
import { main } from 'wailsjs/go/models';
|
|
|
|
interface HeaderProps {
|
|
title: string;
|
|
breadcrumbs?: Array<{
|
|
label: string;
|
|
path?: string;
|
|
}>;
|
|
}
|
|
|
|
export const Header = ({ title, breadcrumbs = [] }: HeaderProps) => {
|
|
const navigate = useNavigate();
|
|
const [chars, setChars] = useState<main.CharacterInfo[]>([]);
|
|
|
|
const refreshState = async () => {
|
|
try {
|
|
const list = await ListCharacters();
|
|
setChars(list);
|
|
} catch { }
|
|
};
|
|
|
|
useEffect(() => {
|
|
refreshState();
|
|
}, []);
|
|
|
|
const handleLogin = async () => {
|
|
try {
|
|
await StartESILogin();
|
|
toast({ title: 'EVE Login', description: 'Complete login in your browser.' });
|
|
for (let i = 0; i < 20; i++) {
|
|
const ok = await ESILoggedIn();
|
|
if (ok) {
|
|
await refreshState();
|
|
break;
|
|
}
|
|
await new Promise(r => setTimeout(r, 500));
|
|
}
|
|
} catch (e: any) {
|
|
toast({ title: 'Login failed', description: String(e), variant: 'destructive' });
|
|
}
|
|
};
|
|
|
|
const handleCharacterClick = async (character: main.CharacterInfo) => {
|
|
try {
|
|
await ToggleCharacterWaypointEnabled(character.character_id);
|
|
await refreshState();
|
|
const newStatus = character.waypoint_enabled ? 'disabled' : 'enabled';
|
|
toast({ title: 'Waypoint Status', description: `${character.character_name} waypoints ${newStatus}` });
|
|
} catch (e: any) {
|
|
toast({ title: 'Toggle failed', description: String(e), variant: 'destructive' });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex-shrink-0 py-4 px-4 border-b border-purple-500/20">
|
|
{breadcrumbs.length > 0 && (
|
|
<div className="mb-3">
|
|
<Breadcrumb>
|
|
<BreadcrumbList>
|
|
{breadcrumbs.map((crumb, index) => (
|
|
<React.Fragment key={index}>
|
|
{index > 0 && <BreadcrumbSeparator className="text-slate-400" />}
|
|
<BreadcrumbItem>
|
|
{crumb.path ? (
|
|
<BreadcrumbLink
|
|
onClick={() => navigate(crumb.path!)}
|
|
className="text-purple-200 hover:text-white cursor-pointer"
|
|
>
|
|
{crumb.label}
|
|
</BreadcrumbLink>
|
|
) : (
|
|
<BreadcrumbPage className="text-white font-semibold">
|
|
{crumb.label}
|
|
</BreadcrumbPage>
|
|
)}
|
|
</BreadcrumbItem>
|
|
</React.Fragment>
|
|
))}
|
|
</BreadcrumbList>
|
|
</Breadcrumb>
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex items-center justify-between">
|
|
<h1 className="text-2xl font-bold text-white">{title}</h1>
|
|
<div className="flex items-center gap-3">
|
|
<Button size="sm" variant="outline" className="border-purple-500/40 text-purple-200" onClick={() => navigate('/settings/signature-rules')}>Rules</Button>
|
|
{chars.length > 0 && (
|
|
<div
|
|
className="grid gap-1 flex-1 justify-end"
|
|
style={{
|
|
gridTemplateColumns: `repeat(${Math.ceil(chars.length / 2)}, 1fr)`,
|
|
gridTemplateRows: 'repeat(2, auto)'
|
|
}}
|
|
>
|
|
{chars.map((c) => (
|
|
<span
|
|
key={c.character_id}
|
|
onClick={() => handleCharacterClick(c)}
|
|
className={`px-3 py-1 text-xs cursor-pointer transition-colors text-center overflow-hidden text-ellipsis ${c.waypoint_enabled
|
|
? 'bg-purple-500/20 text-purple-200 border border-purple-400/40 hover:bg-purple-500/30'
|
|
: 'bg-gray-500/20 text-gray-400 border border-gray-400/40 hover:bg-gray-500/30'
|
|
}`}
|
|
title={`Click to ${c.waypoint_enabled ? 'disable' : 'enable'} waypoints for ${c.character_name}`}
|
|
>
|
|
{c.character_name}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
<Button size="sm" className="bg-purple-600 hover:bg-purple-700" onClick={handleLogin}>Log in</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|