Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 165 additions & 2 deletions bun.lock

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
install:
bun install
php artisan key:generate
php artisan migrate --seed

run-dev:
bun run dev

run-server:
php artisan serve
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@
"highlight.js": "^11.11.1",
"input-otp": "^1.4.2",
"laravel-vite-plugin": "^2.0",
"lucide-react": "^0.475.0",
"lucide-react": "^0.575.0",
"marked": "^17.0.3",
"marked-highlight": "^2.2.3",
"radix-ui": "^1.4.3",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"sileo": "^0.1.5",
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/app-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import HytaleModdingLogo from './hytale-modding-logo';

export default function AppFooter() {
return (
<footer className="mt-12 border-t bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<footer className="mt-12 border-t bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60">
<div className="container mx-auto max-w-7xl px-4 py-8">
<div className="grid grid-cols-1 gap-8 md:grid-cols-4">
<div className="col-span-1 md:col-span-2">
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/app-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export function AppHeader({ breadcrumbs = [] }: Props) {
<Button
variant="ghost"
size="icon"
className="mr-2 h-[34px] w-[34px]"
className="mr-2 h-8.5 w-8.5"
>
<Menu className="h-5 w-5" />
</Button>
Expand Down Expand Up @@ -172,7 +172,7 @@ export function AppHeader({ breadcrumbs = [] }: Props) {
size="icon"
className="group h-9 w-9 cursor-pointer"
>
<Search className="!size-5 opacity-80 group-hover:opacity-100" />
<Search className="size-5! opacity-80 group-hover:opacity-100" />
</Button>
<div className="ml-1 hidden gap-1 lg:flex">
{rightNavItems.map((item) => (
Expand Down
13 changes: 8 additions & 5 deletions resources/js/components/app-logo.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import AppLogoIcon from './app-logo-icon';
import HytaleModdingLogo from './hytale-modding-logo';

export default function AppLogo() {
return (
<>
<div className="flex aspect-square size-8 items-center justify-center rounded-md bg-sidebar-primary text-sidebar-primary-foreground">
<AppLogoIcon className="size-5 fill-current text-white dark:text-black" />
<div className="flex aspect-square size-8 items-center justify-center rounded-md text-sidebar-primary-foreground">
<HytaleModdingLogo
variant="icon"
className="size-5 fill-current text-white dark:text-black"
/>
</div>
<div className="ml-1 grid flex-1 text-left text-sm">
<span className="mb-0.5 truncate leading-tight font-semibold">
Laravel Starter Kit
<span className="mb-0.5 truncate text-xl leading-tight font-semibold">
Hytale Modding
</span>
</div>
</>
Expand Down
79 changes: 10 additions & 69 deletions resources/js/components/app-navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Link, usePage } from '@inertiajs/react';
import {
BookOpen,
FileText,
LayoutGrid,
Menu,
Plus,
Search,
Settings,
LogOut,
Expand Down Expand Up @@ -40,25 +38,17 @@ import { cn } from '@/lib/utils';
import { dashboard } from '@/routes';
import { index as modsIndex } from '@/routes/mods';
import type { SharedData } from '@/types';
import { mainNavItems } from '@/utils/navigation-items';
import HytaleModdingLogo from './hytale-modding-logo';

const mainNavItems = [
{
title: 'Dashboard',
href: dashboard().url,
icon: LayoutGrid,
},
];

export default function AppNavbar() {
const { isCurrentUrl } = useCurrentUrl();
const { auth } = usePage<SharedData>().props;
const getInitials = useInitials();
const [isSearchOpen, setIsSearchOpen] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

return (
<nav className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<nav className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-backdrop-filter:bg-background/60">
<div className="container mx-auto flex h-16 max-w-7xl items-center justify-between px-4">
{/* Logo */}
<div className="flex items-center space-x-4">
Expand All @@ -67,14 +57,14 @@ export default function AppNavbar() {
className="flex items-center space-x-2 transition-opacity hover:opacity-80"
>
<HytaleModdingLogo variant="icon" size="md" />
<span className="bg-clip-text text-xl font-bold text-transparent text-white">
<span className="bg-clip-text text-xl font-bold text-white">
HytaleModding
</span>
</Link>
</div>

{/* Desktop Navigation */}
<div className="hidden items-center space-x-6 md:flex">
<div className="hidden flex-1 items-center justify-end md:flex">
<NavigationMenu>
<NavigationMenuList className="flex space-x-1">
{mainNavItems.map((item, index) => (
Expand All @@ -89,7 +79,7 @@ export default function AppNavbar() {
: 'text-muted-foreground',
)}
>
<item.icon className="h-4 w-4" />
{item.icon && <item.icon className="h-4 w-4" />}
<span>{item.title}</span>
</Link>
</NavigationMenuItem>
Expand All @@ -98,33 +88,8 @@ export default function AppNavbar() {
</NavigationMenu>
</div>

{/* Search & Actions */}
<div className="flex items-center space-x-4">
{/* Search */}
<div className="relative hidden sm:flex">
<Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-muted-foreground" />
<Input
placeholder="Search documentation..."
className="w-64 border-0 bg-muted/50 pr-4 pl-10 focus:bg-background"
/>
</div>

<Button
variant="ghost"
size="icon"
className="sm:hidden"
onClick={() => setIsSearchOpen(!isSearchOpen)}
>
<Search className="h-4 w-4" />
</Button>

<Button asChild size="sm" className="hidden sm:flex">
<Link href="/mods/create">
<Plus className="h-4 w-4" />
New Mod
</Link>
</Button>

{/* Actions */}
<div className="ml-8 flex items-center space-x-4">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-9 w-9 rounded-full">
Expand All @@ -133,7 +98,7 @@ export default function AppNavbar() {
src={auth.user?.avatar ?? ''}
alt={auth.user?.name ?? ''}
/>
<AvatarFallback className="bg-gradient-to-br from-blue-500 to-purple-600 text-xs text-white">
<AvatarFallback className="bg-linear-to-br from-blue-500 to-purple-600 text-xs text-white">
{getInitials(auth.user?.name ?? '')}
</AvatarFallback>
</Avatar>
Expand All @@ -146,7 +111,7 @@ export default function AppNavbar() {
src={auth.user?.avatar ?? ''}
alt={auth.user?.name ?? ''}
/>
<AvatarFallback className="bg-gradient-to-br from-blue-500 to-purple-600 text-xs text-white">
<AvatarFallback className="bg-linear-to-br from-blue-500 to-purple-600 text-xs text-white">
{getInitials(auth.user?.name ?? '')}
</AvatarFallback>
</Avatar>
Expand Down Expand Up @@ -246,23 +211,13 @@ export default function AppNavbar() {
)}
onClick={() => setIsMobileMenuOpen(false)}
>
<item.icon className="h-5 w-5" />
{item.icon && <item.icon className="h-5 w-5" />}
<span>{item.title}</span>
</Link>
))}
</div>

<div className="border-t pt-6">
<Button asChild className="mb-4 w-full justify-start">
<Link
href="/mods/create"
onClick={() => setIsMobileMenuOpen(false)}
>
<Plus className="mr-2 h-4 w-4" />
Create New Mod
</Link>
</Button>

<div className="flex flex-col space-y-2">
<Button
asChild
Expand Down Expand Up @@ -301,20 +256,6 @@ export default function AppNavbar() {
</Sheet>
</div>
</div>

{/* Mobile Search Expanded */}
{isSearchOpen && (
<div className="border-t bg-background p-4 sm:hidden">
<div className="relative">
<Search className="absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2 transform text-muted-foreground" />
<Input
placeholder="Search documentation..."
className="pr-4 pl-10"
autoFocus
/>
</div>
</div>
)}
</nav>
);
}
11 changes: 2 additions & 9 deletions resources/js/components/app-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Link } from '@inertiajs/react';
import { BookOpen, Folder, LayoutGrid } from 'lucide-react';
import { BookOpen, Folder } from 'lucide-react';
import { NavFooter } from '@/components/nav-footer';
import { NavMain } from '@/components/nav-main';
import { NavUser } from '@/components/nav-user';
Expand All @@ -14,16 +14,9 @@ import {
} from '@/components/ui/sidebar';
import { dashboard } from '@/routes';
import type { NavItem } from '@/types';
import { mainNavItems } from '@/utils/navigation-items';
import AppLogo from './app-logo';

const mainNavItems: NavItem[] = [
{
title: 'Dashboard',
href: dashboard(),
icon: LayoutGrid,
},
];

const footerNavItems: NavItem[] = [
{
title: 'Repository',
Expand Down
70 changes: 70 additions & 0 deletions resources/js/components/dashboard/quick-action-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Link } from '@inertiajs/react';
import { type LucideIcon } from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card';
import { cn } from '@/lib/utils';

interface QuickActionButtonProps {
icon: LucideIcon;
label: string;
description: string;
href: string;
variant?: 'default' | 'primary' | 'success';
}

const variantStyles = {
default: {
card: 'hover:bg-accent hover:border-accent',
icon: 'bg-muted text-foreground group-hover:bg-accent',
},
primary: {
card: 'hover:bg-primary/10 hover:border-primary/50',
icon: 'bg-primary/10 text-primary group-hover:bg-primary/20 group-hover:scale-110',
},
success: {
card: 'hover:bg-green-500/10 hover:border-green-500/50',
icon: 'bg-green-500/10 text-green-600 dark:text-green-400 group-hover:bg-green-500/20 group-hover:scale-110',
},
};

export function QuickActionButton({
icon: Icon,
label,
description,
href,
variant = 'default',
}: QuickActionButtonProps) {
const styles = variantStyles[variant];

return (
<Link href={href}>
<Card
className={cn(
'group relative overflow-hidden border-border/50 transition-all duration-300 ease-in-out',
'cursor-pointer hover:scale-[1.02] hover:shadow-md',
styles.card,
)}
>
<CardContent className="p-4">
<div className="flex items-start gap-3">
<div
className={cn(
'rounded-lg p-2.5 transition-all duration-300',
styles.icon,
)}
>
<Icon className="h-5 w-5" />
</div>
<div className="min-w-0 flex-1">
<h4 className="text-sm font-semibold transition-colors group-hover:text-primary">
{label}
</h4>
<p className="mt-0.5 text-xs text-muted-foreground">
{description}
</p>
</div>
</div>
</CardContent>
</Card>
</Link>
);
}
Loading