Loading...
Loading...
Creates a main menu/navigation hub component with dynamically generated menu items based on selected capabilities (search, create, save, delete). Prompts for entity name and available actions, generates menu card and routes. Use when the user asks for Day 2 step 3 of the CRUD drill, or asks to build a main menu for up-app.
npx skill4agent add softinter-chiangrai/up-ai-skill-training d2-03-main-menuProductOrderEmployeesearchcreatesavedeletesearchcreatesavedeleteapp.routes.tsimport { Routes } from '@angular/router';
import { MenuComponent } from './pages/menu/menu.component';
import { <Entity>SearchComponent } from './pages/<entity>-search/<entity>-search.component';
import { <Entity>FormComponent } from './pages/<entity>-form/<entity>-form.component';
// Add more imports for additional entities as needed
export const routes: Routes = [
// Landing page (menu comes first!)
{ path: '', component: MenuComponent },
// <Entity> CRUD routes
{ path: '<entity>', component: <Entity>SearchComponent }, // Search/list page
{ path: '<entity>/new', component: <Entity>FormComponent }, // Create new record
{ path: '<entity>/:id/edit', component: <Entity>FormComponent }, // Edit existing record
// Add more entity routes here for additional programs:
// { path: 'customer', component: CustomerSearchComponent },
// { path: 'customer/new', component: CustomerFormComponent },
// { path: 'customer/:id/edit', component: CustomerFormComponent },
];{ path: '', component: MenuComponent }/<entity>router.navigate(['/<entity>/new'])router.navigate(['/<entity>', id, 'edit'])/<entity>/new/<entity>/:id/editimport { Component } from '@angular/core';
import { Router } from '@angular/router';
import { CommonModule } from '@angular/common';
interface MenuItem {
name: string;
icon: string;
path: string;
}
interface Program {
name: string;
entity: string;
icon: string;
description: string;
capabilities: string[];
menuItems: MenuItem[];
}
@Component({
selector: 'app-menu',
standalone: true,
imports: [CommonModule],
templateUrl: './menu.component.html',
styleUrls: ['./menu.component.css']
})
export class MenuComponent {
appTitle = 'CRUD Dashboard';
appSubtitle = 'Manage your data with ease';
programs: Program[] = [];
constructor(private router: Router) {
this.programs = [
{
name: '<Entity>',
entity: '<entity>',
icon: '📦',
description: 'Manage <entity> records',
capabilities: ['search', 'create', 'save', 'delete'],
menuItems: this.generateMenuItems('<entity>', ['search', 'create', 'save', 'delete'])
},
// Add more programs here:
// { name: 'Customer', entity: 'customer', icon: '👥', description: 'Manage customer data', capabilities: [...], menuItems: ... }
];
}
generateMenuItems(entity: string, capabilities: string[]): MenuItem[] {
const items: MenuItem[] = [];
if (capabilities.includes('search')) {
items.push({ name: 'Browse', icon: '📋', path: `/${entity}` });
}
if (capabilities.includes('create')) {
items.push({ name: 'Create', icon: '✚', path: `/${entity}/new` });
}
return items;
}
navigate(path: string) {
this.router.navigate([path]);
}
}<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 p-6">
<!-- Header -->
<div class="max-w-6xl mx-auto mb-12">
<div class="text-center mb-8">
<h1 class="text-5xl font-bold text-gray-900">{{ appTitle }}</h1>
<p class="text-gray-600 text-xl mt-4">{{ appSubtitle }}</p>
</div>
</div>
<!-- Program Cards Grid -->
<div class="max-w-6xl mx-auto">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
@for (program of programs; track program.entity) {
<div class="bg-white rounded-xl shadow-md hover:shadow-xl transition-shadow p-6">
<!-- Card Header -->
<div class="flex items-center mb-4">
<span class="text-5xl mr-4">{{ program.icon }}</span>
<div>
<h3 class="text-2xl font-bold text-gray-900">{{ program.name }}</h3>
<p class="text-gray-600 text-sm">{{ program.description }}</p>
</div>
</div>
<!-- Capabilities Badge -->
<div class="flex flex-wrap gap-2 mb-4">
@for (cap of program.capabilities; track cap) {
<span class="bg-gray-100 text-gray-700 text-xs font-semibold px-3 py-1 rounded-full">
{{ cap }}
</span>
}
</div>
<!-- Divider -->
<div class="border-b border-gray-200 my-4"></div>
<!-- Dynamic Menu Buttons -->
<div class="flex flex-col gap-4">
@for (item of program.menuItems; track item.name) {
<button
(click)="navigate(item.path)"
[class]="item.name === 'Browse' ? 'w-full text-white font-semibold px-6 py-3 rounded-lg transition bg-blue-500 hover:bg-blue-600' : 'w-full text-white font-semibold px-6 py-3 rounded-lg transition bg-green-500 hover:bg-green-600'"
>
{{ item.icon }} {{ item.name }}
</button>
}
</div>
@if (program.menuItems.length === 0) {
<p class="text-gray-600 text-sm text-center">No actions available for this program.</p>
}
</div>
}
</div>
</div>
<!-- Footer -->
<div class="max-w-6xl mx-auto mt-12 text-center">
<p class="text-gray-600 text-sm">Built with Angular + Tailwind CSS</p>
</div>
</div>