@beknurakhmed/webforge-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +212 -0
  2. package/dist/index.js +386 -0
  3. package/package.json +63 -0
  4. package/templates/angular/angular.json +36 -0
  5. package/templates/angular/package.json +29 -0
  6. package/templates/angular/src/app/app.component.ts +27 -0
  7. package/templates/angular/src/index.html +11 -0
  8. package/templates/angular/src/main.ts +4 -0
  9. package/templates/angular/src/styles.css +24 -0
  10. package/templates/angular/tsconfig.json +27 -0
  11. package/templates/base/README.md +16 -0
  12. package/templates/base/_gitignore +11 -0
  13. package/templates/extras/eslint/config/eslint.config.js +18 -0
  14. package/templates/extras/eslint/deps.json +7 -0
  15. package/templates/extras/prettier/config/.prettierignore +6 -0
  16. package/templates/extras/prettier/config/.prettierrc +7 -0
  17. package/templates/extras/prettier/deps.json +5 -0
  18. package/templates/nextjs/next.config.ts +5 -0
  19. package/templates/nextjs/package.json +16 -0
  20. package/templates/nextjs/src/app/globals.css +36 -0
  21. package/templates/nextjs/src/app/layout.tsx +19 -0
  22. package/templates/nextjs/src/app/page.tsx +8 -0
  23. package/templates/nextjs/tsconfig.json +21 -0
  24. package/templates/nuxt/app.vue +3 -0
  25. package/templates/nuxt/assets/css/main.css +24 -0
  26. package/templates/nuxt/nuxt.config.ts +5 -0
  27. package/templates/nuxt/package.json +17 -0
  28. package/templates/nuxt/pages/index.vue +20 -0
  29. package/templates/nuxt/tsconfig.json +3 -0
  30. package/templates/overlays/blog/react/src/App.css +41 -0
  31. package/templates/overlays/blog/react/src/App.tsx +39 -0
  32. package/templates/overlays/blog/react/src/components/BlogFooter.tsx +7 -0
  33. package/templates/overlays/blog/react/src/components/BlogHeader.tsx +15 -0
  34. package/templates/overlays/blog/react/src/components/BlogSidebar.tsx +26 -0
  35. package/templates/overlays/blog/react/src/components/PostList.tsx +27 -0
  36. package/templates/overlays/crm/react/src/App.css +48 -0
  37. package/templates/overlays/crm/react/src/App.tsx +49 -0
  38. package/templates/overlays/crm/react/src/components/ContactsTable.tsx +40 -0
  39. package/templates/overlays/crm/react/src/components/Filters.tsx +22 -0
  40. package/templates/overlays/crm/react/src/components/Sidebar.tsx +25 -0
  41. package/templates/overlays/crm/react/src/components/StatsCards.tsx +26 -0
  42. package/templates/overlays/dashboard/react/src/App.css +64 -0
  43. package/templates/overlays/dashboard/react/src/App.tsx +30 -0
  44. package/templates/overlays/dashboard/react/src/components/ChartPlaceholder.tsx +18 -0
  45. package/templates/overlays/dashboard/react/src/components/DataTable.tsx +44 -0
  46. package/templates/overlays/dashboard/react/src/components/KPICards.tsx +22 -0
  47. package/templates/overlays/dashboard/react/src/components/Sidebar.tsx +24 -0
  48. package/templates/overlays/ecommerce/react/src/App.css +82 -0
  49. package/templates/overlays/ecommerce/react/src/App.tsx +68 -0
  50. package/templates/overlays/ecommerce/react/src/components/Cart.tsx +47 -0
  51. package/templates/overlays/ecommerce/react/src/components/Footer.tsx +29 -0
  52. package/templates/overlays/ecommerce/react/src/components/Header.tsx +26 -0
  53. package/templates/overlays/ecommerce/react/src/components/ProductGrid.tsx +32 -0
  54. package/templates/overlays/ecommerce/vue/src/App.vue +44 -0
  55. package/templates/overlays/ecommerce/vue/src/components/CartPanel.vue +46 -0
  56. package/templates/overlays/ecommerce/vue/src/components/ProductGrid.vue +40 -0
  57. package/templates/overlays/ecommerce/vue/src/components/StoreFooter.vue +17 -0
  58. package/templates/overlays/ecommerce/vue/src/components/StoreHeader.vue +33 -0
  59. package/templates/overlays/landing/angular/src/app/app.component.ts +21 -0
  60. package/templates/overlays/landing/angular/src/app/components/cta.component.ts +24 -0
  61. package/templates/overlays/landing/angular/src/app/components/features.component.ts +42 -0
  62. package/templates/overlays/landing/angular/src/app/components/footer.component.ts +45 -0
  63. package/templates/overlays/landing/angular/src/app/components/hero.component.ts +41 -0
  64. package/templates/overlays/landing/nextjs/src/app/components/CTA.tsx +12 -0
  65. package/templates/overlays/landing/nextjs/src/app/components/Features.tsx +26 -0
  66. package/templates/overlays/landing/nextjs/src/app/components/Footer.tsx +27 -0
  67. package/templates/overlays/landing/nextjs/src/app/components/Hero.tsx +22 -0
  68. package/templates/overlays/landing/nextjs/src/app/globals.css +49 -0
  69. package/templates/overlays/landing/nextjs/src/app/page.tsx +15 -0
  70. package/templates/overlays/landing/nuxt/components/LandingCta.vue +18 -0
  71. package/templates/overlays/landing/nuxt/components/LandingFeatures.vue +36 -0
  72. package/templates/overlays/landing/nuxt/components/LandingFooter.vue +29 -0
  73. package/templates/overlays/landing/nuxt/components/LandingHero.vue +35 -0
  74. package/templates/overlays/landing/nuxt/pages/index.vue +15 -0
  75. package/templates/overlays/landing/react/src/App.css +70 -0
  76. package/templates/overlays/landing/react/src/App.tsx +18 -0
  77. package/templates/overlays/landing/react/src/components/CTA.tsx +14 -0
  78. package/templates/overlays/landing/react/src/components/Features.tsx +50 -0
  79. package/templates/overlays/landing/react/src/components/Footer.tsx +34 -0
  80. package/templates/overlays/landing/react/src/components/Hero.tsx +22 -0
  81. package/templates/overlays/landing/vanilla/src/main.ts +68 -0
  82. package/templates/overlays/landing/vanilla/src/style.css +43 -0
  83. package/templates/overlays/landing/vue/src/App.vue +19 -0
  84. package/templates/overlays/landing/vue/src/components/AppFooter.vue +44 -0
  85. package/templates/overlays/landing/vue/src/components/CTA.vue +21 -0
  86. package/templates/overlays/landing/vue/src/components/Features.vue +36 -0
  87. package/templates/overlays/landing/vue/src/components/Hero.vue +35 -0
  88. package/templates/overlays/portfolio/react/src/App.css +81 -0
  89. package/templates/overlays/portfolio/react/src/App.tsx +20 -0
  90. package/templates/overlays/portfolio/react/src/components/ContactForm.tsx +29 -0
  91. package/templates/overlays/portfolio/react/src/components/HeroSection.tsx +24 -0
  92. package/templates/overlays/portfolio/react/src/components/PortfolioFooter.tsx +14 -0
  93. package/templates/overlays/portfolio/react/src/components/Projects.tsx +33 -0
  94. package/templates/overlays/portfolio/react/src/components/Skills.tsx +27 -0
  95. package/templates/react/index.html +13 -0
  96. package/templates/react/package.json +19 -0
  97. package/templates/react/public/vite.svg +1 -0
  98. package/templates/react/src/App.css +11 -0
  99. package/templates/react/src/App.tsx +12 -0
  100. package/templates/react/src/index.css +42 -0
  101. package/templates/react/src/main.tsx +10 -0
  102. package/templates/react/vite.config.ts +6 -0
  103. package/templates/state/mobx/deps.json +6 -0
  104. package/templates/state/mobx/react/src/store/AppStore.ts +15 -0
  105. package/templates/state/ngrx/angular/src/app/store/app.state.ts +22 -0
  106. package/templates/state/ngrx/deps.json +7 -0
  107. package/templates/state/pinia/deps.json +5 -0
  108. package/templates/state/pinia/vue/src/store/useAppStore.ts +15 -0
  109. package/templates/state/redux/deps.json +6 -0
  110. package/templates/state/redux/react/src/store/counterSlice.ts +20 -0
  111. package/templates/state/redux/react/src/store/index.ts +11 -0
  112. package/templates/state/rxjs/angular/src/app/services/app-state.service.ts +18 -0
  113. package/templates/state/rxjs/deps.json +3 -0
  114. package/templates/state/zustand/deps.json +5 -0
  115. package/templates/state/zustand/react/src/store/useStore.ts +15 -0
  116. package/templates/styling/angular-material/deps.json +6 -0
  117. package/templates/styling/ant-design/deps.json +5 -0
  118. package/templates/styling/chakra-ui/deps.json +5 -0
  119. package/templates/styling/css-modules/deps.json +3 -0
  120. package/templates/styling/material-ui/deps.json +7 -0
  121. package/templates/styling/scss/deps.json +5 -0
  122. package/templates/styling/styled-components/deps.json +5 -0
  123. package/templates/styling/tailwind/config/postcss.config.js +5 -0
  124. package/templates/styling/tailwind/config/tailwind.config.js +11 -0
  125. package/templates/styling/tailwind/deps.json +6 -0
  126. package/templates/vanilla/index.html +13 -0
  127. package/templates/vanilla/package.json +14 -0
  128. package/templates/vanilla/src/main.ts +9 -0
  129. package/templates/vanilla/src/style.css +36 -0
  130. package/templates/vanilla/vite.config.ts +3 -0
  131. package/templates/vue/index.html +13 -0
  132. package/templates/vue/package.json +18 -0
  133. package/templates/vue/src/App.vue +23 -0
  134. package/templates/vue/src/main.ts +5 -0
  135. package/templates/vue/src/style.css +39 -0
  136. package/templates/vue/vite.config.ts +6 -0
