Initial commit: Helpdesk application setup

- Backend: Node.js/TypeScript with Prisma ORM
- Frontend: Vite + TypeScript
- Project configuration and documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 08:53:22 +01:00
commit e4f63a135e
103 changed files with 19913 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
import { Link } from 'react-router-dom';
import { LogOut, User, Settings } from 'lucide-react';
import { useAuthStore } from '@/store/authStore';
import { Button } from '@/components/ui';
export function Header() {
const { user, logout } = useAuthStore();
const handleLogout = async () => {
await logout();
};
return (
<header className="sticky top-0 z-40 border-b bg-background">
<div className="flex h-14 items-center justify-between px-4">
<Link to="/" className="flex items-center gap-2 font-semibold">
<span className="text-lg">Helpdesk</span>
</Link>
<div className="flex items-center gap-4">
{user && (
<>
<div className="flex items-center gap-2 text-sm">
<User className="h-4 w-4" />
<span>{user.name}</span>
<span className="text-muted-foreground">({user.role.name})</span>
</div>
{user.role.code === 'ROOT' && (
<Link to="/settings">
<Button variant="ghost" size="sm">
<Settings className="h-4 w-4" />
</Button>
</Link>
)}
<Button variant="ghost" size="sm" onClick={handleLogout}>
<LogOut className="h-4 w-4" />
</Button>
</>
)}
</div>
</div>
</header>
);
}

View File

@@ -0,0 +1,15 @@
import { Outlet } from 'react-router-dom';
import { Header } from './Header';
import { Sidebar } from './Sidebar';
export function MainLayout() {
return (
<div className="min-h-screen bg-background">
<Header />
<Sidebar />
<main className="ml-56 p-6">
<Outlet />
</main>
</div>
);
}

View File

@@ -0,0 +1,46 @@
import { NavLink } from 'react-router-dom';
import {
LayoutDashboard,
FolderKanban,
CheckSquare,
Users,
Wrench,
RotateCcw,
} from 'lucide-react';
import { cn } from '@/lib/utils';
const navItems = [
{ to: '/', icon: LayoutDashboard, label: 'Dashboard' },
{ to: '/projects', icon: FolderKanban, label: 'Projekty' },
{ to: '/tasks', icon: CheckSquare, label: 'Úlohy' },
{ to: '/customers', icon: Users, label: 'Zákazníci' },
{ to: '/equipment', icon: Wrench, label: 'Zariadenia' },
{ to: '/rma', icon: RotateCcw, label: 'RMA' },
];
export function Sidebar() {
return (
<aside className="fixed left-0 top-14 z-30 h-[calc(100vh-3.5rem)] w-56 border-r bg-background">
<nav className="flex flex-col gap-1 p-4">
{navItems.map((item) => (
<NavLink
key={item.to}
to={item.to}
end={item.to === '/'}
className={({ isActive }) =>
cn(
'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors',
isActive
? 'bg-primary text-primary-foreground'
: 'text-muted-foreground hover:bg-accent hover:text-accent-foreground'
)
}
>
<item.icon className="h-4 w-4" />
{item.label}
</NavLink>
))}
</nav>
</aside>
);
}

View File

@@ -0,0 +1,3 @@
export { Header } from './Header';
export { Sidebar } from './Sidebar';
export { MainLayout } from './MainLayout';