@lucifer91299/create-portal-app 1.0.6 → 1.0.8
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.
- package/README.md +9 -0
- package/dist/cli/index.js +92 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -216,6 +216,15 @@ See the full component and theming documentation at:
|
|
|
216
216
|
|
|
217
217
|
## Changelog
|
|
218
218
|
|
|
219
|
+
### v1.0.7
|
|
220
|
+
- Removed `PageFooter` from generated dashboard layout — no double footer
|
|
221
|
+
- Template generates cleaner layout; `PageFooter` can be added manually where needed
|
|
222
|
+
|
|
223
|
+
### v1.0.6
|
|
224
|
+
- Generated project now includes Users and Settings pages
|
|
225
|
+
- Fixed Windows folder creation bug (`path.dirname` instead of `lastIndexOf('/')`)
|
|
226
|
+
- CLI help text corrected to `npx @lucifer91299/create-portal-app`
|
|
227
|
+
|
|
219
228
|
### v1.0.3
|
|
220
229
|
- Added `workflow_dispatch` to GitHub Actions — manual publish trigger from Actions tab
|
|
221
230
|
- README improvements: badges, changelog
|
package/dist/cli/index.js
CHANGED
|
@@ -37,11 +37,12 @@ function closePrompt() {
|
|
|
37
37
|
// src/templates/index.ts
|
|
38
38
|
function genPackageJson(o) {
|
|
39
39
|
const deps = {
|
|
40
|
-
"@lucifer91299/ui": o.localUiPath ? `file:${o.localUiPath}` : "^1.0.
|
|
40
|
+
"@lucifer91299/ui": o.localUiPath ? `file:${o.localUiPath}` : "^1.0.7",
|
|
41
41
|
"next": "^15.3.0",
|
|
42
42
|
"react": "^19.0.0",
|
|
43
43
|
"react-dom": "^19.0.0",
|
|
44
44
|
"framer-motion": "^12.0.0",
|
|
45
|
+
"recharts": "^3.8.1",
|
|
45
46
|
"axios": "^1.7.9",
|
|
46
47
|
"@tanstack/react-query": "^5.64.1",
|
|
47
48
|
"jose": "^5.9.6",
|
|
@@ -424,7 +425,7 @@ export const navGroups: NavGroup[] = [
|
|
|
424
425
|
function genDashboardLayout(o) {
|
|
425
426
|
return `'use client'
|
|
426
427
|
|
|
427
|
-
import { DashboardLayout,
|
|
428
|
+
import { DashboardLayout, use${o.authMode === "multi-role" ? "MultiRoleAuth" : "JwtAuth"} } from '@lucifer91299/ui'
|
|
428
429
|
import { usePathname } from 'next/navigation'
|
|
429
430
|
import { navGroups } from '@/components/layout/nav-config'
|
|
430
431
|
|
|
@@ -450,15 +451,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
|
|
450
451
|
pathname={pathname}
|
|
451
452
|
onLogout={logout}
|
|
452
453
|
>
|
|
453
|
-
|
|
454
|
-
<div className="flex-1">{children}</div>
|
|
455
|
-
<PageFooter
|
|
456
|
-
organizationName="${o.projectName}"
|
|
457
|
-
logoSrc="/brand/logo.svg"
|
|
458
|
-
poweredByText="Powered by"
|
|
459
|
-
poweredByHref="#"
|
|
460
|
-
/>
|
|
461
|
-
</div>
|
|
454
|
+
{children}
|
|
462
455
|
</DashboardLayout>
|
|
463
456
|
)
|
|
464
457
|
}
|
|
@@ -525,14 +518,33 @@ export default function Home() {
|
|
|
525
518
|
function genDashboardHomePage(o) {
|
|
526
519
|
return `'use client'
|
|
527
520
|
|
|
528
|
-
import {
|
|
521
|
+
import { useState } from 'react'
|
|
522
|
+
import { PageShell, DataTable, StatusBadge, useJwtAuth, PortalBarChart, PortalAreaChart, PortalDonutChart, DatePicker } from '@lucifer91299/ui'
|
|
529
523
|
import { TrendingUp, Users, ShoppingCart, Activity } from 'lucide-react'
|
|
530
524
|
|
|
531
525
|
const stats = [
|
|
532
|
-
{ label: 'Total Users', value: '2,847', change: '+12%', icon: Users,
|
|
533
|
-
{ label: 'Revenue', value: '\u20B948,295', change: '+8.2%', icon: TrendingUp,
|
|
534
|
-
{ label: 'Orders', value: '1,429', change: '+5.1%', icon: ShoppingCart,
|
|
535
|
-
{ label: 'Active Now', value: '94', change: '+3', icon: Activity,
|
|
526
|
+
{ label: 'Total Users', value: '2,847', change: '+12%', icon: Users, bg: 'bg-blue-50', fg: 'text-blue-600' },
|
|
527
|
+
{ label: 'Revenue', value: '\u20B948,295', change: '+8.2%', icon: TrendingUp, bg: 'bg-green-50', fg: 'text-green-600' },
|
|
528
|
+
{ label: 'Orders', value: '1,429', change: '+5.1%', icon: ShoppingCart, bg: 'bg-orange-50', fg: 'text-orange-600' },
|
|
529
|
+
{ label: 'Active Now', value: '94', change: '+3', icon: Activity, bg: 'bg-purple-50', fg: 'text-purple-600' },
|
|
530
|
+
]
|
|
531
|
+
|
|
532
|
+
const MONTHLY = [
|
|
533
|
+
{ month: 'Jan', orders: 38, members: 120, revenue: 48 },
|
|
534
|
+
{ month: 'Feb', orders: 52, members: 134, revenue: 62 },
|
|
535
|
+
{ month: 'Mar', orders: 47, members: 128, revenue: 55 },
|
|
536
|
+
{ month: 'Apr', orders: 65, members: 156, revenue: 78 },
|
|
537
|
+
{ month: 'May', orders: 71, members: 172, revenue: 85 },
|
|
538
|
+
{ month: 'Jun', orders: 60, members: 160, revenue: 72 },
|
|
539
|
+
{ month: 'Jul', orders: 84, members: 198, revenue: 96 },
|
|
540
|
+
{ month: 'Aug', orders: 79, members: 185, revenue: 92 },
|
|
541
|
+
]
|
|
542
|
+
|
|
543
|
+
const STATUS_DONUT = [
|
|
544
|
+
{ name: 'Completed', value: 384, color: '#138808' },
|
|
545
|
+
{ name: 'Approved', value: 213, color: '#000080' },
|
|
546
|
+
{ name: 'Pending', value: 97, color: '#FF9933' },
|
|
547
|
+
{ name: 'Rejected', value: 42, color: '#ef4444' },
|
|
536
548
|
]
|
|
537
549
|
|
|
538
550
|
const activity = [
|
|
@@ -545,40 +557,88 @@ const activity = [
|
|
|
545
557
|
|
|
546
558
|
export default function DashboardHome() {
|
|
547
559
|
const { user } = useJwtAuth()
|
|
560
|
+
const [fromDate, setFromDate] = useState('')
|
|
561
|
+
const [toDate, setToDate] = useState('')
|
|
548
562
|
|
|
549
563
|
return (
|
|
550
|
-
<div className="p-6 space-y-6">
|
|
551
|
-
<
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
564
|
+
<div className="p-4 sm:p-6 space-y-6 max-w-7xl mx-auto">
|
|
565
|
+
<div className="flex items-start justify-between gap-4 flex-wrap">
|
|
566
|
+
<div>
|
|
567
|
+
<h1 className="text-title1 text-label-primary font-semibold">
|
|
568
|
+
Welcome back, {String(user?.name ?? 'Admin')} \u{1F44B}
|
|
569
|
+
</h1>
|
|
570
|
+
<p className="text-body text-label-secondary mt-0.5">Here's what's happening today.</p>
|
|
571
|
+
</div>
|
|
572
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
573
|
+
<DatePicker value={fromDate} onChange={setFromDate} placeholder="From date" className="w-36" disableFuture />
|
|
574
|
+
<span className="text-label-tertiary">\u2013</span>
|
|
575
|
+
<DatePicker value={toDate} onChange={setToDate} placeholder="To date" className="w-36" disableFuture />
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
555
578
|
|
|
556
579
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
|
|
557
|
-
{stats.map(({ label, value, change, icon: Icon,
|
|
558
|
-
<div key={label} className="bg-white rounded-
|
|
580
|
+
{stats.map(({ label, value, change, icon: Icon, bg, fg }) => (
|
|
581
|
+
<div key={label} className="bg-white rounded-2xl p-5 shadow-sm border border-separator">
|
|
559
582
|
<div className="flex items-center justify-between mb-3">
|
|
560
583
|
<p className="text-subhead text-label-secondary">{label}</p>
|
|
561
|
-
<div className={\`w-
|
|
584
|
+
<div className={\`w-9 h-9 rounded-xl flex items-center justify-center \${bg} \${fg}\`}>
|
|
562
585
|
<Icon className="w-4 h-4" />
|
|
563
586
|
</div>
|
|
564
587
|
</div>
|
|
565
588
|
<p className="text-title1 font-bold text-label-primary">{value}</p>
|
|
566
|
-
<p className="text-footnote text-green-600 mt-
|
|
589
|
+
<p className="text-footnote text-green-600 mt-0.5 font-medium">{change} this month</p>
|
|
567
590
|
</div>
|
|
568
591
|
))}
|
|
569
592
|
</div>
|
|
570
593
|
|
|
571
|
-
<div className="
|
|
594
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
|
|
595
|
+
<div className="lg:col-span-2 bg-white rounded-2xl border border-separator shadow-sm p-5">
|
|
596
|
+
<p className="text-headline font-semibold text-label-primary mb-1">Orders & Members per Month</p>
|
|
597
|
+
<p className="text-footnote text-label-tertiary mb-4">Current year overview</p>
|
|
598
|
+
<PortalBarChart
|
|
599
|
+
data={MONTHLY}
|
|
600
|
+
xKey="month"
|
|
601
|
+
series={[
|
|
602
|
+
{ key: 'orders', name: 'Orders' },
|
|
603
|
+
{ key: 'members', name: 'Members' },
|
|
604
|
+
]}
|
|
605
|
+
height={220}
|
|
606
|
+
/>
|
|
607
|
+
</div>
|
|
608
|
+
<div className="bg-white rounded-2xl border border-separator shadow-sm p-5">
|
|
609
|
+
<p className="text-headline font-semibold text-label-primary mb-1">Order Status</p>
|
|
610
|
+
<p className="text-footnote text-label-tertiary mb-2">All time</p>
|
|
611
|
+
<PortalDonutChart
|
|
612
|
+
data={STATUS_DONUT}
|
|
613
|
+
height={230}
|
|
614
|
+
centerValue="764"
|
|
615
|
+
centerLabel="Orders"
|
|
616
|
+
/>
|
|
617
|
+
</div>
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
<div className="bg-white rounded-2xl border border-separator shadow-sm p-5">
|
|
621
|
+
<p className="text-headline font-semibold text-label-primary mb-1">Revenue Trend (\u20B9 thousands)</p>
|
|
622
|
+
<p className="text-footnote text-label-tertiary mb-4">Monthly revenue</p>
|
|
623
|
+
<PortalAreaChart
|
|
624
|
+
data={MONTHLY}
|
|
625
|
+
xKey="month"
|
|
626
|
+
series={[{ key: 'revenue', name: 'Revenue (\u20B9K)' }]}
|
|
627
|
+
height={200}
|
|
628
|
+
/>
|
|
629
|
+
</div>
|
|
630
|
+
|
|
631
|
+
<div className="bg-white rounded-2xl shadow-sm border border-separator overflow-hidden">
|
|
572
632
|
<div className="px-5 py-4 border-b border-separator">
|
|
573
633
|
<h2 className="text-callout font-semibold text-label-primary">Recent Activity</h2>
|
|
574
634
|
</div>
|
|
575
635
|
<DataTable
|
|
576
636
|
columns={[
|
|
577
|
-
{ key: 'id', header: 'ID',
|
|
578
|
-
{ key: 'user', header: 'User', render: (r) => <span className="font-medium text-label-primary">{r.user}</span>
|
|
579
|
-
{ key: 'action', header: 'Action', render: (r) => <span className="text-label-secondary">{r.action}</span>
|
|
580
|
-
{ key: 'time', header: 'Time', render: (r) => <span className="text-label-tertiary">{r.time}</span>
|
|
581
|
-
{ key: 'status', header: 'Status', render: (r) => <StatusBadge status={r.status} />
|
|
637
|
+
{ key: 'id', header: 'ID', render: (r) => <span className="font-mono text-xs text-label-tertiary">{r.id}</span> },
|
|
638
|
+
{ key: 'user', header: 'User', render: (r) => <span className="font-medium text-label-primary">{r.user}</span> },
|
|
639
|
+
{ key: 'action', header: 'Action', render: (r) => <span className="text-label-secondary">{r.action}</span> },
|
|
640
|
+
{ key: 'time', header: 'Time', render: (r) => <span className="text-label-tertiary">{r.time}</span> },
|
|
641
|
+
{ key: 'status', header: 'Status', render: (r) => <StatusBadge status={r.status} /> },
|
|
582
642
|
]}
|
|
583
643
|
data={activity}
|
|
584
644
|
keyExtractor={(r) => r.id}
|
|
@@ -733,7 +793,7 @@ export default function SettingsPage() {
|
|
|
733
793
|
actions={<Button variant="primary" onClick={handleSave}>Save changes</Button>}
|
|
734
794
|
/>
|
|
735
795
|
|
|
736
|
-
{saved && <AlertBanner variant="success"
|
|
796
|
+
{saved && <AlertBanner variant="success">Settings saved successfully.</AlertBanner>}
|
|
737
797
|
|
|
738
798
|
<Card className="p-6">
|
|
739
799
|
<h3 className="text-callout font-semibold text-label-primary mb-4">Appearance</h3>
|
package/package.json
CHANGED