@@ -0,0 +1,49 @@
1
+ import { useState } from 'react';
2
+ import { Sidebar } from './components/Sidebar';
3
+ import { StatsCards } from './components/StatsCards';
4
+ import { ContactsTable } from './components/ContactsTable';
5
+ import { Filters } from './components/Filters';
6
+ import './App.css';
7
+
8
+ export interface Contact {
9
+ id: number;
10
+ name: string;
11
+ email: string;
12
+ company: string;
13
+ status: 'Lead' | 'Prospect' | 'Customer' | 'Churned';
14
+ value: string;
15
+ lastContact: string;
16
+ }
17
+
18
+ const initialContacts: Contact[] = [
19
+ { id: 1, name: 'Sarah Connor', email: 'sarah@acme.com', company: 'Acme Corp', status: 'Customer', value: '$12,400', lastContact: '2 hours ago' },
20
+ { id: 2, name: 'John Smith', email: 'john@globex.com', company: 'Globex Inc', status: 'Lead', value: '$8,200', lastContact: '1 day ago' },
21
+ { id: 3, name: 'Emma Wilson', email: 'emma@wayne.com', company: 'Wayne Enterprises', status: 'Prospect', value: '$34,000', lastContact: '3 days ago' },
22
+ { id: 4, name: 'Mike Chen', email: 'mike@stark.com', company: 'Stark Industries', status: 'Customer', value: '$22,500', lastContact: '5 hours ago' },
23
+ { id: 5, name: 'Lisa Park', email: 'lisa@initech.com', company: 'Initech', status: 'Churned', value: '$5,100', lastContact: '2 weeks ago' },
24
+ { id: 6, name: 'David Lee', email: 'david@umbrella.com', company: 'Umbrella Corp', status: 'Lead', value: '$15,800', lastContact: '4 hours ago' },
25
+ ];
26
+
27
+ function App() {
28
+ const [contacts] = useState<Contact[]>(initialContacts);
29
+ const [filter, setFilter] = useState<string>('all');
30
+
31
+ const filtered = filter === 'all' ? contacts : contacts.filter((c) => c.status.toLowerCase() === filter);
32
+
33
+ return (
34
+ <div className="crm">
35
+ <Sidebar />
36
+ <main className="crm-main">
37
+ <header className="crm-header">
38
+ <h1>Contacts</h1>
39
+ <button className="btn-primary">+ Add Contact</button>
40
+ </header>
41
+ <StatsCards contacts={contacts} />
42
+ <Filters activeFilter={filter} onFilterChange={setFilter} />
43
+ <ContactsTable contacts={filtered} />
44
+ </main>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ export default App;
@@ -0,0 +1,40 @@
1
+ import type { Contact } from '../App';
2
+
3
+ interface ContactsTableProps {
4
+ contacts: Contact[];
5
+ }
6
+
7
+ export function ContactsTable({ contacts }: ContactsTableProps) {
8
+ return (
9
+ <div className="table-card">
10
+ <table className="data-table">
11
+ <thead>
12
+ <tr>
13
+ <th>Name</th>
14
+ <th>Company</th>
15
+ <th>Email</th>
16
+ <th>Status</th>
17
+ <th>Deal Value</th>
18
+ <th>Last Contact</th>
19
+ </tr>
20
+ </thead>
21
+ <tbody>
22
+ {contacts.map((c) => (
23
+ <tr key={c.id}>
24
+ <td className="contact-name">{c.name}</td>
25
+ <td>{c.company}</td>
26
+ <td className="contact-email">{c.email}</td>
27
+ <td>
28
+ <span className={`status-badge status-${c.status.toLowerCase()}`}>
29
+ {c.status}
30
+ </span>
31
+ </td>
32
+ <td className="contact-value">{c.value}</td>
33
+ <td className="contact-time">{c.lastContact}</td>
34
+ </tr>
35
+ ))}
36
+ </tbody>
37
+ </table>
38
+ </div>
39
+ );
40
+ }
@@ -0,0 +1,22 @@
1
+ interface FiltersProps {
2
+ activeFilter: string;
3
+ onFilterChange: (filter: string) => void;
4
+ }
5
+
6
+ const filters = ['all', 'lead', 'prospect', 'customer', 'churned'];
7
+
8
+ export function Filters({ activeFilter, onFilterChange }: FiltersProps) {
9
+ return (
10
+ <div className="filters">
11
+ {filters.map((f) => (
12
+ <button
13
+ key={f}
14
+ className={`filter-btn ${activeFilter === f ? 'active' : ''}`}
15
+ onClick={() => onFilterChange(f)}
16
+ >
17
+ {f.charAt(0).toUpperCase() + f.slice(1)}
18
+ </button>
19
+ ))}
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,25 @@
1
+ const menuItems = [
2
+ { icon: '👥', label: 'Contacts', active: true },
3
+ { icon: '🏢', label: 'Companies', active: false },
4
+ { icon: '💰', label: 'Deals', active: false },
5
+ { icon: '📧', label: 'Emails', active: false },
6
+ { icon: '📅', label: 'Calendar', active: false },
7
+ { icon: '📊', label: 'Reports', active: false },
8
+ { icon: '⚙️', label: 'Settings', active: false },
9
+ ];
10
+
11
+ export function Sidebar() {
12
+ return (
13
+ <aside className="sidebar">
14
+ <div className="sidebar-logo">{{projectName}}</div>
15
+ <nav className="sidebar-nav">
16
+ {menuItems.map((item, i) => (
17
+ <a key={i} href="#" className={`sidebar-item ${item.active ? 'active' : ''}`}>
18
+ <span>{item.icon}</span>
19
+ {item.label}
20
+ </a>
21
+ ))}
22
+ </nav>
23
+ </aside>
24
+ );
25
+ }
@@ -0,0 +1,26 @@
1
+ import type { Contact } from '../App';
2
+
3
+ interface StatsCardsProps {
4
+ contacts: Contact[];
5
+ }
6
+
7
+ export function StatsCards({ contacts }: StatsCardsProps) {
8
+ const stats = [
9
+ { label: 'Total Contacts', value: contacts.length, color: '#4f46e5' },
10
+ { label: 'Leads', value: contacts.filter((c) => c.status === 'Lead').length, color: '#f59e0b' },
11
+ { label: 'Customers', value: contacts.filter((c) => c.status === 'Customer').length, color: '#10b981' },
12
+ { label: 'Churned', value: contacts.filter((c) => c.status === 'Churned').length, color: '#ef4444' },
13
+ ];
14
+
15
+ return (
16
+ <div className="stats-grid">
17
+ {stats.map((stat, i) => (
18
+ <div key={i} className="stat-card">
19
+ <div className="stat-indicator" style={{ background: stat.color }} />
20
+ <span className="stat-label">{stat.label}</span>
21
+ <div className="stat-value">{stat.value}</div>
22
+ </div>
23
+ ))}
24
+ </div>
25
+ );
26
+ }
@@ -0,0 +1,64 @@
1
+ .dashboard { display: flex; min-height: 100vh; }
2
+
3
+ /* Sidebar */
4
+ .sidebar { width: 250px; background: #111827; color: white; padding: 1.5rem; flex-shrink: 0; }
5
+ .sidebar-logo { font-size: 1.25rem; font-weight: 700; padding: 0.5rem 0.75rem; margin-bottom: 2rem; color: #4f46e5; }
6
+ .sidebar-nav { display: flex; flex-direction: column; gap: 0.25rem; }
7
+ .sidebar-item { display: flex; align-items: center; gap: 0.75rem; padding: 0.75rem; border-radius: 8px; color: #9ca3af; text-decoration: none; transition: all 0.2s; }
8
+ .sidebar-item:hover { background: #1f2937; color: white; }
9
+ .sidebar-item.active { background: #4f46e5; color: white; }
10
+ .sidebar-icon { font-size: 1.1rem; }
11
+
12
+ /* Main */
13
+ .dashboard-main { flex: 1; background: #f9fafb; padding: 2rem; overflow-y: auto; }
14
+ .dashboard-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem; }
15
+ .dashboard-header h1 { font-size: 1.75rem; font-weight: 700; color: #111827; margin: 0; }
16
+ .header-actions { display: flex; align-items: center; gap: 1rem; }
17
+ .search-input { padding: 0.5rem 1rem; border: 1px solid #d1d5db; border-radius: 8px; font-size: 0.9rem; }
18
+ .user-avatar { width: 36px; height: 36px; background: #4f46e5; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 600; }
19
+
20
+ /* KPI Cards */
21
+ .kpi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; }
22
+ .kpi-card { background: white; border-radius: 12px; padding: 1.5rem; border: 1px solid #e5e7eb; }
23
+ .kpi-label { font-size: 0.85rem; color: #6b7280; font-weight: 500; }
24
+ .kpi-value { font-size: 2rem; font-weight: 700; margin: 0.25rem 0; color: #111827; }
25
+ .kpi-change { font-size: 0.8rem; }
26
+ .kpi-change.positive { color: #10b981; }
27
+ .kpi-change.negative { color: #ef4444; }
28
+
29
+ /* Charts */
30
+ .dashboard-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 1.5rem; margin-bottom: 2rem; }
31
+ .chart-card { background: white; border-radius: 12px; padding: 1.5rem; border: 1px solid #e5e7eb; }
32
+ .chart-card h3 { font-size: 1.1rem; font-weight: 600; margin-bottom: 1rem; color: #111827; }
33
+ .chart-placeholder { height: 200px; display: flex; align-items: flex-end; }
34
+ .chart-bars { display: flex; gap: 8px; align-items: flex-end; height: 100%; width: 100%; }
35
+ .chart-bar { flex: 1; background: linear-gradient(to top, #4f46e5, #818cf8); border-radius: 4px 4px 0 0; transition: height 0.3s; min-width: 12px; }
36
+
37
+ /* Table */
38
+ .table-card { background: white; border-radius: 12px; border: 1px solid #e5e7eb; overflow: hidden; }
39
+ .table-header { display: flex; justify-content: space-between; align-items: center; padding: 1.25rem 1.5rem; }
40
+ .table-header h3 { margin: 0; font-size: 1.1rem; color: #111827; }
41
+ .table-btn { background: none; border: 1px solid #d1d5db; padding: 0.4rem 1rem; border-radius: 6px; cursor: pointer; font-size: 0.85rem; color: #374151; }
42
+ .data-table { width: 100%; border-collapse: collapse; }
43
+ .data-table th { text-align: left; padding: 0.75rem 1.5rem; font-size: 0.8rem; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em; border-top: 1px solid #e5e7eb; background: #f9fafb; }
44
+ .data-table td { padding: 0.75rem 1.5rem; border-top: 1px solid #f3f4f6; font-size: 0.9rem; color: #374151; }
45
+ .status-badge { padding: 0.25rem 0.75rem; border-radius: 9999px; font-size: 0.75rem; font-weight: 500; }
46
+ .status-completed { background: #d1fae5; color: #065f46; }
47
+ .status-processing { background: #dbeafe; color: #1e40af; }
48
+ .status-cancelled { background: #fee2e2; color: #991b1b; }
49
+
50
+ @media (max-width: 768px) {
51
+ .dashboard { flex-direction: column; }
52
+ .sidebar { width: 100%; }
53
+ .dashboard-grid { grid-template-columns: 1fr; }
54
+ }
55
+
56
+ @media (prefers-color-scheme: dark) {
57
+ .dashboard-main { background: #0f172a; }
58
+ .dashboard-header h1 { color: white; }
59
+ .kpi-card, .chart-card, .table-card { background: #1e293b; border-color: #334155; }
60
+ .kpi-value, .chart-card h3, .table-header h3 { color: white; }
61
+ .data-table th { background: #1e293b; border-color: #334155; color: #94a3b8; }
62
+ .data-table td { border-color: #334155; color: #cbd5e1; }
63
+ .search-input { background: #1e293b; border-color: #334155; color: white; }
64
+ }
@@ -0,0 +1,30 @@
1
+ import { Sidebar } from './components/Sidebar';
2
+ import { KPICards } from './components/KPICards';
3
+ import { DataTable } from './components/DataTable';
4
+ import { ChartPlaceholder } from './components/ChartPlaceholder';
5
+ import './App.css';
6
+
7
+ function App() {
8
+ return (
9
+ <div className="dashboard">
10
+ <Sidebar />
11
+ <main className="dashboard-main">
12
+ <header className="dashboard-header">
13
+ <h1>Dashboard</h1>
14
+ <div className="header-actions">
15
+ <input type="text" placeholder="Search..." className="search-input" />
16
+ <div className="user-avatar">B</div>
17
+ </div>
18
+ </header>
19
+ <KPICards />
20
+ <div className="dashboard-grid">
21
+ <ChartPlaceholder title="Revenue Overview" />
22
+ <ChartPlaceholder title="User Growth" />
23
+ </div>
24
+ <DataTable />
25
+ </main>
26
+ </div>
27
+ );
28
+ }
29
+
30
+ export default App;
@@ -0,0 +1,18 @@
1
+ interface ChartPlaceholderProps {
2
+ title: string;
3
+ }
4
+
5
+ export function ChartPlaceholder({ title }: ChartPlaceholderProps) {
6
+ return (
7
+ <div className="chart-card">
8
+ <h3>{title}</h3>
9
+ <div className="chart-placeholder">
10
+ <div className="chart-bars">
11
+ {[40, 65, 45, 80, 55, 70, 90, 60, 75, 50, 85, 95].map((h, i) => (
12
+ <div key={i} className="chart-bar" style={{ height: `${h}%` }} />
13
+ ))}
14
+ </div>
15
+ </div>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,44 @@
1
+ const rows = [
2
+ { id: '#3210', customer: 'Olivia Martin', email: 'olivia@email.com', amount: '$42.00', status: 'Completed' },
3
+ { id: '#3209', customer: 'Ava Johnson', email: 'ava@email.com', amount: '$74.99', status: 'Processing' },
4
+ { id: '#3208', customer: 'Michael Brown', email: 'michael@email.com', amount: '$64.00', status: 'Completed' },
5
+ { id: '#3207', customer: 'Lisa Anderson', email: 'lisa@email.com', amount: '$49.99', status: 'Cancelled' },
6
+ { id: '#3206', customer: 'Thomas Wilson', email: 'thomas@email.com', amount: '$120.00', status: 'Completed' },
7
+ ];
8
+
9
+ export function DataTable() {
10
+ return (
11
+ <div className="table-card">
12
+ <div className="table-header">
13
+ <h3>Recent Orders</h3>
14
+ <button className="table-btn">View All</button>
15
+ </div>
16
+ <table className="data-table">
17
+ <thead>
18
+ <tr>
19
+ <th>Order</th>
20
+ <th>Customer</th>
21
+ <th>Email</th>
22
+ <th>Amount</th>
23
+ <th>Status</th>
24
+ </tr>
25
+ </thead>
26
+ <tbody>
27
+ {rows.map((row, i) => (
28
+ <tr key={i}>
29
+ <td>{row.id}</td>
30
+ <td>{row.customer}</td>
31
+ <td>{row.email}</td>
32
+ <td>{row.amount}</td>
33
+ <td>
34
+ <span className={`status-badge status-${row.status.toLowerCase()}`}>
35
+ {row.status}
36
+ </span>
37
+ </td>
38
+ </tr>
39
+ ))}
40
+ </tbody>
41
+ </table>
42
+ </div>
43
+ );
44
+ }
@@ -0,0 +1,22 @@
1
+ const kpis = [
2
+ { label: 'Total Revenue', value: '$45,231', change: '+20.1%', positive: true },
3
+ { label: 'Active Users', value: '2,350', change: '+15.3%', positive: true },
4
+ { label: 'New Orders', value: '1,247', change: '-3.2%', positive: false },
5
+ { label: 'Conversion Rate', value: '3.24%', change: '+2.1%', positive: true },
6
+ ];
7
+
8
+ export function KPICards() {
9
+ return (
10
+ <div className="kpi-grid">
11
+ {kpis.map((kpi, i) => (
12
+ <div key={i} className="kpi-card">
13
+ <span className="kpi-label">{kpi.label}</span>
14
+ <div className="kpi-value">{kpi.value}</div>
15
+ <span className={`kpi-change ${kpi.positive ? 'positive' : 'negative'}`}>
16
+ {kpi.change} from last month
17
+ </span>
18
+ </div>
19
+ ))}
20
+ </div>
21
+ );
22
+ }
@@ -0,0 +1,24 @@
1
+ const menuItems = [
2
+ { icon: '📊', label: 'Dashboard', active: true },
3
+ { icon: '👥', label: 'Users', active: false },
4
+ { icon: '📦', label: 'Products', active: false },
5
+ { icon: '📋', label: 'Orders', active: false },
6
+ { icon: '📈', label: 'Analytics', active: false },
7
+ { icon: '⚙️', label: 'Settings', active: false },
8
+ ];
9
+
10
+ export function Sidebar() {
11
+ return (
12
+ <aside className="sidebar">
13
+ <div className="sidebar-logo">{{projectName}}</div>
14
+ <nav className="sidebar-nav">
15
+ {menuItems.map((item, i) => (
16
+ <a key={i} href="#" className={`sidebar-item ${item.active ? 'active' : ''}`}>
17
+ <span className="sidebar-icon">{item.icon}</span>
18
+ {item.label}
19
+ </a>
20
+ ))}
21
+ </nav>
22
+ </aside>
23
+ );
24
+ }
@@ -0,0 +1,82 @@
1
+ .ecommerce { min-height: 100vh; display: flex; flex-direction: column; }
2
+
3
+ /* Header */
4
+ .store-header { background: white; border-bottom: 1px solid #e5e7eb; position: sticky; top: 0; z-index: 10; }
5
+ .header-content { max-width: 1200px; margin: 0 auto; padding: 1rem 2rem; display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; }
6
+ .store-logo { font-size: 1.5rem; color: #4f46e5; margin: 0; }
7
+ .store-nav { display: flex; gap: 1.5rem; }
8
+ .store-nav a { text-decoration: none; color: #6b7280; font-weight: 500; transition: color 0.2s; }
9
+ .store-nav a:hover, .store-nav a.active { color: #4f46e5; }
10
+ .header-actions { display: flex; gap: 1rem; margin-left: auto; align-items: center; }
11
+ .search-input { padding: 0.5rem 1rem; border: 1px solid #d1d5db; border-radius: 8px; font-size: 0.9rem; width: 200px; }
12
+ .cart-btn { background: #4f46e5; color: white; border: none; padding: 0.5rem 1.25rem; border-radius: 8px; cursor: pointer; font-weight: 600; }
13
+
14
+ /* Main */
15
+ .main { flex: 1; max-width: 1200px; margin: 0 auto; padding: 2rem; width: 100%; }
16
+
17
+ /* Product Section */
18
+ .product-section h2 { font-size: 1.75rem; font-weight: 700; margin-bottom: 1.5rem; }
19
+ .product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1.5rem; }
20
+ .product-card { border: 1px solid #e5e7eb; border-radius: 12px; overflow: hidden; transition: all 0.2s; background: white; }
21
+ .product-card:hover { box-shadow: 0 8px 25px rgba(0,0,0,0.08); transform: translateY(-2px); }
22
+ .product-image { font-size: 4rem; text-align: center; padding: 2rem; background: #f9fafb; }
23
+ .product-info { padding: 1.25rem; }
24
+ .product-category { font-size: 0.75rem; color: #4f46e5; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
25
+ .product-info h3 { font-size: 1.1rem; margin: 0.25rem 0; }
26
+ .product-info p { color: #6b7280; font-size: 0.9rem; margin-bottom: 1rem; }
27
+ .product-footer { display: flex; justify-content: space-between; align-items: center; }
28
+ .product-price { font-size: 1.25rem; font-weight: 700; color: #111827; }
29
+ .add-to-cart { background: #4f46e5; color: white; border: none; padding: 0.5rem 1rem; border-radius: 6px; cursor: pointer; font-weight: 500; font-size: 0.85rem; }
30
+ .add-to-cart:hover { background: #4338ca; }
31
+
32
+ /* Cart */
33
+ .cart-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 50; }
34
+ .cart-panel { position: fixed; top: 0; right: 0; bottom: 0; width: 400px; max-width: 100%; background: white; box-shadow: -4px 0 25px rgba(0,0,0,0.1); display: flex; flex-direction: column; }
35
+ .cart-header { display: flex; justify-content: space-between; align-items: center; padding: 1.5rem; border-bottom: 1px solid #e5e7eb; }
36
+ .cart-header h2 { margin: 0; font-size: 1.25rem; }
37
+ .cart-close { background: none; border: none; font-size: 1.25rem; cursor: pointer; color: #6b7280; }
38
+ .cart-empty { text-align: center; padding: 3rem; color: #9ca3af; }
39
+ .cart-items { flex: 1; overflow-y: auto; padding: 1rem; }
40
+ .cart-item { display: flex; align-items: center; gap: 1rem; padding: 1rem 0; border-bottom: 1px solid #f3f4f6; }
41
+ .cart-item-image { font-size: 2rem; }
42
+ .cart-item-info h4 { margin: 0; font-size: 0.95rem; }
43
+ .cart-item-info p { color: #6b7280; font-size: 0.85rem; margin: 0; }
44
+ .cart-item-remove { background: none; border: none; color: #ef4444; cursor: pointer; font-size: 0.8rem; margin-left: auto; }
45
+ .cart-footer { padding: 1.5rem; border-top: 1px solid #e5e7eb; }
46
+ .cart-total { display: flex; justify-content: space-between; margin-bottom: 1rem; font-size: 1.1rem; }
47
+ .checkout-btn { width: 100%; background: #4f46e5; color: white; border: none; padding: 0.75rem; border-radius: 8px; font-size: 1rem; font-weight: 600; cursor: pointer; }
48
+ .checkout-btn:hover { background: #4338ca; }
49
+
50
+ /* Footer */
51
+ .store-footer { background: #111827; color: #d1d5db; padding: 3rem 2rem 1.5rem; margin-top: auto; }
52
+ .store-footer .footer-content { display: flex; justify-content: space-between; max-width: 1200px; margin: 0 auto; gap: 3rem; flex-wrap: wrap; }
53
+ .store-footer .footer-brand h3 { color: white; font-size: 1.25rem; margin-bottom: 0.5rem; }
54
+ .store-footer .footer-links { display: flex; gap: 3rem; }
55
+ .store-footer .footer-col { display: flex; flex-direction: column; gap: 0.5rem; }
56
+ .store-footer .footer-col h4 { color: white; font-size: 0.8rem; text-transform: uppercase; margin-bottom: 0.25rem; }
57
+ .store-footer .footer-col a { color: #9ca3af; text-decoration: none; font-size: 0.9rem; }
58
+ .store-footer .footer-col a:hover { color: white; }
59
+ .store-footer .footer-bottom { border-top: 1px solid #374151; margin-top: 2rem; padding-top: 1rem; text-align: center; max-width: 1200px; margin-left: auto; margin-right: auto; }
60
+ .store-footer .footer-bottom p { font-size: 0.8rem; color: #6b7280; }
61
+
62
+ @media (max-width: 768px) {
63
+ .header-content { flex-direction: column; align-items: flex-start; }
64
+ .header-actions { margin-left: 0; width: 100%; }
65
+ .search-input { flex: 1; }
66
+ .cart-panel { width: 100%; }
67
+ }
68
+
69
+ @media (prefers-color-scheme: dark) {
70
+ .store-header { background: #1f2937; border-color: #374151; }
71
+ .product-card { background: #1f2937; border-color: #374151; }
72
+ .product-image { background: #111827; }
73
+ .product-info h3 { color: white; }
74
+ .product-price { color: white; }
75
+ .product-section h2 { color: white; }
76
+ .search-input { background: #374151; border-color: #4b5563; color: white; }
77
+ .cart-panel { background: #1f2937; }
78
+ .cart-header { border-color: #374151; }
79
+ .cart-item { border-color: #374151; }
80
+ .cart-footer { border-color: #374151; }
81
+ .cart-item-info h4 { color: white; }
82
+ }
@@ -0,0 +1,68 @@
1
+ import { useState } from 'react';
2
+ import { Header } from './components/Header';
3
+ import { ProductGrid } from './components/ProductGrid';
4
+ import { Cart } from './components/Cart';
5
+ import { Footer } from './components/Footer';
6
+ import './App.css';
7
+
8
+ export interface Product {
9
+ id: number;
10
+ name: string;
11
+ price: number;
12
+ image: string;
13
+ category: string;
14
+ description: string;
15
+ }
16
+
17
+ export interface CartItem extends Product {
18
+ quantity: number;
19
+ }
20
+
21
+ const products: Product[] = [
22
+ { id: 1, name: 'Wireless Headphones', price: 79.99, image: '🎧', category: 'Electronics', description: 'Premium sound quality with noise cancellation.' },
23
+ { id: 2, name: 'Smart Watch', price: 199.99, image: '⌚', category: 'Electronics', description: 'Track your fitness and stay connected.' },
24
+ { id: 3, name: 'Laptop Stand', price: 49.99, image: '💻', category: 'Accessories', description: 'Ergonomic aluminum stand for better posture.' },
25
+ { id: 4, name: 'Mechanical Keyboard', price: 129.99, image: '⌨️', category: 'Electronics', description: 'Tactile switches with RGB backlighting.' },
26
+ { id: 5, name: 'USB-C Hub', price: 39.99, image: '🔌', category: 'Accessories', description: '7-in-1 hub with 4K HDMI output.' },
27
+ { id: 6, name: 'Webcam HD', price: 69.99, image: '📷', category: 'Electronics', description: '1080p webcam with built-in microphone.' },
28
+ { id: 7, name: 'Desk Lamp', price: 34.99, image: '💡', category: 'Home', description: 'LED desk lamp with adjustable brightness.' },
29
+ { id: 8, name: 'Mouse Pad XL', price: 19.99, image: '🖱️', category: 'Accessories', description: 'Extended mouse pad with stitched edges.' },
30
+ ];
31
+
32
+ function App() {
33
+ const [cartItems, setCartItems] = useState<CartItem[]>([]);
34
+ const [isCartOpen, setIsCartOpen] = useState(false);
35
+
36
+ const addToCart = (product: Product) => {
37
+ setCartItems((prev) => {
38
+ const existing = prev.find((item) => item.id === product.id);
39
+ if (existing) {
40
+ return prev.map((item) =>
41
+ item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
42
+ );
43
+ }
44
+ return [...prev, { ...product, quantity: 1 }];
45
+ });
46
+ };
47
+
48
+ const removeFromCart = (id: number) => {
49
+ setCartItems((prev) => prev.filter((item) => item.id !== id));
50
+ };
51
+
52
+ const cartCount = cartItems.reduce((sum, item) => sum + item.quantity, 0);
53
+
54
+ return (
55
+ <div className="ecommerce">
56
+ <Header cartCount={cartCount} onCartClick={() => setIsCartOpen(!isCartOpen)} />
57
+ <main className="main">
58
+ <ProductGrid products={products} onAddToCart={addToCart} />
59
+ </main>
60
+ {isCartOpen && (
61
+ <Cart items={cartItems} onRemove={removeFromCart} onClose={() => setIsCartOpen(false)} />
62
+ )}
63
+ <Footer />
64
+ </div>
65
+ );
66
+ }
67
+
68
+ export default App;
@@ -0,0 +1,47 @@
1
+ import type { CartItem } from '../App';
2
+
3
+ interface CartProps {
4
+ items: CartItem[];
5
+ onRemove: (id: number) => void;
6
+ onClose: () => void;
7
+ }
8
+
9
+ export function Cart({ items, onRemove, onClose }: CartProps) {
10
+ const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
11
+
12
+ return (
13
+ <div className="cart-overlay" onClick={onClose}>
14
+ <div className="cart-panel" onClick={(e) => e.stopPropagation()}>
15
+ <div className="cart-header">
16
+ <h2>Shopping Cart</h2>
17
+ <button className="cart-close" onClick={onClose}>X</button>
18
+ </div>
19
+ {items.length === 0 ? (
20
+ <p className="cart-empty">Your cart is empty</p>
21
+ ) : (
22
+ <>
23
+ <div className="cart-items">
24
+ {items.map((item) => (
25
+ <div key={item.id} className="cart-item">
26
+ <span className="cart-item-image">{item.image}</span>
27
+ <div className="cart-item-info">
28
+ <h4>{item.name}</h4>
29
+ <p>Qty: {item.quantity} x ${item.price.toFixed(2)}</p>
30
+ </div>
31
+ <button className="cart-item-remove" onClick={() => onRemove(item.id)}>Remove</button>
32
+ </div>
33
+ ))}
34
+ </div>
35
+ <div className="cart-footer">
36
+ <div className="cart-total">
37
+ <span>Total:</span>
38
+ <strong>${total.toFixed(2)}</strong>
39
+ </div>
40
+ <button className="checkout-btn">Checkout</button>
41
+ </div>
42
+ </>
43
+ )}
44
+ </div>
45
+ </div>
46
+ );
47
+ }
@@ -0,0 +1,29 @@
1
+ export function Footer() {
2
+ return (
3
+ <footer className="store-footer">
4
+ <div className="footer-content">
5
+ <div className="footer-brand">
6
+ <h3>{{projectName}}</h3>
7
+ <p>Your one-stop shop for quality products.</p>
8
+ </div>
9
+ <div className="footer-links">
10
+ <div className="footer-col">
11
+ <h4>Shop</h4>
12
+ <a href="#">All Products</a>
13
+ <a href="#">New Arrivals</a>
14
+ <a href="#">Sale</a>
15
+ </div>
16
+ <div className="footer-col">
17
+ <h4>Support</h4>
18
+ <a href="#">FAQ</a>
19
+ <a href="#">Shipping</a>
20
+ <a href="#">Returns</a>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ <div className="footer-bottom">
25
+ <p>&copy; 2025 {{projectName}}. All rights reserved.</p>
26
+ </div>
27
+ </footer>
28
+ );
29
+ }
@@ -0,0 +1,26 @@
1
+ interface HeaderProps {
2
+ cartCount: number;
3
+ onCartClick: () => void;
4
+ }
5
+
6
+ export function Header({ cartCount, onCartClick }: HeaderProps) {
7
+ return (
8
+ <header className="store-header">
9
+ <div className="header-content">
10
+ <h1 className="store-logo">{{projectName}}</h1>
11
+ <nav className="store-nav">
12
+ <a href="#" className="active">All Products</a>
13
+ <a href="#">Electronics</a>
14
+ <a href="#">Accessories</a>
15
+ <a href="#">Home</a>
16
+ </nav>
17
+ <div className="header-actions">
18
+ <input type="text" className="search-input" placeholder="Search products..." />
19
+ <button className="cart-btn" onClick={onCartClick}>
20
+ Cart ({cartCount})
21
+ </button>
22
+ </div>
23
+ </div>
24
+ </header>
25
+ );
26
+ }