@ereactthohir/cli 1.3.0 ā 1.5.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.
- package/README.md +23 -142
- package/dist/commands/about.d.ts +2 -0
- package/dist/commands/about.d.ts.map +1 -0
- package/dist/commands/about.js +70 -0
- package/dist/commands/about.js.map +1 -0
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +1669 -570
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/generators.d.ts +30 -2
- package/dist/commands/generators.d.ts.map +1 -1
- package/dist/commands/generators.js +340 -274
- package/dist/commands/generators.js.map +1 -1
- package/dist/commands/key.d.ts +2 -0
- package/dist/commands/key.d.ts.map +1 -0
- package/dist/commands/key.js +57 -0
- package/dist/commands/key.js.map +1 -0
- package/dist/commands/route.d.ts +2 -0
- package/dist/commands/route.d.ts.map +1 -0
- package/dist/commands/route.js +111 -0
- package/dist/commands/route.js.map +1 -0
- package/dist/commands/routes.d.ts +2 -0
- package/dist/commands/routes.d.ts.map +1 -0
- package/dist/commands/routes.js +35 -0
- package/dist/commands/routes.js.map +1 -0
- package/dist/index.js +93 -6
- package/dist/index.js.map +1 -1
- package/package.json +45 -45
package/dist/commands/create.js
CHANGED
|
@@ -10,8 +10,17 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const ora_1 = __importDefault(require("ora"));
|
|
12
12
|
async function create(name) {
|
|
13
|
-
console.log(chalk_1.default.
|
|
14
|
-
|
|
13
|
+
console.log(chalk_1.default.red.bold(`
|
|
14
|
+
āāāāāāāāāāāāāāā āāāāāāāā āāāāāā āāāāāāāāāāāāāāāāāāāāāāāāāāāā āāā āāāāāāā āāā āāāāāāāāāāāāā
|
|
15
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā āāāāāāāāāāāāāāā āāāāāāāāāāāāāā
|
|
16
|
+
āāāāāā āāāāāāāāāāāāāā āāāāāāāāāāā āāā āāā āāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāā
|
|
17
|
+
āāāāāā āāāāāāāāāāāāāā āāāāāāāāāāā āāā āāā āāāāāāāāāāā āāāāāāāāāāāāāāāāāāāāāā
|
|
18
|
+
āāāāāāāāāāā āāāāāāāāāāāāāā āāāāāāāāāāā āāā āāā āāā āāāāāāāāāāāāāāā āāāāāāāāā āāā
|
|
19
|
+
āāāāāāāāāāā āāāāāāāāāāāāāā āāā āāāāāāā āāā āāā āāā āāā āāāāāāā āāā āāāāāāāāā āāā
|
|
20
|
+
`));
|
|
21
|
+
console.log(chalk_1.default.blue(`\n š [EN] Initializing EreactThohir Project: ${chalk_1.default.bold(name)}`));
|
|
22
|
+
console.log(chalk_1.default.blue(` [ID] Inisialisasi Proyek EreactThohir: ${chalk_1.default.bold(name)}`));
|
|
23
|
+
console.log(chalk_1.default.gray(` Powered by ${chalk_1.default.white.bold('Dhafa Nazula Permadi')} (KangPCode)\n`));
|
|
15
24
|
let answers;
|
|
16
25
|
if (process.env.CI) {
|
|
17
26
|
console.log(chalk_1.default.yellow(' Run in automated CI mode (Skipping prompts)'));
|
|
@@ -157,93 +166,9 @@ Route.get('/', (req, res) => {
|
|
|
157
166
|
return res.view('Welcome');
|
|
158
167
|
});
|
|
159
168
|
`);
|
|
160
|
-
// Write Welcome component
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
export default function Welcome() {
|
|
164
|
-
return (
|
|
165
|
-
<div className="rice-min-h-screen rice-bg-white rice-relative rice-overflow-hidden">
|
|
166
|
-
{/* Background Decorative Elements */}
|
|
167
|
-
<div className="rice-absolute rice-inset-0 rice-pointer-events-none">
|
|
168
|
-
<div className="rice-absolute rice-top-[-10%] rice-right-[-5%] rice-w-[500px] rice-h-[500px] rice-bg-primary-500 rice-opacity-5 rice-blur-3xl rice-rounded-full" />
|
|
169
|
-
<div className="rice-absolute rice-bottom-[-10%] rice-left-[-5%] rice-w-[600px] rice-h-[600px] rice-secondary-600 rice-opacity-5 rice-blur-3xl rice-rounded-full" />
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
{/* Navigation */}
|
|
173
|
-
<nav className="rice-relative rice-z-10 rice-flex rice-items-center rice-justify-between rice-px-8 rice-py-6 rice-max-w-7xl rice-mx-auto">
|
|
174
|
-
<div className="rice-flex rice-items-center rice-gap-2">
|
|
175
|
-
<div className="rice-w-10 rice-h-10 rice-bg-secondary-900 rice-rounded-xl rice-flex rice-items-center rice-justify-center rice-text-white rice-font-black">E</div>
|
|
176
|
-
<span className="rice-text-xl rice-font-black rice-tracking-tighter">EreactThohir</span>
|
|
177
|
-
</div>
|
|
178
|
-
<div className="rice-hidden rice-md-flex rice-items-center rice-gap-8 rice-text-sm rice-font-medium rice-text-secondary-600">
|
|
179
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Documentation</a>
|
|
180
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Showcase</a>
|
|
181
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Community</a>
|
|
182
|
-
<a href="/auth/login" className="rice-px-5 rice-py-2 rice-bg-secondary-900 rice-text-white rice-rounded-full rice-hover-scale-105 rice-transition-all">Get Started</a>
|
|
183
|
-
</div>
|
|
184
|
-
</nav>
|
|
185
|
-
|
|
186
|
-
<main className="rice-relative rice-z-10 rice-max-w-7xl rice-mx-auto rice-px-8 rice-pt-20 rice-pb-32">
|
|
187
|
-
<div className="rice-text-center rice-max-w-4xl rice-mx-auto">
|
|
188
|
-
<div className="rice-inline-flex rice-items-center rice-gap-2 rice-px-4 rice-py-2 rice-bg-secondary-100 rice-rounded-full rice-mb-8 rice-animate-pulse">
|
|
189
|
-
<span className="rice-w-2 rice-h-2 rice-bg-primary-500 rice-rounded-full" />
|
|
190
|
-
<span className="rice-text-xs rice-font-bold rice-text-secondary-600">Framework v1.3.0 "Powerful" is now available</span>
|
|
191
|
-
</div>
|
|
192
|
-
|
|
193
|
-
<h1 className="rice-text-6xl rice-md-text-8xl rice-font-black rice-tracking-tight rice-mb-8">
|
|
194
|
-
The Future of <span className="rice-gradient-primary rice-bg-clip-text rice-text-transparent">Modern Web</span> Development.
|
|
195
|
-
</h1>
|
|
196
|
-
|
|
197
|
-
<p className="rice-text-xl rice-md-text-2xl rice-text-secondary-600 rice-mb-12 rice-leading-relaxed">
|
|
198
|
-
Combine the elegance of Laravel's architecture with the power of React.
|
|
199
|
-
Build stunning, enterprise-ready applications faster than ever before.
|
|
200
|
-
</p>
|
|
201
|
-
|
|
202
|
-
<div className="rice-flex rice-flex-wrap rice-justify-center rice-gap-4">
|
|
203
|
-
<a href="/auth/register" className="rice-px-10 rice-py-5 rice-bg-secondary-900 rice-text-white rice-text-lg rice-font-bold rice-rounded-2xl rice-shadow-2xl rice-hover-scale-105 rice-transition-all rice-duration-300">
|
|
204
|
-
Create Your First App
|
|
205
|
-
</a>
|
|
206
|
-
<a href="#" className="rice-px-10 rice-py-5 rice-bg-white rice-border rice-text-secondary-900 rice-text-lg rice-font-bold rice-rounded-2xl rice-hover-bg-secondary-50 rice-transition-all rice-duration-300">
|
|
207
|
-
Read Documentation
|
|
208
|
-
</a>
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
211
|
-
|
|
212
|
-
{/* Feature Grid */}
|
|
213
|
-
<div className="rice-mt-32 rice-grid rice-grid-cols-1 rice-md-grid-cols-3 rice-gap-8">
|
|
214
|
-
<div className="rice-p-8 rice-bg-white rice-border rice-rounded-3xl rice-hover-shadow-xl rice-transition-all rice-duration-300">
|
|
215
|
-
<div className="rice-w-12 rice-h-12 rice-bg-primary-500 rice-bg-opacity-10 rice-rounded-2xl rice-flex rice-items-center rice-justify-center rice-mb-6 rice-text-primary-600 rice-text-xl">MVC</div>
|
|
216
|
-
<h3 className="rice-text-xl rice-font-bold rice-mb-3">Clean MVC Architecture</h3>
|
|
217
|
-
<p className="rice-text-secondary-600 rice-leading-relaxed">Full-featured routing, controllers, models, and middleware inspired by Laravel's elegance.</p>
|
|
218
|
-
</div>
|
|
219
|
-
<div className="rice-p-8 rice-bg-white rice-border rice-rounded-3xl rice-hover-shadow-xl rice-transition-all rice-duration-300">
|
|
220
|
-
<div className="rice-w-12 rice-h-12 rice-bg-success-600 rice-bg-opacity-10 rice-rounded-2xl rice-flex rice-items-center rice-justify-center rice-mb-6 rice-text-success-600 rice-text-xl">ā”</div>
|
|
221
|
-
<h3 className="rice-text-xl rice-font-bold rice-mb-3">Real-time Performance</h3>
|
|
222
|
-
<p className="rice-text-secondary-600 rice-leading-relaxed">Optimized SSR and hydration system ensures your app loads instantly and stays interactive.</p>
|
|
223
|
-
</div>
|
|
224
|
-
<div className="rice-p-8 rice-bg-white rice-border rice-rounded-3xl rice-hover-shadow-xl rice-transition-all rice-duration-300">
|
|
225
|
-
<div className="rice-w-12 rice-h-12 rice-bg-secondary-900 rice-bg-opacity-10 rice-rounded-2xl rice-flex rice-items-center rice-justify-center rice-mb-6 rice-text-secondary-900 rice-text-xl">šØ</div>
|
|
226
|
-
<h3 className="rice-text-xl rice-font-bold rice-mb-3">Rice UI System</h3>
|
|
227
|
-
<p className="rice-text-secondary-600 rice-leading-relaxed">Beautiful, accessible components built-in. No more fighting with CSS frameworks.</p>
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
</main>
|
|
231
|
-
|
|
232
|
-
{/* Footer */}
|
|
233
|
-
<footer className="rice-py-12 rice-border-t">
|
|
234
|
-
<div className="rice-max-w-7xl rice-mx-auto rice-px-8 rice-flex rice-flex-col rice-md-flex-row rice-items-center rice-justify-between rice-gap-6">
|
|
235
|
-
<p className="rice-text-secondary-500 rice-text-sm">Ā© 2024 EreactThohir. Built with passion for developers.</p>
|
|
236
|
-
<div className="rice-flex rice-gap-6 rice-text-secondary-400 rice-text-xl">
|
|
237
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">š</a>
|
|
238
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">GitHub</a>
|
|
239
|
-
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Discord</a>
|
|
240
|
-
</div>
|
|
241
|
-
</div>
|
|
242
|
-
</footer>
|
|
243
|
-
</div>
|
|
244
|
-
);
|
|
245
|
-
}
|
|
246
|
-
`);
|
|
169
|
+
// Write Welcome component with dynamic UI System
|
|
170
|
+
const welcomeContent = generateWelcomePage(answers.uiSystem, name);
|
|
171
|
+
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/views/Welcome.tsx'), welcomeContent);
|
|
247
172
|
// Write routes/api.ts
|
|
248
173
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/api.ts'), `import { Route } from '@ereactthohir/core';
|
|
249
174
|
|
|
@@ -273,12 +198,6 @@ Route.screen('Home', () => {
|
|
|
273
198
|
template: '${answers.template}'
|
|
274
199
|
};
|
|
275
200
|
`);
|
|
276
|
-
// Write ereact.json marker
|
|
277
|
-
await fs_extra_1.default.writeJSON(path_1.default.join(projectDir, 'ereact.json'), {
|
|
278
|
-
name: name,
|
|
279
|
-
version: '0.0.1',
|
|
280
|
-
created_at: new Date().toISOString()
|
|
281
|
-
}, { spaces: 2 });
|
|
282
201
|
// Write README.md with template info
|
|
283
202
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'README.md'), `# ${name}
|
|
284
203
|
|
|
@@ -317,6 +236,14 @@ DB_DRIVER=${answers.database.includes('sawit') ? 'sawit' : answers.database.toLo
|
|
|
317
236
|
"App\\Providers\\AuthServiceProvider"
|
|
318
237
|
]
|
|
319
238
|
}, { spaces: 2 });
|
|
239
|
+
// Write ereact.json for project metadata
|
|
240
|
+
await fs_extra_1.default.writeJSON(path_1.default.join(projectDir, 'ereact.json'), {
|
|
241
|
+
name,
|
|
242
|
+
template: answers.template,
|
|
243
|
+
uiSystem: answers.uiSystem,
|
|
244
|
+
installSemouth: answers.installSemouth,
|
|
245
|
+
createdAt: new Date().toISOString()
|
|
246
|
+
}, { spaces: 2 });
|
|
320
247
|
// Generate template structure based on selection
|
|
321
248
|
if (answers.template !== 'None (Blank)') {
|
|
322
249
|
spinner.text = `Generating ${answers.template} template...`;
|
|
@@ -344,7 +271,19 @@ DB_DRIVER=${answers.database.includes('sawit') ? 'sawit' : answers.database.toLo
|
|
|
344
271
|
if (answers.installSemouth) {
|
|
345
272
|
dependencies["@ereactthohir/semouth"] = "^1.3.0";
|
|
346
273
|
}
|
|
347
|
-
//
|
|
274
|
+
// Write Global CSS
|
|
275
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(projectDir, 'resources/css'));
|
|
276
|
+
let globalCSS = '';
|
|
277
|
+
if (answers.uiSystem === 'Rice UI (default, official)') {
|
|
278
|
+
globalCSS = await fs_extra_1.default.readFile(path_1.default.join(__dirname, '../../rice-ui/src/styles/rice.css'), 'utf-8');
|
|
279
|
+
}
|
|
280
|
+
else if (answers.uiSystem === 'JokoUI') {
|
|
281
|
+
globalCSS = await fs_extra_1.default.readFile(path_1.default.join(__dirname, '../../rice-ui/src/styles/joko.css'), 'utf-8');
|
|
282
|
+
}
|
|
283
|
+
if (globalCSS) {
|
|
284
|
+
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/css/app.css'), globalCSS);
|
|
285
|
+
}
|
|
286
|
+
// Configuration for non-default systems
|
|
348
287
|
if (answers.uiSystem !== 'Rice UI (default, official)') {
|
|
349
288
|
spinner.text = 'Configuring UI system...';
|
|
350
289
|
await configureUISystem(projectDir, answers.uiSystem);
|
|
@@ -853,24 +792,159 @@ async function generateTemplateStructure(projectDir, template, uiSystem) {
|
|
|
853
792
|
break;
|
|
854
793
|
}
|
|
855
794
|
}
|
|
795
|
+
/**
|
|
796
|
+
* Generate CMS Template
|
|
797
|
+
*/
|
|
856
798
|
/**
|
|
857
799
|
* Generate CMS Template
|
|
858
800
|
*/
|
|
859
801
|
async function generateCMSTemplate(projectDir, uiSystem) {
|
|
860
|
-
|
|
802
|
+
const h = getUIHelper(uiSystem);
|
|
803
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
804
|
+
// Create CMS Dashboard Page
|
|
861
805
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/CMSDashboard.tsx'), `import React from 'react';
|
|
806
|
+
${uiSystem === 'Material UI' ? "import { Box, Drawer, List, ListItem, ListItemIcon, ListItemText, Typography, Button, Grid, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Chip, AppBar, Toolbar, Divider } from '@mui/material';" : ""}
|
|
807
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Card, Button, Table, Badge, Nav, Navbar } from 'react-bootstrap';" : ""}
|
|
862
808
|
|
|
863
809
|
export default function CMSDashboard() {
|
|
810
|
+
${uiSystem === 'Material UI' ? `
|
|
811
|
+
return (
|
|
812
|
+
<Box sx={{ display: 'flex', bgcolor: '#f8fafc', minHeight: '100vh' }}>
|
|
813
|
+
<Drawer variant="permanent" sx={{ width: 280, flexShrink: 0, '& .MuiDrawer-paper': { width: 280, boxSizing: 'border-box', borderRight: '1px solid #e2e8f0', bgcolor: '#fff' } }}>
|
|
814
|
+
<Box sx={{ p: 4, display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
815
|
+
<Box sx={{ width: 32, height: 32, bgcolor: 'primary.main', borderRadius: 1.5, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontWeight: 900 }}>C</Box>
|
|
816
|
+
<Typography variant="h6" sx={{ fontWeight: 900, color: 'text.primary' }}>RiceCMS</Typography>
|
|
817
|
+
</Box>
|
|
818
|
+
<Divider sx={{ mb: 2 }} />
|
|
819
|
+
<List sx={{ px: 2 }}>
|
|
820
|
+
{['Dashboard', 'Posts', 'Categories', 'Media', 'Staff', 'Settings'].map((text, index) => (
|
|
821
|
+
<ListItem button key={text} selected={index === 0} sx={{ borderRadius: 3, mb: 1, py: 1.5, '&.Mui-selected': { bgcolor: 'primary.main', color: 'primary.contrastText', '&:hover': { bgcolor: 'primary.dark' } } }}>
|
|
822
|
+
<ListItemText primary={text} primaryTypographyProps={{ fontWeight: 700, fontSize: '0.9rem' }} />
|
|
823
|
+
</ListItem>
|
|
824
|
+
))}
|
|
825
|
+
</List>
|
|
826
|
+
</Drawer>
|
|
827
|
+
|
|
828
|
+
<Box component="main" sx={{ flexGrow: 1, p: 8 }}>
|
|
829
|
+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 8 }}>
|
|
830
|
+
<Box>
|
|
831
|
+
<Typography variant="h3" sx={{ fontWeight: 900, mb: 1, tracking: -1 }}>Content Overview</Typography>
|
|
832
|
+
<Typography color="textSecondary" sx={{ fontWeight: 500 }}>Manage your publication and track performance.</Typography>
|
|
833
|
+
</Box>
|
|
834
|
+
<Button variant="contained" sx={{ py: 2, px: 4, fontWeight: 900, borderRadius: 3, textTransform: 'none', fontSize: '1rem', boxShadow: '0 4px 14px 0 rgba(0,118,255,0.39)' }}>
|
|
835
|
+
+ New Entry
|
|
836
|
+
</Button>
|
|
837
|
+
</Box>
|
|
838
|
+
|
|
839
|
+
<Grid container spacing={4} sx={{ mb: 8 }}>
|
|
840
|
+
{[{t: 'Total Posts', v: '1,280', c: '#6366f1'}, {t: 'Total Views', v: '48.2K', c: '#10b981'}, {t: 'Pending', v: '12', c: '#f59e0b'}].map(s => (
|
|
841
|
+
<Grid item xs={12} md={4} key={s.t}>
|
|
842
|
+
<Paper sx={{ p: 4, borderRadius: 6, border: '1px solid #e2e8f0', boxShadow: '0 1px 3px 0 rgba(0,0,0,0.1)' }}>
|
|
843
|
+
<Typography color="textSecondary" sx={{ fontWeight: 700, fontSize: '0.8rem', textTransform: 'uppercase', letterSpacing: 1, mb: 2 }}>{s.t}</Typography>
|
|
844
|
+
<Typography variant="h4" sx={{ fontWeight: 900, color: s.c }}>{s.v}</Typography>
|
|
845
|
+
</Paper>
|
|
846
|
+
</Grid>
|
|
847
|
+
))}
|
|
848
|
+
</Grid>
|
|
849
|
+
|
|
850
|
+
<TableContainer component={Paper} sx={{ borderRadius: 6, border: '1px solid #e2e8f0', boxShadow: 'none', overflow: 'hidden' }}>
|
|
851
|
+
<Table>
|
|
852
|
+
<TableHead sx={{ bgcolor: '#f8fafc' }}>
|
|
853
|
+
<TableRow>
|
|
854
|
+
<TableCell sx={{ fontWeight: 900, py: 3, ps: 4 }}>TITLE</TableCell>
|
|
855
|
+
<TableCell sx={{ fontWeight: 900, py: 3 }}>AUTHOR</TableCell>
|
|
856
|
+
<TableCell sx={{ fontWeight: 900, py: 3 }}>STATUS</TableCell>
|
|
857
|
+
<TableCell sx={{ fontWeight: 900, py: 3, pe: 4 }}>DATE</TableCell>
|
|
858
|
+
</TableRow>
|
|
859
|
+
</TableHead>
|
|
860
|
+
<TableBody>
|
|
861
|
+
{['The Art of Minimalist Living', 'Explaining EreactThohir Architecture', 'Designing with Rice UI'].map((title, i) => (
|
|
862
|
+
<TableRow key={title} hover sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
|
|
863
|
+
<TableCell sx={{ fontWeight: 700, py: 3, ps: 4 }}>{title}</TableCell>
|
|
864
|
+
<TableCell sx={{ color: 'text.secondary', fontWeight: 500 }}>Dhafa N.</TableCell>
|
|
865
|
+
<TableCell>
|
|
866
|
+
<Chip label={i === 2 ? "DRAFT" : "PUBLISHED"} size="small" color={i === 2 ? "default" : "success"} sx={{ fontWeight: 900, borderRadius: 1.5, fontSize: '0.7rem' }} />
|
|
867
|
+
</TableCell>
|
|
868
|
+
<TableCell sx={{ color: 'text.secondary', py: 3, pe: 4 }}>Oct {24-i}, 2023</TableCell>
|
|
869
|
+
</TableRow>
|
|
870
|
+
))}
|
|
871
|
+
</TableBody>
|
|
872
|
+
</Table>
|
|
873
|
+
</TableContainer>
|
|
874
|
+
</Box>
|
|
875
|
+
</Box>
|
|
876
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
864
877
|
return (
|
|
865
|
-
<div className="
|
|
878
|
+
<div className="d-flex bg-white min-vh-100">
|
|
866
879
|
{/* Sidebar */}
|
|
867
|
-
<
|
|
868
|
-
<div className="
|
|
869
|
-
<div className="
|
|
870
|
-
<span className="
|
|
880
|
+
<div className="bg-light border-end d-none d-md-block" style={{ width: '280px' }}>
|
|
881
|
+
<div className="p-4 d-flex align-items-center gap-2 mb-4">
|
|
882
|
+
<div className="bg-dark rounded-3 text-white fw-black d-flex align-items-center justify-content-center" style={{ width: '32px', height: '32px' }}>C</div>
|
|
883
|
+
<span className="h5 fw-black mb-0 text-dark">RiceCMS</span>
|
|
884
|
+
</div>
|
|
885
|
+
<Nav className="flex-column px-3 gap-1">
|
|
886
|
+
<Nav.Link className="bg-primary text-white rounded-4 fw-bold p-3 mb-2 shadow-sm">š Dashboard</Nav.Link>
|
|
887
|
+
<Nav.Link className="text-secondary fw-bold p-3">š Posts</Nav.Link>
|
|
888
|
+
<Nav.Link className="text-secondary fw-bold p-3">š Categories</Nav.Link>
|
|
889
|
+
<Nav.Link className="text-secondary fw-bold p-3">š¼ļø Media</Nav.Link>
|
|
890
|
+
<Nav.Link className="text-secondary fw-bold p-3">š„ Staff</Nav.Link>
|
|
891
|
+
<Nav.Link className="text-secondary fw-bold p-3">āļø Settings</Nav.Link>
|
|
892
|
+
</Nav>
|
|
893
|
+
</div>
|
|
894
|
+
|
|
895
|
+
{/* Main Content */}
|
|
896
|
+
<main className="flex-grow-1 p-5 bg-white">
|
|
897
|
+
<div className="d-flex justify-content-between align-items-center mb-5">
|
|
898
|
+
<div>
|
|
899
|
+
<h1 className="display-5 fw-black mb-1 letter-spacing-tight">Content Overview</h1>
|
|
900
|
+
<p className="text-muted lead fs-6">Manage your publication and track performance.</p>
|
|
901
|
+
</div>
|
|
902
|
+
<Button variant="dark" className="py-3 px-4 fw-bold rounded-4 shadow-lg border-0" style={{ background: 'linear-gradient(135deg, #0f172a 0%, #334155 100%)' }}>
|
|
903
|
+
+ New Entry
|
|
904
|
+
</Button>
|
|
905
|
+
</div>
|
|
906
|
+
|
|
907
|
+
<Row className="mb-5 g-4 text-center">
|
|
908
|
+
{[{t:'Total Posts',v:'1,280',c:'primary'}, {t:'Total Views',v:'48.2K',c:'success'}, {t:'Pending',v:'12',c:'warning'}].map(s => (
|
|
909
|
+
<Col md={4} key={s.t}>
|
|
910
|
+
<Card className="border-0 bg-light rounded-5 p-4 h-100">
|
|
911
|
+
<span className="text-uppercase small fw-black text-secondary letter-spacing-wide mb-2">{s.t}</span>
|
|
912
|
+
<h2 className={\`fw-black mb-0 text-\${s.c}\`}>{s.v}</h2>
|
|
913
|
+
</Card>
|
|
914
|
+
</Col>
|
|
915
|
+
))}
|
|
916
|
+
</Row>
|
|
917
|
+
|
|
918
|
+
<div className="card border-0 shadow-sm rounded-5 overflow-hidden">
|
|
919
|
+
<Table hover responsive className="mb-0 align-middle">
|
|
920
|
+
<thead className="bg-light">
|
|
921
|
+
<tr>
|
|
922
|
+
<th className="p-4 ps-5 border-0 text-secondary small fw-black">TITLE</th>
|
|
923
|
+
<th className="p-4 border-0 text-secondary small fw-black">AUTHOR</th>
|
|
924
|
+
<th className="p-4 border-0 text-secondary small fw-black">STATUS</th>
|
|
925
|
+
<th className="p-4 pe-5 border-0 text-secondary small fw-black">DATE</th>
|
|
926
|
+
</tr>
|
|
927
|
+
</thead>
|
|
928
|
+
<tbody>
|
|
929
|
+
<CMSRow title="The Art of Minimalist Living" author="Dhafa N." status="Published" date="Oct 24, 2023" />
|
|
930
|
+
<CMSRow title="Explaining EreactThohir Architecture" author="Dhafa N." status="Published" date="Oct 22, 2023" />
|
|
931
|
+
<CMSRow title="Designing Rice UI" author="Sarah K." status="Draft" date="Oct 20, 2023" />
|
|
932
|
+
</tbody>
|
|
933
|
+
</Table>
|
|
934
|
+
</div>
|
|
935
|
+
</main>
|
|
936
|
+
</div>
|
|
937
|
+
);` : `
|
|
938
|
+
return (
|
|
939
|
+
<div className="\${p}min-h-screen \${p}bg-secondary-50 \${p}flex">
|
|
940
|
+
{/* Sidebar */}
|
|
941
|
+
<aside className="\${p}w-72 \${p}bg-white \${p}border-r \${p}p-8 \${p}flex \${p}col \${p}gap-8 \${p}hidden \${p}md-flex">
|
|
942
|
+
<div className="\${p}flex \${p}items-center \${p}gap-2">
|
|
943
|
+
<div className="\${p}w-8 \${p}h-8 \${p}bg-secondary-900 \${p}rounded-lg \${p}flex \${p}items-center \${p}justify-center \${p}text-white \${p}font-black">C</div>
|
|
944
|
+
<span className="\${p}text-xl \${p}font-black">RiceCMS</span>
|
|
871
945
|
</div>
|
|
872
946
|
|
|
873
|
-
<nav className="
|
|
947
|
+
<nav className="\${p}flex \${p}col \${p}gap-2 \${p}w-full">
|
|
874
948
|
<NavItem icon="š" label="Dashboard" active />
|
|
875
949
|
<NavItem icon="š" label="Posts" />
|
|
876
950
|
<NavItem icon="š" label="Categories" />
|
|
@@ -881,55 +955,53 @@ export default function CMSDashboard() {
|
|
|
881
955
|
</aside>
|
|
882
956
|
|
|
883
957
|
{/* Main Content */}
|
|
884
|
-
<main className="
|
|
885
|
-
<header className="
|
|
958
|
+
<main className="\${p}flex-1 \${p}p-8 \${p}md-p-12">
|
|
959
|
+
<header className="\${p}mb-12 \${p}flex \${p}justify-between \${p}items-center">
|
|
886
960
|
<div>
|
|
887
|
-
<h1 className="
|
|
888
|
-
<p className="
|
|
961
|
+
<h1 className="\${p}text-4xl \${p}font-black \${p}mb-2">Content Overview</h1>
|
|
962
|
+
<p className="\${p}text-secondary-600">Manage your publication and track performance.</p>
|
|
889
963
|
</div>
|
|
890
|
-
<button className="
|
|
964
|
+
<button className="\${p}px-6 \${p}py-3 \${p}bg-primary-500 \${p}text-white \${p}rounded-xl \${p}font-bold \${p}shadow-lg \${p}hover-scale-105 \${p}transition-all">
|
|
891
965
|
+ New Entry
|
|
892
966
|
</button>
|
|
893
967
|
</header>
|
|
894
968
|
|
|
895
969
|
{/* Stats Grid */}
|
|
896
|
-
<div className="
|
|
970
|
+
<div className="\${p}grid \${p}grid-cols-1 \${p}md-grid-cols-3 \${p}gap-8 \${p}mb-12">
|
|
897
971
|
<CMSStatCard title="Total Posts" value="1,280" icon="š" />
|
|
898
972
|
<CMSStatCard title="Total Views" value="48.2K" icon="šļø" />
|
|
899
|
-
<CMSStatCard title="Pending Review" value="12" icon="ā³" color="
|
|
973
|
+
<CMSStatCard title="Pending Review" value="12" icon="ā³" color="\${p}text-primary-500" />
|
|
900
974
|
</div>
|
|
901
975
|
|
|
902
976
|
{/* Recent Entries Table */}
|
|
903
|
-
<div className="
|
|
904
|
-
<div className="
|
|
905
|
-
<h2 className="
|
|
906
|
-
<span className="
|
|
977
|
+
<div className="\${p}bg-white \${p}border \${p}rounded-3xl \${p}overflow-hidden">
|
|
978
|
+
<div className="\${p}p-8 \${p}border-b \${p}flex \${p}justify-between \${p}items-center">
|
|
979
|
+
<h2 className="\${p}text-xl \${p}font-bold">Recent Entries</h2>
|
|
980
|
+
<span className="\${p}text-sm \${p}text-secondary-500 \${p}cursor-pointer \${p}hover-text-secondary-900">View all</span>
|
|
907
981
|
</div>
|
|
908
|
-
<table className="
|
|
909
|
-
<thead className="
|
|
982
|
+
<table className="\${p}w-full">
|
|
983
|
+
<thead className="\${p}bg-secondary-50">
|
|
910
984
|
<tr>
|
|
911
|
-
<th className="
|
|
912
|
-
<th className="
|
|
913
|
-
<th className="
|
|
914
|
-
<th className="
|
|
985
|
+
<th className="\${p}px-8 \${p}py-4 \${p}text-left \${p}text-xs \${p}font-bold \${p}text-secondary-500">TITLE</th>
|
|
986
|
+
<th className="\${p}px-8 \${p}py-4 \${p}text-left \${p}text-xs \${p}font-bold \${p}text-secondary-500">AUTHOR</th>
|
|
987
|
+
<th className="\${p}px-8 \${p}py-4 \${p}text-left \${p}text-xs \${p}font-bold \${p}text-secondary-500">STATUS</th>
|
|
988
|
+
<th className="\${p}px-8 \${p}py-4 \${p}text-left \${p}text-xs \${p}font-bold \${p}text-secondary-500">DATE</th>
|
|
915
989
|
</tr>
|
|
916
990
|
</thead>
|
|
917
|
-
<tbody className="
|
|
991
|
+
<tbody className="\${p}divide-y">
|
|
918
992
|
<CMSRow title="The Art of Minimalist Living" author="Dhafa N." status="Published" date="Oct 24, 2023" />
|
|
919
993
|
<CMSRow title="Explaining EreactThohir Internal Architecture" author="Dhafa N." status="Published" date="Oct 22, 2023" />
|
|
920
|
-
<CMSRow title="Designing with Rice UI in Mind" author="Sarah K." status="Draft" date="Oct 20, 2023" />
|
|
921
|
-
<CMSRow title="Future of Serverless Frameworks" author="Mark T." status="Scheduled" date="Oct 18, 2023" />
|
|
922
994
|
</tbody>
|
|
923
995
|
</table>
|
|
924
996
|
</div>
|
|
925
997
|
</main>
|
|
926
998
|
</div>
|
|
927
|
-
)
|
|
999
|
+
);`}
|
|
928
1000
|
}
|
|
929
1001
|
|
|
930
1002
|
function NavItem({ icon, label, active = false }: any) {
|
|
931
1003
|
return (
|
|
932
|
-
<div className={
|
|
1004
|
+
<div className={\`\${p}flex \${p}items-center \${p}gap-3 \${p}px-4 \${p}py-3 \${p}rounded-xl \${p}text-sm \${p}font-bold \${p}cursor-pointer \${p}transition-all \${active ? '\${p}bg-secondary-900 \${p}text-white' : '\${p}text-secondary-600 \${p}hover-bg-secondary-100'}\`}>
|
|
933
1005
|
<span>{icon}</span>
|
|
934
1006
|
<span>{label}</span>
|
|
935
1007
|
</div>
|
|
@@ -938,39 +1010,48 @@ function NavItem({ icon, label, active = false }: any) {
|
|
|
938
1010
|
|
|
939
1011
|
function CMSStatCard({ title, value, icon, color }: any) {
|
|
940
1012
|
return (
|
|
941
|
-
<div className="
|
|
942
|
-
<div className="
|
|
943
|
-
<div className="
|
|
1013
|
+
<div className="\${p}bg-white \${p}p-8 \${p}border \${p}rounded-3xl \${p}shadow-sm">
|
|
1014
|
+
<div className="\${p}flex \${p}justify-between \${p}items-start \${p}mb-4">
|
|
1015
|
+
<div className="\${p}w-12 \${p}h-12 \${p}bg-secondary-50 \${p}rounded-2xl \${p}flex \${p}items-center \${p}justify-center \${p}text-xl">{icon}</div>
|
|
944
1016
|
</div>
|
|
945
|
-
<p className="
|
|
946
|
-
<p className={
|
|
1017
|
+
<p className="\${p}text-sm \${p}font-medium \${p}text-secondary-500 \${p}mb-1">{title}</p>
|
|
1018
|
+
<p className={\`\${p}text-3xl \${p}font-black \${color || '\${p}text-secondary-900'}\`}>{value}</p>
|
|
947
1019
|
</div>
|
|
948
1020
|
);
|
|
949
1021
|
}
|
|
950
1022
|
|
|
951
1023
|
function CMSRow({ title, author, status, date }: any) {
|
|
1024
|
+
${uiSystem === 'Bootstrap 5' ? `
|
|
1025
|
+
return (
|
|
1026
|
+
<tr>
|
|
1027
|
+
<td className="p-4 ps-5 fw-bold text-dark">{title}</td>
|
|
1028
|
+
<td className="p-4 text-muted">{author}</td>
|
|
1029
|
+
<td className="p-4"><Badge bg={status === 'Published'?'success':'secondary'} pill className="px-3 py-2">{status.toUpperCase()}</Badge></td>
|
|
1030
|
+
<td className="p-4 pe-5 text-muted">{date}</td>
|
|
1031
|
+
</tr>
|
|
1032
|
+
);` : `
|
|
952
1033
|
return (
|
|
953
|
-
<tr className="
|
|
954
|
-
<td className="
|
|
955
|
-
<p className="
|
|
1034
|
+
<tr className="\${p}hover-bg-secondary-50 \${p}transition-all \${p}cursor-pointer">
|
|
1035
|
+
<td className="\${p}px-8 \${p}py-6">
|
|
1036
|
+
<p className="\${p}font-bold \${p}text-secondary-900">{title}</p>
|
|
956
1037
|
</td>
|
|
957
|
-
<td className="
|
|
958
|
-
<p className="
|
|
1038
|
+
<td className="\${p}px-8 \${p}py-6">
|
|
1039
|
+
<p className="\${p}text-sm \${p}text-secondary-600">{author}</p>
|
|
959
1040
|
</td>
|
|
960
|
-
<td className="
|
|
961
|
-
<span className={
|
|
962
|
-
status === 'Published' ? '
|
|
963
|
-
status === 'Draft' ? '
|
|
964
|
-
'
|
|
1041
|
+
<td className="\${p}px-8 \${p}py-6">
|
|
1042
|
+
<span className={\`\${p}px-3 \${p}py-1 \${p}rounded-full \${p}text-[10px] \${p}font-black \${p}tracking-wider \${
|
|
1043
|
+
status === 'Published' ? '\${p}bg-success-600 \${p}bg-opacity-10 \${p}text-success-600' :
|
|
1044
|
+
status === 'Draft' ? '\${p}bg-secondary-200 \${p}text-secondary-600' :
|
|
1045
|
+
'\${p}bg-primary-500 \${p}bg-opacity-10 \${p}text-primary-600'
|
|
965
1046
|
}\`}>
|
|
966
1047
|
{status.toUpperCase()}
|
|
967
1048
|
</span>
|
|
968
1049
|
</td>
|
|
969
|
-
<td className="
|
|
970
|
-
<p className="
|
|
1050
|
+
<td className="\${p}px-8 \${p}py-6">
|
|
1051
|
+
<p className="\${p}text-sm \${p}text-secondary-500">{date}</p>
|
|
971
1052
|
</td>
|
|
972
1053
|
</tr>
|
|
973
|
-
)
|
|
1054
|
+
);`}
|
|
974
1055
|
}
|
|
975
1056
|
`);
|
|
976
1057
|
// Create Entry Editor Page
|
|
@@ -978,34 +1059,34 @@ function CMSRow({ title, author, status, date }: any) {
|
|
|
978
1059
|
|
|
979
1060
|
export default function CMSEditor() {
|
|
980
1061
|
return (
|
|
981
|
-
<div className="
|
|
982
|
-
<header className="
|
|
983
|
-
<div className="
|
|
984
|
-
<button className="
|
|
985
|
-
<h1 className="
|
|
1062
|
+
<div className="\${p}min-h-screen \${p}bg-white \${p}flex \${p}col">
|
|
1063
|
+
<header className="\${p}p-6 \${p}border-b \${p}flex \${p}justify-between \${p}items-center">
|
|
1064
|
+
<div className="\${p}flex \${p}items-center \${p}gap-4">
|
|
1065
|
+
<button className="\${p}p-2 \${p}hover-bg-secondary-100 \${p}rounded-lg">ā</button>
|
|
1066
|
+
<h1 className="\${p}text-lg \${p}font-bold">Edit Entry</h1>
|
|
986
1067
|
</div>
|
|
987
|
-
<div className="
|
|
988
|
-
<button className="
|
|
989
|
-
<button className="
|
|
1068
|
+
<div className="\${p}flex \${p}gap-3">
|
|
1069
|
+
<button className="\${p}px-5 \${p}py-2 \${p}text-secondary-600 \${p}font-bold \${p}text-sm">Save as Draft</button>
|
|
1070
|
+
<button className="\${p}px-5 \${p}py-2 \${p}bg-secondary-900 \${p}text-white \${p}rounded-xl \${p}font-bold \${p}text-sm">Publish Post</button>
|
|
990
1071
|
</div>
|
|
991
1072
|
</header>
|
|
992
1073
|
|
|
993
|
-
<main className="
|
|
1074
|
+
<main className="\${p}flex-1 \${p}p-8 \${p}max-w-4xl \${p}mx-auto \${p}w-full">
|
|
994
1075
|
<input
|
|
995
1076
|
type="text"
|
|
996
1077
|
placeholder="Enter post title..."
|
|
997
|
-
className="
|
|
1078
|
+
className="\${p}w-full \${p}text-5xl \${p}font-black \${p}rice-placeholder-secondary-300 \${p}focus-outline-none \${p}mb-8"
|
|
998
1079
|
/>
|
|
999
1080
|
|
|
1000
|
-
<div className="
|
|
1001
|
-
<button className="
|
|
1002
|
-
<button className="
|
|
1003
|
-
<button className="
|
|
1081
|
+
<div className="\${p}flex \${p}gap-4 \${p}mb-8 \${p}border-b \${p}pb-4">
|
|
1082
|
+
<button className="\${p}text-sm \${p}font-bold \${p}text-primary-500">Content</button>
|
|
1083
|
+
<button className="\${p}text-sm \${p}font-medium \${p}text-secondary-500">SEO</button>
|
|
1084
|
+
<button className="\${p}text-sm \${p}font-medium \${p}text-secondary-500">Settings</button>
|
|
1004
1085
|
</div>
|
|
1005
1086
|
|
|
1006
1087
|
<textarea
|
|
1007
1088
|
placeholder="Start writing your masterpiece..."
|
|
1008
|
-
className="
|
|
1089
|
+
className="\${p}w-full \${p}h-[500px] \${p}text-lg \${p}leading-relaxed \${p}rice-placeholder-secondary-300 \${p}focus-outline-none \${p}rice-resize-none"
|
|
1009
1090
|
/>
|
|
1010
1091
|
</main>
|
|
1011
1092
|
</div>
|
|
@@ -1016,9 +1097,9 @@ export default function CMSEditor() {
|
|
|
1016
1097
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/cms.ts'), `import { Route } from '@ereactthohir/core';
|
|
1017
1098
|
|
|
1018
1099
|
Route.group({ prefix: '/cms' }, () => {
|
|
1019
|
-
Route.get('/dashboard', (req, res) =>
|
|
1020
|
-
|
|
1021
|
-
|
|
1100
|
+
Route.get('/dashboard', (req, res) => {
|
|
1101
|
+
return res.view('CMSDashboard');
|
|
1102
|
+
});
|
|
1022
1103
|
});
|
|
1023
1104
|
`);
|
|
1024
1105
|
}
|
|
@@ -1026,6 +1107,8 @@ Route.group({ prefix: '/cms' }, () => {
|
|
|
1026
1107
|
* Generate Ecommerce App template
|
|
1027
1108
|
*/
|
|
1028
1109
|
async function generateEcommerceTemplate(projectDir, uiSystem) {
|
|
1110
|
+
const h = getUIHelper(uiSystem);
|
|
1111
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1029
1112
|
// Create Cart Store
|
|
1030
1113
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/stores/useCartStore.ts'), `import { create } from 'zustand';
|
|
1031
1114
|
|
|
@@ -1074,6 +1157,8 @@ export const useCartStore = create<CartState>((set) => ({
|
|
|
1074
1157
|
// Create Shop Page
|
|
1075
1158
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Shop.tsx'), `import React from 'react';
|
|
1076
1159
|
import { useCartStore } from '../stores/useCartStore';
|
|
1160
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, Grid, Card as MuiCard, CardMedia, CardContent, Button as MuiButton, AppBar, Toolbar, Badge } from '@mui/material';" : ""}
|
|
1161
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Card as BsCard, Button as BsButton, Navbar, Nav, Badge as BsBadge } from 'react-bootstrap';" : ""}
|
|
1077
1162
|
|
|
1078
1163
|
const products = [
|
|
1079
1164
|
{ id: 1, name: 'Premium Wireless Headphones', price: 299, image: 'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=500' },
|
|
@@ -1085,39 +1170,119 @@ const products = [
|
|
|
1085
1170
|
export default function Shop() {
|
|
1086
1171
|
const { addItem, items } = useCartStore();
|
|
1087
1172
|
|
|
1173
|
+
${uiSystem === 'Material UI' ? `
|
|
1174
|
+
return (
|
|
1175
|
+
<Box sx={{ bgcolor: '#f8fafc', minHeight: '100vh' }}>
|
|
1176
|
+
<AppBar position="sticky" sx={{ bgcolor: 'white', color: 'text.primary', boxShadow: 'none', borderBottom: '1px solid #e2e8f0' }}>
|
|
1177
|
+
<Container>
|
|
1178
|
+
<Toolbar sx={{ justifyContent: 'space-between' }}>
|
|
1179
|
+
<Typography variant="h5" sx={{ fontWeight: 900, color: 'primary.main' }}>ERectShop</Typography>
|
|
1180
|
+
<Badge badgeContent={items.length} color="primary">
|
|
1181
|
+
<Typography sx={{ fontSize: 24 }}>š</Typography>
|
|
1182
|
+
</Badge>
|
|
1183
|
+
</Toolbar>
|
|
1184
|
+
</Container>
|
|
1185
|
+
</AppBar>
|
|
1186
|
+
|
|
1187
|
+
<Container sx={{ py: 8 }}>
|
|
1188
|
+
<Box sx={{ mb: 6 }}>
|
|
1189
|
+
<Typography variant="h3" sx={{ fontWeight: 900, mb: 1 }}>Featured Products</Typography>
|
|
1190
|
+
<Typography color="textSecondary">Curated collection of premium tech gadgets.</Typography>
|
|
1191
|
+
</Box>
|
|
1192
|
+
|
|
1193
|
+
<Grid container spacing={4}>
|
|
1194
|
+
{products.map(product => (
|
|
1195
|
+
<Grid item xs={12} sm={6} lg={3} key={product.id}>
|
|
1196
|
+
<MuiCard sx={{ borderRadius: 4, overflow: 'hidden', transition: '0.3s', '&:hover': { transform: 'translateY(-8px)', boxShadow: 10 } }}>
|
|
1197
|
+
<CardMedia component="img" height="240" image={product.image} />
|
|
1198
|
+
<CardContent sx={{ p: 3 }}>
|
|
1199
|
+
<Typography variant="h6" sx={{ fontWeight: 900, mb: 1 }}>{product.name}</Typography>
|
|
1200
|
+
<Typography variant="h5" color="primary" sx={{ fontWeight: 900, mb: 2 }}>\${product.price}</Typography>
|
|
1201
|
+
<MuiButton variant="contained" fullWidth sx={{ py: 1.5, fontWeight: 900, borderRadius: 2 }} onClick={() => addItem(product)}>
|
|
1202
|
+
Add To Cart
|
|
1203
|
+
</MuiButton>
|
|
1204
|
+
</CardContent>
|
|
1205
|
+
</MuiCard>
|
|
1206
|
+
</Grid>
|
|
1207
|
+
))}
|
|
1208
|
+
</Grid>
|
|
1209
|
+
</Container>
|
|
1210
|
+
</Box>
|
|
1211
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
1088
1212
|
return (
|
|
1089
|
-
<div className="
|
|
1213
|
+
<div className="bg-light min-vh-100">
|
|
1214
|
+
<Navbar bg="white" sticky="top" className="py-3 shadow-sm">
|
|
1215
|
+
<Container>
|
|
1216
|
+
<Navbar.Brand className="fw-black text-primary fs-3">ERectShop</Navbar.Brand>
|
|
1217
|
+
<Nav className="ms-auto align-items-center">
|
|
1218
|
+
<div className="position-relative">
|
|
1219
|
+
<span className="fs-4">š</span>
|
|
1220
|
+
{items.length > 0 && <BsBadge pill bg="primary" className="position-absolute top-0 start-100 translate-middle">{items.length}</BsBadge>}
|
|
1221
|
+
</div>
|
|
1222
|
+
</Nav>
|
|
1223
|
+
</Container>
|
|
1224
|
+
</Navbar>
|
|
1225
|
+
|
|
1226
|
+
<Container className="py-5">
|
|
1227
|
+
<header className="mb-5">
|
|
1228
|
+
<h2 className="display-5 fw-black mb-2">Featured Products</h2>
|
|
1229
|
+
<p className="text-secondary lead">Curated collection of premium tech gadgets.</p>
|
|
1230
|
+
</header>
|
|
1231
|
+
|
|
1232
|
+
<Row className="g-4">
|
|
1233
|
+
{products.map(product => (
|
|
1234
|
+
<Col sm={6} lg={3} key={product.id}>
|
|
1235
|
+
<BsCard className="border-0 shadow-lg rounded-4 overflow-hidden h-100">
|
|
1236
|
+
<div className="ratio ratio-4x3">
|
|
1237
|
+
<BsCard.Img variant="top" src={product.image} className="object-fit-cover" />
|
|
1238
|
+
</div>
|
|
1239
|
+
<BsCard.Body className="p-4">
|
|
1240
|
+
<BsCard.Title className="fw-bold fs-5 mb-2">{product.name}</BsCard.Title>
|
|
1241
|
+
<BsCard.Text className="fs-4 fw-black text-primary mb-4">\${product.price}</BsCard.Text>
|
|
1242
|
+
<BsButton variant="dark" className="w-100 py-3 rounded-3 fw-bold" onClick={() => addItem(product)}>
|
|
1243
|
+
Add to Cart
|
|
1244
|
+
</BsButton>
|
|
1245
|
+
</BsCard.Body>
|
|
1246
|
+
</BsCard>
|
|
1247
|
+
</Col>
|
|
1248
|
+
))}
|
|
1249
|
+
</Row>
|
|
1250
|
+
</Container>
|
|
1251
|
+
</div>
|
|
1252
|
+
);` : `
|
|
1253
|
+
return (
|
|
1254
|
+
<div className="\${p}min-h-screen \${p}bg-secondary-100">
|
|
1090
1255
|
{/* Navbar */}
|
|
1091
|
-
<nav className="
|
|
1092
|
-
<h1 className="
|
|
1093
|
-
<div className="
|
|
1094
|
-
<span className="
|
|
1256
|
+
<nav className="\${p}p-6 \${p}bg-white \${p}shadow-sm \${p}flex \${p}justify-between \${p}items-center \${p}sticky \${p}top-0 \${p}z-10">
|
|
1257
|
+
<h1 className="\${p}text-2xl \${p}font-black \${h.cls('rice-gradient-primary rice-bg-clip-text rice-text-transparent', 'text-blue-600', 'joko-text-primary-600')}">ERectShop</h1>
|
|
1258
|
+
<div className="\${p}relative \${p}cursor-pointer">
|
|
1259
|
+
<span className="\${p}text-lg">š</span>
|
|
1095
1260
|
{items.length > 0 && (
|
|
1096
|
-
<span className="
|
|
1261
|
+
<span className="\${p}absolute -\${p}top-2 -\${p}right-2 \${p}bg-primary-500 \${p}text-white \${p}text-xs \${p}font-bold \${p}rounded-full \${p}w-5 \${p}h-5 \${p}flex \${p}items-center \${p}justify-center">
|
|
1097
1262
|
{items.length}
|
|
1098
1263
|
</span>
|
|
1099
1264
|
)}
|
|
1100
1265
|
</div>
|
|
1101
1266
|
</nav>
|
|
1102
1267
|
|
|
1103
|
-
<div className="
|
|
1104
|
-
<header className="
|
|
1105
|
-
<h2 className="
|
|
1106
|
-
<p className="
|
|
1268
|
+
<div className="\${p}p-8 \${p}max-w-7xl \${p}mx-auto">
|
|
1269
|
+
<header className="\${p}mb-12">
|
|
1270
|
+
<h2 className="\${p}text-4xl \${p}font-bold \${p}mb-2">Featured Products</h2>
|
|
1271
|
+
<p className="\${p}text-secondary-600">Curated collection of premium tech gadgets.</p>
|
|
1107
1272
|
</header>
|
|
1108
1273
|
|
|
1109
|
-
<div className="
|
|
1274
|
+
<div className="\${p}grid \${p}grid-cols-1 \${h.cls('rice-md-grid-cols-2 rice-lg-grid-cols-4', 'md:grid-cols-2 lg:grid-cols-4', 'joko-grid-cols-2')} \${p}gap-8">
|
|
1110
1275
|
{products.map(product => (
|
|
1111
|
-
<div key={product.id} className="rice-bg-white rice-rounded-2xl rice-overflow-hidden rice-shadow-lg rice-hover-shadow-2xl rice-transition-all rice-duration-300 rice-group">
|
|
1112
|
-
<div className="
|
|
1113
|
-
<img src={product.image} alt={product.name} className="
|
|
1276
|
+
<div key={product.id} className="\${h.cls('rice-bg-white rice-rounded-2xl rice-overflow-hidden rice-shadow-lg rice-hover-shadow-2xl rice-transition-all rice-duration-300 rice-group', 'bg-white rounded-2xl overflow-hidden shadow-lg hover:shadow-2xl transition-all duration-300 group', 'joko-card')}">
|
|
1277
|
+
<div className="\${p}h-64 \${p}overflow-hidden">
|
|
1278
|
+
<img src={product.image} alt={product.name} className="\${p}w-full \${p}h-full \${p}object-cover \${p}transition-all \${p}duration-500" />
|
|
1114
1279
|
</div>
|
|
1115
|
-
<div className="
|
|
1116
|
-
<h3 className="
|
|
1117
|
-
<p className="rice-text-primary-600 rice-font-black rice-text-xl rice-mb-4"
|
|
1280
|
+
<div className="\${p}p-6">
|
|
1281
|
+
<h3 className="\${p}font-bold \${p}text-lg \${p}mb-1">{product.name}</h3>
|
|
1282
|
+
<p className="\${h.cls('rice-text-primary-600 rice-font-black rice-text-xl rice-mb-4', 'text-blue-600 font-black text-xl mb-4', 'joko-text-primary-600 font-bold mb-4')}">{product.price}</p>
|
|
1118
1283
|
<button
|
|
1119
1284
|
onClick={() => addItem(product)}
|
|
1120
|
-
className="rice-w-full rice-py-3 rice-bg-secondary-900 rice-text-white rice-rounded-xl rice-font-bold rice-hover-bg-primary-600 rice-transition-all"
|
|
1285
|
+
className="\${h.cls('rice-w-full rice-py-3 rice-bg-secondary-900 rice-text-white rice-rounded-xl rice-font-bold rice-hover-bg-primary-600 rice-transition-all', 'w-full py-3 bg-slate-900 text-white rounded-xl font-bold hover:bg-blue-600 transition-all', 'joko-btn joko-btn-primary')} joko-w-full"
|
|
1121
1286
|
>
|
|
1122
1287
|
Add to Cart
|
|
1123
1288
|
</button>
|
|
@@ -1127,7 +1292,7 @@ export default function Shop() {
|
|
|
1127
1292
|
</div>
|
|
1128
1293
|
</div>
|
|
1129
1294
|
</div>
|
|
1130
|
-
)
|
|
1295
|
+
);`}
|
|
1131
1296
|
}
|
|
1132
1297
|
`);
|
|
1133
1298
|
// Create Ecommerce routes
|
|
@@ -1135,54 +1300,140 @@ export default function Shop() {
|
|
|
1135
1300
|
|
|
1136
1301
|
Route.get('/shop', (req, res) => res.view('Shop'));
|
|
1137
1302
|
Route.get('/cart', (req, res) => res.view('Cart'));
|
|
1138
|
-
Route.
|
|
1303
|
+
Route.post('/checkout', 'CheckoutController@store');
|
|
1139
1304
|
`);
|
|
1140
1305
|
}
|
|
1141
1306
|
/**
|
|
1142
1307
|
* Generate Portfolio Template
|
|
1143
1308
|
*/
|
|
1144
1309
|
async function generatePortfolioTemplate(projectDir, uiSystem) {
|
|
1310
|
+
const h = getUIHelper(uiSystem);
|
|
1311
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1145
1312
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Portfolio.tsx'), `import React from 'react';
|
|
1313
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, Button, Grid, Paper, Chip, Stack } from '@mui/material';" : ""}
|
|
1314
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Button, Card, Nav } from 'react-bootstrap';" : ""}
|
|
1146
1315
|
|
|
1147
1316
|
export default function Portfolio() {
|
|
1317
|
+
${uiSystem === 'Material UI' ? `
|
|
1318
|
+
return (
|
|
1319
|
+
<Box sx={{ bgcolor: 'white', color: 'text.primary', minHeight: '100vh' }}>
|
|
1320
|
+
{/* Hero Section */}
|
|
1321
|
+
<Container sx={{ py: 15, textAlign: 'center' }}>
|
|
1322
|
+
<Box sx={{ mb: 4 }}>
|
|
1323
|
+
<Chip label="Available for hire" color="primary" sx={{ fontWeight: 900, borderRadius: 10, px: 1 }} />
|
|
1324
|
+
</Box>
|
|
1325
|
+
<Typography variant="h1" sx={{ fontWeight: 900, mb: 3, tracking: -2 }}>
|
|
1326
|
+
Crafting <Box component="span" sx={{ color: 'primary.main' }}>Digital Experiences</Box> that matter.
|
|
1327
|
+
</Typography>
|
|
1328
|
+
<Typography variant="h5" color="textSecondary" sx={{ maxW: '800px', mx: 'auto', mb: 6, fontWeight: 500, lineHeight: 1.6 }}>
|
|
1329
|
+
I'm a Fullstack Developer specializing in building high-performance web applications with EreactThohir ecosystem.
|
|
1330
|
+
</Typography>
|
|
1331
|
+
<Stack direction="row" spacing={3} justifyContent="center">
|
|
1332
|
+
<Button variant="contained" size="large" sx={{ px: 6, py: 2, borderRadius: 10, fontWeight: 900 }}>View Projects</Button>
|
|
1333
|
+
<Button variant="outlined" size="large" sx={{ px: 6, py: 2, borderRadius: 10, fontWeight: 900 }}>Contact Me</Button>
|
|
1334
|
+
</Stack>
|
|
1335
|
+
</Container>
|
|
1336
|
+
|
|
1337
|
+
{/* Projects Grid */}
|
|
1338
|
+
<Box sx={{ py: 12, bgcolor: '#f8fafc' }}>
|
|
1339
|
+
<Container>
|
|
1340
|
+
<Typography variant="h3" sx={{ fontWeight: 900, mb: 8 }}>Selected Works</Typography>
|
|
1341
|
+
<Grid container spacing={6}>
|
|
1342
|
+
{[1, 2, 3, 4].map(i => (
|
|
1343
|
+
<Grid item xs={12} md={6} key={i}>
|
|
1344
|
+
<Paper elevation={0} sx={{ borderRadius: 8, overflow: 'hidden', bgcolor: 'transparent', cursor: 'pointer', transition: '0.3s', '&:hover': { transform: 'translateY(-8px)' } }}>
|
|
1345
|
+
<Box sx={{ aspectSize: '16/9', bgcolor: '#e2e8f0', borderRadius: 8, mb: 3 }} />
|
|
1346
|
+
<Typography variant="h5" sx={{ fontWeight: 900, mb: 1 }}>Project Name #{i}</Typography>
|
|
1347
|
+
<Typography color="textSecondary" sx={{ fontWeight: 500 }}>UI/UX Design ⢠Development ⢠2024</Typography>
|
|
1348
|
+
</Paper>
|
|
1349
|
+
</Grid>
|
|
1350
|
+
))}
|
|
1351
|
+
</Grid>
|
|
1352
|
+
</Container>
|
|
1353
|
+
</Box>
|
|
1354
|
+
|
|
1355
|
+
{/* Footer */}
|
|
1356
|
+
<Box component="footer" sx={{ py: 8, textAlign: 'center', borderTop: '1px solid #e2e8f0' }}>
|
|
1357
|
+
<Typography color="textSecondary">© 2024 Designer ⢠Built with EreactThohir</Typography>
|
|
1358
|
+
</Box>
|
|
1359
|
+
</Box>
|
|
1360
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
1361
|
+
return (
|
|
1362
|
+
<div className="bg-white text-dark min-vh-100">
|
|
1363
|
+
{/* Hero Section */}
|
|
1364
|
+
<Container className="py-5 text-center" style={{ marginTop: '100px', marginBottom: '100px' }}>
|
|
1365
|
+
<div className="mb-4">
|
|
1366
|
+
<span className="badge rounded-pill bg-primary px-3 py-2 fw-black">Available for hire</span>
|
|
1367
|
+
</div>
|
|
1368
|
+
<h1 className="display-1 fw-black mb-4 tracking-tight">Crafting <span className="text-primary">Digital Experiences</span> that matter.</h1>
|
|
1369
|
+
<p className="lead text-muted mx-auto mb-5" style={{ maxWidth: '800px' }}>I'm a Fullstack Developer specializing in building high-performance web applications with EreactThohir ecosystem.</p>
|
|
1370
|
+
<div className="d-flex justify-content-center gap-3">
|
|
1371
|
+
<Button variant="dark" size="lg" className="px-5 py-3 rounded-pill fw-black shadow-lg">View Projects</Button>
|
|
1372
|
+
<Button variant="outline-dark" size="lg" className="px-5 py-3 rounded-pill fw-black">Contact Me</Button>
|
|
1373
|
+
</div>
|
|
1374
|
+
</Container>
|
|
1375
|
+
|
|
1376
|
+
{/* Projects */}
|
|
1377
|
+
<div className="bg-light py-5">
|
|
1378
|
+
<Container className="py-5">
|
|
1379
|
+
<h2 className="display-5 fw-black mb-5">Selected Works</h2>
|
|
1380
|
+
<Row className="g-5">
|
|
1381
|
+
{[1, 2, 3, 4].map(i => (
|
|
1382
|
+
<Col md={6} key={i}>
|
|
1383
|
+
<div className="project-card cursor-pointer transition-transform" style={{ cursor: 'pointer' }}>
|
|
1384
|
+
<div className="bg-secondary rounded-5 mb-4 shadow-sm" style={{ aspectRatio: '16/9', opacity: 0.1 }}></div>
|
|
1385
|
+
<h3 className="h4 fw-black mb-2">Project Name #{i}</h3>
|
|
1386
|
+
<p className="text-muted fw-bold">UI/UX Design ⢠Development ⢠2024</p>
|
|
1387
|
+
</div>
|
|
1388
|
+
</Col>
|
|
1389
|
+
))}
|
|
1390
|
+
</Row>
|
|
1391
|
+
</Container>
|
|
1392
|
+
</div>
|
|
1393
|
+
|
|
1394
|
+
<footer className="py-5 text-center border-top">
|
|
1395
|
+
<p className="text-muted mb-0">© 2024 Designer ⢠Built with EreactThohir</p>
|
|
1396
|
+
</footer>
|
|
1397
|
+
</div>
|
|
1398
|
+
);` : `
|
|
1148
1399
|
return (
|
|
1149
|
-
<div className="
|
|
1400
|
+
<div className="\${p}min-h-screen \${p}bg-white \${p}text-secondary-900">
|
|
1150
1401
|
{/* Hero Section */}
|
|
1151
|
-
<section className="
|
|
1152
|
-
<div className="
|
|
1153
|
-
<span className="
|
|
1402
|
+
<section className="\${p}py-24 \${p}px-6 \${p}max-w-7xl \${p}mx-auto \${p}text-center">
|
|
1403
|
+
<div className="\${p}mb-8 \${p}animate-pulse">
|
|
1404
|
+
<span className="\${p}px-4 \${p}py-2 \${p}bg-primary-500 \${p}bg-opacity-10 \${p}text-primary-600 \${p}rounded-full \${p}text-sm \${p}font-bold">
|
|
1154
1405
|
Available for hire
|
|
1155
1406
|
</span>
|
|
1156
1407
|
</div>
|
|
1157
|
-
<h1 className="
|
|
1158
|
-
Crafting <span className="
|
|
1408
|
+
<h1 className="\${p}text-7xl \${p}font-black \${p}mb-6 \${p}tracking-tight">
|
|
1409
|
+
Crafting <span className="\${p}gradient-primary \${p}bg-clip-text \${p}text-transparent">Digital Experiences</span> that matter.
|
|
1159
1410
|
</h1>
|
|
1160
|
-
<p className="
|
|
1411
|
+
<p className="\${p}text-2xl \${p}text-secondary-600 \${p}max-w-3xl \${p}mx-auto \${p}mb-12">
|
|
1161
1412
|
I'm a Fullstack Developer specializing in building high-performance web applications with EreactThohir ecosystem.
|
|
1162
1413
|
</p>
|
|
1163
|
-
<div className="
|
|
1164
|
-
<button className="
|
|
1414
|
+
<div className="\${p}flex \${p}justify-center \${p}gap-4">
|
|
1415
|
+
<button className="\${p}px-8 \${p}py-4 \${p}bg-secondary-900 \${p}text-white \${p}rounded-full \${p}font-bold \${p}shadow-xl \${p}hover-scale-105 \${p}transition-all">
|
|
1165
1416
|
View Projects
|
|
1166
1417
|
</button>
|
|
1167
|
-
<button className="
|
|
1418
|
+
<button className="\${p}px-8 \${p}py-4 \${p}border \${p}rounded-full \${p}font-bold \${p}hover-bg-secondary-100 \${p}transition-all">
|
|
1168
1419
|
Contact Me
|
|
1169
1420
|
</button>
|
|
1170
1421
|
</div>
|
|
1171
1422
|
</section>
|
|
1172
1423
|
|
|
1173
1424
|
{/* Projects Grid */}
|
|
1174
|
-
<section className="
|
|
1175
|
-
<div className="
|
|
1176
|
-
<h2 className="
|
|
1177
|
-
<div className="
|
|
1425
|
+
<section className="\${p}py-20 \${p}bg-secondary-50">
|
|
1426
|
+
<div className="\${p}max-w-7xl \${p}mx-auto \${p}px-6">
|
|
1427
|
+
<h2 className="\${p}text-4xl \${p}font-bold \${p}mb-12">Selected Works</h2>
|
|
1428
|
+
<div className="\${p}grid \${p}grid-cols-1 \${p}md-grid-cols-2 \${p}gap-12">
|
|
1178
1429
|
{[1, 2, 3, 4].map(i => (
|
|
1179
|
-
<div key={i} className="
|
|
1180
|
-
<div className="
|
|
1181
|
-
<div className="
|
|
1182
|
-
<div className="
|
|
1430
|
+
<div key={i} className="\${p}group \${p}cursor-pointer">
|
|
1431
|
+
<div className="\${p}aspect-video \${p}bg-secondary-200 \${p}rounded-3xl \${p}mb-6 \${p}overflow-hidden \${p}relative">
|
|
1432
|
+
<div className="\${p}absolute \${p}inset-0 \${p}bg-primary-500 \${p}opacity-0 \${p}group-hover-opacity-10 \${p}transition-all" />
|
|
1433
|
+
<div className="\${p}w-full \${p}h-full \${p}bg-gradient-to-br \${p}from-secondary-200 \${p}to-secondary-300" />
|
|
1183
1434
|
</div>
|
|
1184
|
-
<h3 className="
|
|
1185
|
-
<p className="
|
|
1435
|
+
<h3 className="\${p}text-2xl \${p}font-bold \${p}mb-2">Project Name #\${i}</h3>
|
|
1436
|
+
<p className="\${p}text-secondary-600">UI/UX Design ⢠Development ⢠2024</p>
|
|
1186
1437
|
</div>
|
|
1187
1438
|
))}
|
|
1188
1439
|
</div>
|
|
@@ -1190,16 +1441,18 @@ export default function Portfolio() {
|
|
|
1190
1441
|
</section>
|
|
1191
1442
|
|
|
1192
1443
|
{/* Footer */}
|
|
1193
|
-
<footer className="
|
|
1194
|
-
<p className="
|
|
1444
|
+
<footer className="\${p}py-12 \${p}text-center \${p}border-t">
|
|
1445
|
+
<p className="\${p}text-secondary-500">© 2024 Designer ⢠Built with EreactThohir</p>
|
|
1195
1446
|
</footer>
|
|
1196
1447
|
</div>
|
|
1197
|
-
)
|
|
1448
|
+
);`}
|
|
1198
1449
|
}
|
|
1199
1450
|
`);
|
|
1200
1451
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/portfolio.ts'), `import { Route } from '@ereactthohir/core';
|
|
1201
1452
|
|
|
1202
|
-
Route.get('/portfolio', (req, res) =>
|
|
1453
|
+
Route.get('/portfolio', (req, res) => {
|
|
1454
|
+
return res.view('Portfolio');
|
|
1455
|
+
});
|
|
1203
1456
|
`);
|
|
1204
1457
|
}
|
|
1205
1458
|
/**
|
|
@@ -1400,94 +1653,165 @@ Route.screen('Settings', () => import('../resources/pages/Settings'));
|
|
|
1400
1653
|
* Generate Admin Dashboard template
|
|
1401
1654
|
*/
|
|
1402
1655
|
async function generateAdminDashboardTemplate(projectDir, uiSystem) {
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
const api = axios.create({
|
|
1407
|
-
baseURL: process.env.REACT_APP_API_URL || 'http://localhost:3000/api',
|
|
1408
|
-
});
|
|
1409
|
-
|
|
1410
|
-
api.interceptors.request.use((config) => {
|
|
1411
|
-
const token = localStorage.getItem('auth_token');
|
|
1412
|
-
if (token) config.headers.Authorization = \`Bearer \${token}\`;
|
|
1413
|
-
return config;
|
|
1414
|
-
});
|
|
1415
|
-
|
|
1416
|
-
export default api;
|
|
1417
|
-
`);
|
|
1656
|
+
const h = getUIHelper(uiSystem);
|
|
1657
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1418
1658
|
// Create Admin Store
|
|
1419
1659
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/stores/useAdminStore.ts'), `import { create } from 'zustand';
|
|
1420
1660
|
|
|
1421
1661
|
interface AdminState {
|
|
1422
1662
|
activeMenu: string;
|
|
1423
1663
|
users: any[];
|
|
1424
|
-
products: any[];
|
|
1425
|
-
settings: any;
|
|
1426
1664
|
stats: any;
|
|
1427
|
-
|
|
1428
1665
|
setActiveMenu: (menu: string) => void;
|
|
1429
1666
|
setUsers: (users: any[]) => void;
|
|
1430
|
-
setProducts: (products: any[]) => void;
|
|
1431
|
-
setSettings: (settings: any) => void;
|
|
1432
1667
|
setStats: (stats: any) => void;
|
|
1433
1668
|
}
|
|
1434
1669
|
|
|
1435
1670
|
export const useAdminStore = create<AdminState>((set) => ({
|
|
1436
1671
|
activeMenu: 'dashboard',
|
|
1437
1672
|
users: [],
|
|
1438
|
-
products: [],
|
|
1439
|
-
settings: {},
|
|
1440
1673
|
stats: {},
|
|
1441
|
-
|
|
1442
1674
|
setActiveMenu: (menu) => set({ activeMenu: menu }),
|
|
1443
1675
|
setUsers: (users) => set({ users }),
|
|
1444
|
-
setProducts: (products) => set({ products }),
|
|
1445
|
-
setSettings: (settings) => set({ settings }),
|
|
1446
1676
|
setStats: (stats) => set({ stats }),
|
|
1447
1677
|
}));
|
|
1448
1678
|
`);
|
|
1449
1679
|
// Create Dashboard component
|
|
1450
|
-
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/components/Dashboard.tsx'), `import React
|
|
1451
|
-
import {
|
|
1680
|
+
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/components/Dashboard.tsx'), `import React from 'react';
|
|
1681
|
+
${uiSystem === 'Material UI' ? "import { Box, Typography, Grid, Paper, Stack, Button as MuiButton } from '@mui/material';" : ""}
|
|
1682
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Card, Button as BsButton } from 'react-bootstrap';" : ""}
|
|
1452
1683
|
|
|
1453
1684
|
export default function Dashboard() {
|
|
1454
|
-
|
|
1685
|
+
${uiSystem === 'Material UI' ? `
|
|
1686
|
+
return (
|
|
1687
|
+
<Box sx={{ p: 4, bgcolor: 'background.default', minHeight: '100vh' }}>
|
|
1688
|
+
<Box sx={{ mb: 6, display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
|
|
1689
|
+
<Box>
|
|
1690
|
+
<Typography variant="h3" sx={{ fontWeight: 900, mb: 1 }}>System Overview</Typography>
|
|
1691
|
+
<Typography color="textSecondary">Institutional management dashboard.</Typography>
|
|
1692
|
+
</Box>
|
|
1693
|
+
<MuiButton variant="contained" sx={{ px: 4, py: 1.5, fontWeight: 900, borderRadius: 3 }}>
|
|
1694
|
+
Export Data
|
|
1695
|
+
</MuiButton>
|
|
1696
|
+
</Box>
|
|
1697
|
+
|
|
1698
|
+
<Grid container spacing={3} sx={{ mb: 6 }}>
|
|
1699
|
+
<Grid item xs={12} md={6} lg={3}><StatCard title="Total Users" value="12,482" change="+12%" icon="š„" uiSystem="${uiSystem}" /></Grid>
|
|
1700
|
+
<Grid item xs={12} md={6} lg={3}><StatCard title="Total Sales" value="$48,230" change="+18%" icon="š°" uiSystem="${uiSystem}" /></Grid>
|
|
1701
|
+
<Grid item xs={12} md={6} lg={3}><StatCard title="Active Projects" value="84" change="+3%" icon="ā”" uiSystem="${uiSystem}" /></Grid>
|
|
1702
|
+
<Grid item xs={12} md={6} lg={3}><StatCard title="Server Load" value="23%" change="-2%" icon="š" uiSystem="${uiSystem}" /></Grid>
|
|
1703
|
+
</Grid>
|
|
1704
|
+
|
|
1705
|
+
<Grid container spacing={4}>
|
|
1706
|
+
<Grid item xs={12} lg={8}>
|
|
1707
|
+
<Paper sx={{ p: 4, borderRadius: 6, border: '1px solid #e2e8f0' }} elevation={0}>
|
|
1708
|
+
<Typography variant="h6" sx={{ fontWeight: 900, mb: 4 }}>Performance Trend</Typography>
|
|
1709
|
+
<Box sx={{ height: 350, bgcolor: '#f8fafc', borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center', border: '2px dashed #e2e8f0' }}>
|
|
1710
|
+
<Typography color="textSecondary">Visualization Ready</Typography>
|
|
1711
|
+
</Box>
|
|
1712
|
+
</Paper>
|
|
1713
|
+
</Grid>
|
|
1714
|
+
<Grid item xs={12} lg={4}>
|
|
1715
|
+
<Paper sx={{ p: 4, borderRadius: 6, border: '1px solid #e2e8f0' }} elevation={0}>
|
|
1716
|
+
<Typography variant="h6" sx={{ fontWeight: 900, mb: 4 }}>Recent Alerts</Typography>
|
|
1717
|
+
<Stack spacing={3}>
|
|
1718
|
+
{[1, 2, 3].map(i => (
|
|
1719
|
+
<Box key={i} sx={{ display: 'flex', gap: 2 }}>
|
|
1720
|
+
<Box sx={{ width: 44, height: 44, bgcolor: '#f1f5f9', borderRadius: '50%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>š</Box>
|
|
1721
|
+
<Box>
|
|
1722
|
+
<Typography sx={{ fontWeight: 900, fontSize: '0.875rem' }}>System Update</Typography>
|
|
1723
|
+
<Typography variant="caption" color="textSecondary">v1.2.0 deployed</Typography>
|
|
1724
|
+
</Box>
|
|
1725
|
+
</Box>
|
|
1726
|
+
))}
|
|
1727
|
+
</Stack>
|
|
1728
|
+
</Paper>
|
|
1729
|
+
</Grid>
|
|
1730
|
+
</Grid>
|
|
1731
|
+
</Box>
|
|
1732
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
1733
|
+
return (
|
|
1734
|
+
<Container fluid className="p-5 bg-light min-vh-100">
|
|
1735
|
+
<header className="mb-5 d-flex justify-content-between align-items-end">
|
|
1736
|
+
<div>
|
|
1737
|
+
<h1 className="display-5 fw-black mb-1">System Overview</h1>
|
|
1738
|
+
<p className="text-secondary">Premium Bootstrap Dashboard.</p>
|
|
1739
|
+
</div>
|
|
1740
|
+
<BsButton variant="dark" className="px-4 py-2 rounded-3 fw-bold shadow-sm">
|
|
1741
|
+
Export Data
|
|
1742
|
+
</BsButton>
|
|
1743
|
+
</header>
|
|
1744
|
+
|
|
1745
|
+
<Row className="g-4 mb-5">
|
|
1746
|
+
<Col md={6} lg={3}><StatCard title="Total Users" value="12,482" change="+12%" icon="š„" uiSystem="${uiSystem}" /></Col>
|
|
1747
|
+
<Col md={6} lg={3}><StatCard title="Total Sales" value="$48,230" change="+18%" icon="š°" uiSystem="${uiSystem}" /></Col>
|
|
1748
|
+
<Col md={6} lg={3}><StatCard title="Active Projects" value="84" change="+3%" icon="ā”" uiSystem="${uiSystem}" /></Col>
|
|
1749
|
+
<Col md={6} lg={3}><StatCard title="Server Load" value="23%" change="-2%" icon="š" uiSystem="${uiSystem}" /></Col>
|
|
1750
|
+
</Row>
|
|
1455
1751
|
|
|
1752
|
+
<Row className="g-4">
|
|
1753
|
+
<Col lg={8}>
|
|
1754
|
+
<Card className="border-0 shadow-sm rounded-4 p-4">
|
|
1755
|
+
<h2 className="h5 fw-bold mb-4">Performance Trend</h2>
|
|
1756
|
+
<div className="bg-light rounded-4 border-2 border-dashed d-flex align-items-center justify-content-center" style={{ height: '350px' }}>
|
|
1757
|
+
<p className="text-secondary mb-0">Analytics Engine Active</p>
|
|
1758
|
+
</div>
|
|
1759
|
+
</Card>
|
|
1760
|
+
</Col>
|
|
1761
|
+
<Col lg={4}>
|
|
1762
|
+
<Card className="border-0 shadow-sm rounded-4 p-4">
|
|
1763
|
+
<h2 className="h5 fw-bold mb-4">Recent Alerts</h2>
|
|
1764
|
+
<div className="vstack gap-4">
|
|
1765
|
+
{[1, 2, 3].map(i => (
|
|
1766
|
+
<div key={i} className="d-flex gap-3">
|
|
1767
|
+
<div className="rounded-circle bg-light d-flex align-items-center justify-content-center shadow-inner" style={{ width: '44px', height: '44px' }}>š</div>
|
|
1768
|
+
<div>
|
|
1769
|
+
<p className="small fw-bold mb-0">Security Patch</p>
|
|
1770
|
+
<p className="x-small text-secondary mb-0">System secured</p>
|
|
1771
|
+
</div>
|
|
1772
|
+
</div>
|
|
1773
|
+
))}
|
|
1774
|
+
</div>
|
|
1775
|
+
</Card>
|
|
1776
|
+
</Col>
|
|
1777
|
+
</Row>
|
|
1778
|
+
</Container>
|
|
1779
|
+
);` : `
|
|
1456
1780
|
return (
|
|
1457
|
-
<div className="
|
|
1458
|
-
<header className="
|
|
1781
|
+
<div className="\${p}p-8 \${p}bg-secondary-50 \${p}min-h-screen">
|
|
1782
|
+
<header className="\${p}mb-10 \${p}flex \${p}justify-between \${p}items-end">
|
|
1459
1783
|
<div>
|
|
1460
|
-
<h1 className="
|
|
1461
|
-
<p className="
|
|
1784
|
+
<h1 className="\${p}text-4xl \${p}font-black \${p}mb-2">System Overview</h1>
|
|
1785
|
+
<p className="\${p}text-secondary-600">Premium management dashboard.</p>
|
|
1462
1786
|
</div>
|
|
1463
|
-
<button className="rice-px-6 rice-py-3 rice-bg-secondary-900 rice-text-white rice-rounded-xl rice-font-bold rice-shadow-lg
|
|
1464
|
-
|
|
1787
|
+
<button className="\${h.cls('rice-px-6 rice-py-3 rice-bg-secondary-900 rice-text-white rice-rounded-xl rice-font-bold rice-shadow-lg', 'px-6 py-3 bg-slate-900 text-white rounded-xl font-bold shadow-lg', 'joko-btn joko-btn-primary')}">
|
|
1788
|
+
Export Data
|
|
1465
1789
|
</button>
|
|
1466
1790
|
</header>
|
|
1467
1791
|
|
|
1468
|
-
<div className="
|
|
1469
|
-
<StatCard title="Total Users" value=
|
|
1470
|
-
<StatCard title="Total
|
|
1471
|
-
<StatCard title="
|
|
1472
|
-
<StatCard title="
|
|
1792
|
+
<div className="\${p}grid \${p}grid-cols-1 \${h.cls('rice-md-grid-cols-2 rice-lg-grid-cols-4', 'md:grid-cols-2 lg:grid-cols-4', 'joko-grid-cols-3')} \${p}gap-6 \${p}mb-10">
|
|
1793
|
+
<StatCard title="Total Users" value="12,482" change="+12%" icon="š„" uiSystem="${uiSystem}" />
|
|
1794
|
+
<StatCard title="Total Sales" value="$48,230" change="+18%" icon="š°" uiSystem="${uiSystem}" />
|
|
1795
|
+
<StatCard title="Active Projects" value="84" change="+3%" icon="ā”" uiSystem="${uiSystem}" />
|
|
1796
|
+
<StatCard title="Server Load" value="23%" change="-2%" icon="š" uiSystem="${uiSystem}" />
|
|
1473
1797
|
</div>
|
|
1474
1798
|
|
|
1475
|
-
<div className="
|
|
1476
|
-
<div className="rice-lg-col-span-2 rice-bg-white rice-p-8 rice-rounded-3xl rice-border rice-shadow-sm">
|
|
1477
|
-
<h2 className="
|
|
1478
|
-
<div className="
|
|
1479
|
-
<p className="
|
|
1799
|
+
<div className="\${p}grid \${p}grid-cols-1 \${h.cls('rice-lg-grid-cols-3', 'lg:grid-cols-3', 'joko-grid-cols-1')} \${p}gap-8">
|
|
1800
|
+
<div className="\${h.cls('rice-lg-col-span-2 rice-bg-white rice-p-8 rice-rounded-3xl rice-border rice-shadow-sm', 'lg:col-span-2 bg-white p-8 rounded-3xl border border-slate-200 shadow-sm', 'joko-card')}">
|
|
1801
|
+
<h2 className="\${p}text-xl \${p}font-bold \${p}mb-6">Performance Trend</h2>
|
|
1802
|
+
<div className="\${p}h-80 \${p}bg-secondary-50 \${p}rounded-2xl \${p}border-2 \${p}border-dashed \${p}flex \${p}items-center \${p}justify-center">
|
|
1803
|
+
<p className="\${p}text-secondary-400">Visualization Engine Ready</p>
|
|
1480
1804
|
</div>
|
|
1481
1805
|
</div>
|
|
1482
|
-
<div className="rice-bg-white rice-p-8 rice-rounded-3xl rice-border rice-shadow-sm">
|
|
1483
|
-
<h2 className="
|
|
1484
|
-
<div className="
|
|
1485
|
-
{[1, 2, 3
|
|
1486
|
-
<div key={i} className="
|
|
1487
|
-
<div className="
|
|
1806
|
+
<div className="\${h.cls('rice-bg-white rice-p-8 rice-rounded-3xl rice-border rice-shadow-sm', 'bg-white p-8 rounded-3xl border border-slate-200 shadow-sm', 'joko-card')}">
|
|
1807
|
+
<h2 className="\${p}text-xl \${p}font-bold \${p}mb-6">Recent Alerts</h2>
|
|
1808
|
+
<div className="\${p}space-y-6">
|
|
1809
|
+
{[1, 2, 3].map(i => (
|
|
1810
|
+
<div key={i} className="\${p}flex \${p}gap-4">
|
|
1811
|
+
<div className="\${p}w-10 \${p}h-10 \${p}bg-secondary-100 \${p}rounded-full \${p}flex \${p}items-center \${p}justify-center">š</div>
|
|
1488
1812
|
<div>
|
|
1489
|
-
<p className="
|
|
1490
|
-
<p className="
|
|
1813
|
+
<p className="\${p}text-sm \${p}font-bold">System Update Successful</p>
|
|
1814
|
+
<p className="\${p}text-xs \${p}text-secondary-500">v1.2.0 deployed</p>
|
|
1491
1815
|
</div>
|
|
1492
1816
|
</div>
|
|
1493
1817
|
))}
|
|
@@ -1495,102 +1819,56 @@ export default function Dashboard() {
|
|
|
1495
1819
|
</div>
|
|
1496
1820
|
</div>
|
|
1497
1821
|
</div>
|
|
1498
|
-
)
|
|
1822
|
+
);`}
|
|
1499
1823
|
}
|
|
1500
1824
|
|
|
1501
|
-
function StatCard({ title, value, change, icon,
|
|
1825
|
+
function StatCard({ title, value, change, icon, uiSystem }: any) {
|
|
1826
|
+
${uiSystem === 'Material UI' ? `
|
|
1502
1827
|
return (
|
|
1503
|
-
<
|
|
1504
|
-
<
|
|
1505
|
-
<
|
|
1506
|
-
<
|
|
1828
|
+
<Paper sx={{ p: 3, borderRadius: 5, border: '1px solid #e2e8f0', bgcolor: 'white' }} elevation={0}>
|
|
1829
|
+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
1830
|
+
<Box sx={{ width: 44, height: 44, bgcolor: '#f1f5f9', borderRadius: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 24 }}>{icon}</Box>
|
|
1831
|
+
<Box sx={{ px: 1, py: 0.5, bgcolor: change.startsWith('+') ? '#dcfce7' : '#f1f5f9', color: change.startsWith('+') ? '#166534' : '#64748b', borderRadius: 1.5, fontSize: '0.75rem', fontWeight: 900 }}>{change}</Box>
|
|
1832
|
+
</Box>
|
|
1833
|
+
<Typography variant="body2" color="textSecondary" sx={{ fontWeight: 700, mb: 0.5 }}>{title}</Typography>
|
|
1834
|
+
<Typography variant="h4" sx={{ fontWeight: 900 }}>{value}</Typography>
|
|
1835
|
+
</Paper>
|
|
1836
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
1837
|
+
return (
|
|
1838
|
+
<Card className="border-0 shadow-sm rounded-4 p-4 h-100">
|
|
1839
|
+
<div className="d-flex justify-content-between align-items-center mb-3">
|
|
1840
|
+
<div className="bg-light rounded-3 d-flex align-items-center justify-content-center shadow-inner" style={{ width: '48px', height: '48px', fontSize: '1.5rem' }}>{icon}</div>
|
|
1841
|
+
<span className={\`badge \${change.startsWith('+') ? 'bg-success-soft text-success' : 'bg-light text-secondary'} rounded-pill\`} style={change.startsWith('+') ? { backgroundColor: '#dcfce7' } : {}}>
|
|
1507
1842
|
{change}
|
|
1508
1843
|
</span>
|
|
1509
1844
|
</div>
|
|
1510
|
-
<
|
|
1511
|
-
<
|
|
1512
|
-
</
|
|
1513
|
-
)
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
// Create Users management page
|
|
1517
|
-
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Users.tsx'), `import React, { useEffect } from 'react';
|
|
1518
|
-
import { useAdminStore } from '../stores/useAdminStore';
|
|
1519
|
-
import apiService from '../services/api';
|
|
1520
|
-
|
|
1521
|
-
export default function Users() {
|
|
1522
|
-
const { users, setUsers } = useAdminStore();
|
|
1523
|
-
|
|
1524
|
-
useEffect(() => {
|
|
1525
|
-
loadUsers();
|
|
1526
|
-
}, []);
|
|
1527
|
-
|
|
1528
|
-
const loadUsers = async () => {
|
|
1529
|
-
try {
|
|
1530
|
-
const response = await apiService.get('/admin/users');
|
|
1531
|
-
setUsers(response.data);
|
|
1532
|
-
} catch (error) {
|
|
1533
|
-
console.error('Failed to load users:', error);
|
|
1534
|
-
}
|
|
1535
|
-
};
|
|
1536
|
-
|
|
1845
|
+
<p className="text-secondary small fw-bold mb-1">{title}</p>
|
|
1846
|
+
<h3 className="fw-black mb-0">{value}</h3>
|
|
1847
|
+
</Card>
|
|
1848
|
+
);` : `
|
|
1849
|
+
const h = getUIHelper(uiSystem);
|
|
1850
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1537
1851
|
return (
|
|
1538
|
-
<div className="p-6">
|
|
1539
|
-
<div className="flex justify-between items-
|
|
1540
|
-
<
|
|
1541
|
-
<
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
<div className="bg-white rounded-lg shadow overflow-hidden">
|
|
1545
|
-
<table className="w-full">
|
|
1546
|
-
<thead className="bg-gray-100">
|
|
1547
|
-
<tr>
|
|
1548
|
-
<th className="px-6 py-3 text-left">Name</th>
|
|
1549
|
-
<th className="px-6 py-3 text-left">Email</th>
|
|
1550
|
-
<th className="px-6 py-3 text-left">Role</th>
|
|
1551
|
-
<th className="px-6 py-3 text-left">Status</th>
|
|
1552
|
-
<th className="px-6 py-3 text-left">Actions</th>
|
|
1553
|
-
</tr>
|
|
1554
|
-
</thead>
|
|
1555
|
-
<tbody>
|
|
1556
|
-
{users.map((user) => (
|
|
1557
|
-
<tr key={user.id} className="border-t hover:bg-gray-50">
|
|
1558
|
-
<td className="px-6 py-3">{user.name}</td>
|
|
1559
|
-
<td className="px-6 py-3">{user.email}</td>
|
|
1560
|
-
<td className="px-6 py-3">{user.role}</td>
|
|
1561
|
-
<td className="px-6 py-3">
|
|
1562
|
-
<span className={user.active ? 'text-green-600' : 'text-red-600'}>
|
|
1563
|
-
{user.active ? 'Active' : 'Inactive'}
|
|
1564
|
-
</span>
|
|
1565
|
-
</td>
|
|
1566
|
-
<td className="px-6 py-3">
|
|
1567
|
-
<button className="text-blue-500 hover:underline mr-3">Edit</button>
|
|
1568
|
-
<button className="text-red-500 hover:underline">Delete</button>
|
|
1569
|
-
</td>
|
|
1570
|
-
</tr>
|
|
1571
|
-
))}
|
|
1572
|
-
</tbody>
|
|
1573
|
-
</table>
|
|
1852
|
+
<div className="\${h.cls('rice-bg-white rice-p-6 rice-rounded-3xl rice-border rice-shadow-sm rice-hover-shadow-md rice-transition-all', 'bg-white p-6 rounded-3xl border border-slate-200 shadow-sm hover:shadow-md transition-all', 'joko-card')}">
|
|
1853
|
+
<div className="\${p}flex \${p}justify-between \${p}items-start \${p}mb-4">
|
|
1854
|
+
<div className="\${p}w-12 \${p}h-12 \${p}bg-secondary-50 \${p}rounded-2xl \${p}flex \${p}items-center \${p}justify-center \${p}text-2xl">{icon}</div>
|
|
1855
|
+
<span className=\\\`\${p}text-xs \${p}font-black \${p}px-2 \${p}py-1 \${p}rounded-lg \\\${change.startsWith('+') ? '\${p}text-success-600 \${p}bg-success-600 \${p}bg-opacity-10' : '\${p}text-secondary-600 \${p}bg-secondary-200'}\\\`>
|
|
1856
|
+
{change}
|
|
1857
|
+
</span>
|
|
1574
1858
|
</div>
|
|
1859
|
+
<h3 className="\${p}text-secondary-500 \${p}text-sm \${p}font-medium \${p}mb-1">{title}</h3>
|
|
1860
|
+
<p className="\${p}text-3xl \${p}font-black">{value}</p>
|
|
1575
1861
|
</div>
|
|
1576
|
-
)
|
|
1862
|
+
);`}
|
|
1577
1863
|
}
|
|
1578
|
-
`);
|
|
1579
|
-
// Create admin routes
|
|
1580
|
-
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/admin.ts'), `import { Route } from '@ereactthohir/core';
|
|
1581
|
-
|
|
1582
|
-
Route.middleware(['auth', 'admin']).group(() => {
|
|
1583
|
-
Route.get('/dashboard', 'AdminController@dashboard').name('admin.dashboard');
|
|
1584
|
-
Route.get('/users', 'AdminController@users').name('admin.users');
|
|
1585
|
-
Route.get('/products', 'AdminController@products').name('admin.products');
|
|
1586
|
-
Route.get('/settings', 'AdminController@settings').name('admin.settings');
|
|
1587
|
-
});
|
|
1588
1864
|
`);
|
|
1589
1865
|
}
|
|
1590
1866
|
/**
|
|
1591
1867
|
* Generate Authentication Starter template
|
|
1592
1868
|
*/
|
|
1593
1869
|
async function generateAuthenticationTemplate(projectDir, uiSystem) {
|
|
1870
|
+
const h = getUIHelper(uiSystem);
|
|
1871
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1594
1872
|
// Create Auth store
|
|
1595
1873
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/stores/useAuthStore.ts'), `import { create } from 'zustand';
|
|
1596
1874
|
import apiService from '../services/api';
|
|
@@ -1699,6 +1977,8 @@ export default api;
|
|
|
1699
1977
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Login.tsx'), `import React, { useState } from 'react';
|
|
1700
1978
|
import { useAuthStore } from '../stores/useAuthStore';
|
|
1701
1979
|
import { useNavigate } from 'react-router-dom';
|
|
1980
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, TextField, Button, Paper, Alert, Link } from '@mui/material';" : ""}
|
|
1981
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Card, Form, Button, Alert } from 'react-bootstrap';" : ""}
|
|
1702
1982
|
|
|
1703
1983
|
export default function Login() {
|
|
1704
1984
|
const [email, setEmail] = useState('');
|
|
@@ -1716,67 +1996,127 @@ export default function Login() {
|
|
|
1716
1996
|
}
|
|
1717
1997
|
};
|
|
1718
1998
|
|
|
1999
|
+
${uiSystem === 'Material UI' ? `
|
|
1719
2000
|
return (
|
|
1720
|
-
<
|
|
1721
|
-
<
|
|
1722
|
-
<
|
|
1723
|
-
<
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
)}
|
|
2001
|
+
<Box sx={{ minHeight: '100vh', display: 'flex', alignItems: 'center', bgcolor: '#f8fafc' }}>
|
|
2002
|
+
<Container maxWidth="xs">
|
|
2003
|
+
<Paper sx={{ p: 6, borderRadius: 8, boxShadow: '0 20px 25px -5px rgba(0,0,0,0.1)' }}>
|
|
2004
|
+
<Box sx={{ textAlign: 'center', mb: 4 }}>
|
|
2005
|
+
<Typography variant="h4" sx={{ fontWeight: 900, mb: 1 }}>Welcome Back</Typography>
|
|
2006
|
+
<Typography color="textSecondary">Sign in to your account</Typography>
|
|
2007
|
+
</Box>
|
|
2008
|
+
|
|
2009
|
+
{error && <Alert severity="error" sx={{ mb: 3, borderRadius: 3 }}>{error}</Alert>}
|
|
1730
2010
|
|
|
1731
2011
|
<form onSubmit={handleSubmit}>
|
|
1732
|
-
<
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
2012
|
+
<TextField fullWidth label="Email Address" margin="normal" variant="outlined" value={email} onChange={(e) => setEmail(e.target.value)} sx={{ mb: 2 }} />
|
|
2013
|
+
<TextField fullWidth label="Password" type="password" margin="normal" variant="outlined" value={password} onChange={(e) => setPassword(e.target.value)} sx={{ mb: 4 }} />
|
|
2014
|
+
<Button fullWidth variant="contained" size="large" type="submit" disabled={isLoading} sx={{ py: 1.8, borderRadius: 3, fontWeight: 900, textTransform: 'none', fontSize: '1rem' }}>
|
|
2015
|
+
{isLoading ? 'Decrypting...' : 'Sign In'}
|
|
2016
|
+
</Button>
|
|
2017
|
+
</form>
|
|
2018
|
+
|
|
2019
|
+
<Box sx={{ textAlign: 'center', mt: 4 }}>
|
|
2020
|
+
<Typography color="textSecondary">
|
|
2021
|
+
New here? <Link href="/register" sx={{ fontWeight: 700, textDecoration: 'none' }}>Create an account</Link>
|
|
2022
|
+
</Typography>
|
|
2023
|
+
</Box>
|
|
2024
|
+
</Paper>
|
|
2025
|
+
</Container>
|
|
2026
|
+
</Box>
|
|
2027
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
2028
|
+
return (
|
|
2029
|
+
<div className="bg-light min-vh-100 d-flex align-items-center py-5">
|
|
2030
|
+
<Container>
|
|
2031
|
+
<Card className="border-0 shadow-lg rounded-5 mx-auto" style={{ maxWidth: '450px' }}>
|
|
2032
|
+
<Card.Body className="p-5">
|
|
2033
|
+
<div className="text-center mb-5">
|
|
2034
|
+
<h2 className="fw-black mb-1">Welcome Back</h2>
|
|
2035
|
+
<p className="text-muted">Sign in to your account</p>
|
|
1743
2036
|
</div>
|
|
1744
2037
|
|
|
1745
|
-
<
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
type="
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
className="
|
|
1754
|
-
|
|
1755
|
-
|
|
2038
|
+
{error && <Alert variant="danger" className="rounded-4">{error}</Alert>}
|
|
2039
|
+
|
|
2040
|
+
<Form onSubmit={handleSubmit}>
|
|
2041
|
+
<Form.Group className="mb-4">
|
|
2042
|
+
<Form.Label className="small fw-bold">Email Address</Form.Label>
|
|
2043
|
+
<Form.Control type="email" value={email} onChange={(e) => setEmail(e.target.value)} className="py-3 px-4 rounded-4 border-2" placeholder="name@example.com" />
|
|
2044
|
+
</Form.Group>
|
|
2045
|
+
<Form.Group className="mb-5">
|
|
2046
|
+
<Form.Label className="small fw-bold">Password</Form.Label>
|
|
2047
|
+
<Form.Control type="password" value={password} onChange={(e) => setPassword(e.target.value)} className="py-3 px-4 rounded-4 border-2" placeholder="ā¢ā¢ā¢ā¢ā¢ā¢ā¢ā¢" />
|
|
2048
|
+
</Form.Group>
|
|
2049
|
+
<Button variant="dark" type="submit" disabled={isLoading} className="w-100 py-3 fw-black rounded-4 shadow">
|
|
2050
|
+
{isLoading ? 'Authenticating...' : 'Sign In'}
|
|
2051
|
+
</Button>
|
|
2052
|
+
</Form>
|
|
2053
|
+
|
|
2054
|
+
<div className="text-center mt-4">
|
|
2055
|
+
<p className="text-muted">Don't have an account? <a href="/register" className="fw-bold text-dark">Register</a></p>
|
|
1756
2056
|
</div>
|
|
2057
|
+
</Card.Body>
|
|
2058
|
+
</Card>
|
|
2059
|
+
</Container>
|
|
2060
|
+
</div>
|
|
2061
|
+
);` : `
|
|
2062
|
+
return (
|
|
2063
|
+
<div className="\${p}min-h-screen \${p}flex \${p}items-center \${p}justify-center \${p}bg-secondary-50 \${p}py-12 \${p}px-4">
|
|
2064
|
+
<div className="\${p}max-w-md \${p}w-full \${p}bg-white \${p}p-10 \${p}rounded-[40px] \${p}shadow-2xl \${p}border \${p}border-white">
|
|
2065
|
+
<div className="\${p}text-center \${p}mb-10">
|
|
2066
|
+
<h2 className="\${p}text-4xl \${p}font-black \${p}mb-2">Welcome Back</h2>
|
|
2067
|
+
<p className="\${p}text-secondary-600">Enter your credentials to continue</p>
|
|
2068
|
+
</div>
|
|
1757
2069
|
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
{isLoading ? 'Logging in...' : 'Login'}
|
|
1764
|
-
</button>
|
|
1765
|
-
</form>
|
|
2070
|
+
{error && (
|
|
2071
|
+
<div className="\${p}mb-6 \${p}p-4 \${p}bg-danger-50 \${p}text-danger-600 \${p}rounded-2xl \${p}text-sm \${p}font-bold">
|
|
2072
|
+
{error}
|
|
2073
|
+
</div>
|
|
2074
|
+
)}
|
|
1766
2075
|
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
2076
|
+
<form onSubmit={handleSubmit} className="\${p}space-y-6">
|
|
2077
|
+
<div>
|
|
2078
|
+
<label className="\${p}block \${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2">Email Address</label>
|
|
2079
|
+
<input
|
|
2080
|
+
type="email"
|
|
2081
|
+
value={email}
|
|
2082
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
2083
|
+
className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}transition-all \${p}outline-none \${p}font-bold"
|
|
2084
|
+
placeholder="hello@rice.com"
|
|
2085
|
+
/>
|
|
2086
|
+
</div>
|
|
2087
|
+
<div>
|
|
2088
|
+
<label className="\${p}block \${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2">Password</label>
|
|
2089
|
+
<input
|
|
2090
|
+
type="password"
|
|
2091
|
+
value={password}
|
|
2092
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
2093
|
+
className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}transition-all \${p}outline-none \${p}font-bold"
|
|
2094
|
+
placeholder="ā¢ā¢ā¢ā¢ā¢ā¢ā¢ā¢"
|
|
2095
|
+
/>
|
|
2096
|
+
</div>
|
|
2097
|
+
|
|
2098
|
+
<button
|
|
2099
|
+
type="submit"
|
|
2100
|
+
disabled={isLoading}
|
|
2101
|
+
className="\${p}w-full \${p}py-4 \${p}bg-secondary-900 \${p}text-white \${p}rounded-2xl \${p}font-black \${p}text-lg \${p}shadow-xl \${p}hover-scale-[1.02] \${p}active-scale-95 \${p}transition-all \${p}disabled-opacity-50">
|
|
2102
|
+
{isLoading ? 'Authenticating...' : 'Sign In'}
|
|
2103
|
+
</button>
|
|
2104
|
+
</form>
|
|
2105
|
+
|
|
2106
|
+
<p className="\${p}text-center \${p}mt-10 \${p}text-secondary-600">
|
|
2107
|
+
New here? <a href="/register" className="\${p}text-primary-500 \${p}font-black \${p}hover-underline">Create an account</a>
|
|
2108
|
+
</p>
|
|
1771
2109
|
</div>
|
|
1772
2110
|
</div>
|
|
1773
|
-
)
|
|
2111
|
+
);`}
|
|
1774
2112
|
}
|
|
1775
2113
|
`);
|
|
1776
2114
|
// Create Register page
|
|
1777
2115
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Register.tsx'), `import React, { useState } from 'react';
|
|
1778
2116
|
import { useAuthStore } from '../stores/useAuthStore';
|
|
1779
2117
|
import { useNavigate } from 'react-router-dom';
|
|
2118
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, TextField, Button, Paper, Alert, Link, Checkbox, FormControlLabel } from '@mui/material';" : ""}
|
|
2119
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Card, Form, Button, Alert } from 'react-bootstrap';" : ""}
|
|
1780
2120
|
|
|
1781
2121
|
export default function Register() {
|
|
1782
2122
|
const [formData, setFormData] = useState({ name: '', email: '', password: '', password_confirmation: '' });
|
|
@@ -1797,92 +2137,131 @@ export default function Register() {
|
|
|
1797
2137
|
}
|
|
1798
2138
|
};
|
|
1799
2139
|
|
|
2140
|
+
${uiSystem === 'Material UI' ? `
|
|
1800
2141
|
return (
|
|
1801
|
-
<
|
|
1802
|
-
<
|
|
1803
|
-
<
|
|
1804
|
-
<
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
)}
|
|
2142
|
+
<Box sx={{ minHeight: '100vh', display: 'flex', alignItems: 'center', bgcolor: '#f8fafc', py: 8 }}>
|
|
2143
|
+
<Container maxWidth="xs">
|
|
2144
|
+
<Paper sx={{ p: 6, borderRadius: 8, boxShadow: '0 20px 25px -5px rgba(0,0,0,0.1)' }}>
|
|
2145
|
+
<Box sx={{ textAlign: 'center', mb: 4 }}>
|
|
2146
|
+
<Typography variant="h4" sx={{ fontWeight: 900, mb: 1 }}>Sign Up</Typography>
|
|
2147
|
+
<Typography color="textSecondary">Create your free account</Typography>
|
|
2148
|
+
</Box>
|
|
2149
|
+
|
|
2150
|
+
{error && <Alert severity="error" sx={{ mb: 3, borderRadius: 3 }}>{error}</Alert>}
|
|
1811
2151
|
|
|
1812
2152
|
<form onSubmit={handleSubmit}>
|
|
1813
|
-
<
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
</div>
|
|
2153
|
+
<TextField fullWidth label="Full Name" margin="normal" variant="outlined" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} sx={{ mb: 2 }} />
|
|
2154
|
+
<TextField fullWidth label="Email Address" margin="normal" variant="outlined" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} sx={{ mb: 2 }} />
|
|
2155
|
+
<TextField fullWidth label="Password" type="password" margin="normal" variant="outlined" value={formData.password} onChange={(e) => setFormData({...formData, password: e.target.value})} sx={{ mb: 2 }} />
|
|
2156
|
+
<TextField fullWidth label="Confirm Password" type="password" margin="normal" variant="outlined" value={formData.password_confirmation} onChange={(e) => setFormData({...formData, password_confirmation: e.target.value})} sx={{ mb: 4 }} />
|
|
2157
|
+
|
|
2158
|
+
<Button fullWidth variant="contained" size="large" type="submit" disabled={isLoading} sx={{ py: 1.8, borderRadius: 3, fontWeight: 900, textTransform: 'none', fontSize: '1rem' }}>
|
|
2159
|
+
{isLoading ? 'Creating Account...' : 'Get Started'}
|
|
2160
|
+
</Button>
|
|
2161
|
+
</form>
|
|
1823
2162
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
<
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
2163
|
+
<Box sx={{ textAlign: 'center', mt: 4 }}>
|
|
2164
|
+
<Typography color="textSecondary">
|
|
2165
|
+
Already have an account? <Link href="/login" sx={{ fontWeight: 700, textDecoration: 'none' }}>Sign in here</Link>
|
|
2166
|
+
</Typography>
|
|
2167
|
+
</Box>
|
|
2168
|
+
</Paper>
|
|
2169
|
+
</Container>
|
|
2170
|
+
</Box>
|
|
2171
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
2172
|
+
return (
|
|
2173
|
+
<div className="bg-light min-vh-100 d-flex align-items-center py-5">
|
|
2174
|
+
<Container>
|
|
2175
|
+
<Card className="border-0 shadow-lg rounded-5 mx-auto" style={{ maxWidth: '500px' }}>
|
|
2176
|
+
<Card.Body className="p-5">
|
|
2177
|
+
<div className="text-center mb-5">
|
|
2178
|
+
<h2 className="fw-black mb-1">Create Account</h2>
|
|
2179
|
+
<p className="text-muted">Start your journey with us</p>
|
|
1833
2180
|
</div>
|
|
1834
2181
|
|
|
1835
|
-
<
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
onChange={(e) => setFormData({...formData,
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
2182
|
+
{error && <Alert variant="danger" className="rounded-4">{error}</Alert>}
|
|
2183
|
+
|
|
2184
|
+
<Form onSubmit={handleSubmit}>
|
|
2185
|
+
<Form.Group className="mb-3">
|
|
2186
|
+
<Form.Label className="small fw-bold">Full Name</Form.Label>
|
|
2187
|
+
<Form.Control type="text" value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} className="py-3 px-4 rounded-4 border-2" />
|
|
2188
|
+
</Form.Group>
|
|
2189
|
+
<Form.Group className="mb-3">
|
|
2190
|
+
<Form.Label className="small fw-bold">Email Address</Form.Label>
|
|
2191
|
+
<Form.Control type="email" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} className="py-3 px-4 rounded-4 border-2" />
|
|
2192
|
+
</Form.Group>
|
|
2193
|
+
<Form.Group className="mb-3">
|
|
2194
|
+
<Form.Label className="small fw-bold">Password</Form.Label>
|
|
2195
|
+
<Form.Control type="password" value={formData.password} onChange={(e) => setFormData({...formData, password: e.target.value})} className="py-3 px-4 rounded-4 border-2" />
|
|
2196
|
+
</Form.Group>
|
|
2197
|
+
<Form.Group className="mb-5">
|
|
2198
|
+
<Form.Label className="small fw-bold">Confirm Password</Form.Label>
|
|
2199
|
+
<Form.Control type="password" value={formData.password_confirmation} onChange={(e) => setFormData({...formData, password_confirmation: e.target.value})} className="py-3 px-4 rounded-4 border-2" />
|
|
2200
|
+
</Form.Group>
|
|
2201
|
+
<Button variant="dark" type="submit" disabled={isLoading} className="w-100 py-3 fw-black rounded-4 shadow">
|
|
2202
|
+
{isLoading ? 'Processing...' : 'Register Now'}
|
|
2203
|
+
</Button>
|
|
2204
|
+
</Form>
|
|
2205
|
+
|
|
2206
|
+
<div className="text-center mt-4">
|
|
2207
|
+
<p className="text-muted mb-0">Member already? <a href="/login" className="fw-bold text-dark">Login instead</a></p>
|
|
1844
2208
|
</div>
|
|
2209
|
+
</Card.Body>
|
|
2210
|
+
</Card>
|
|
2211
|
+
</Container>
|
|
2212
|
+
</div>
|
|
2213
|
+
);` : `
|
|
2214
|
+
return (
|
|
2215
|
+
<div className="\${p}min-h-screen \${p}flex \${p}items-center \${p}justify-center \${p}bg-secondary-50 \${p}py-20 \${p}px-4">
|
|
2216
|
+
<div className="\${p}max-w-md \${p}w-full \${p}bg-white \${p}p-10 \${p}rounded-[40px] \${p}shadow-2xl \${p}border \${p}border-white">
|
|
2217
|
+
<div className="\${p}text-center \${p}mb-10">
|
|
2218
|
+
<h2 className="\${p}text-4xl \${p}font-black \${p}mb-2">Get Started</h2>
|
|
2219
|
+
<p className="\${p}text-secondary-600">Join our premium community today</p>
|
|
2220
|
+
</div>
|
|
1845
2221
|
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
onChange={(e) => setFormData({...formData, password_confirmation: e.target.value})}
|
|
1852
|
-
className="w-full px-4 py-2 border rounded-lg focus:outline-none focus:border-blue-500"
|
|
1853
|
-
required
|
|
1854
|
-
/>
|
|
1855
|
-
</div>
|
|
2222
|
+
{error && (
|
|
2223
|
+
<div className="\${p}mb-6 \${p}p-4 \${p}bg-danger-50 \${p}text-danger-600 \${p}rounded-2xl \${p}text-sm \${p}font-bold">
|
|
2224
|
+
{error}
|
|
2225
|
+
</div>
|
|
2226
|
+
)}
|
|
1856
2227
|
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
</
|
|
1864
|
-
|
|
2228
|
+
<form onSubmit={handleSubmit} className="\${p}space-y-5">
|
|
2229
|
+
<div>
|
|
2230
|
+
<label className="\${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2 \${p}block">Name</label>
|
|
2231
|
+
<input type="text" className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}outline-none \${p}font-bold" placeholder="Dhafa N." value={formData.name} onChange={(e) => setFormData({...formData, name: e.target.value})} required />
|
|
2232
|
+
</div>
|
|
2233
|
+
<div>
|
|
2234
|
+
<label className="\${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2 \${p}block">Email</label>
|
|
2235
|
+
<input type="email" className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}outline-none \${p}font-bold" placeholder="name@example.com" value={formData.email} onChange={(e) => setFormData({...formData, email: e.target.value})} required />
|
|
2236
|
+
</div>
|
|
2237
|
+
<div>
|
|
2238
|
+
<label className="\${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2 \${p}block">Password</label>
|
|
2239
|
+
<input type="password" className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}outline-none \${p}font-bold" placeholder="ā¢ā¢ā¢ā¢ā¢ā¢ā¢ā¢" value={formData.password} onChange={(e) => setFormData({...formData, password: e.target.value})} required />
|
|
2240
|
+
</div>
|
|
2241
|
+
<div>
|
|
2242
|
+
<label className="\${p}text-xs \${p}font-black \${p}text-secondary-500 \${p}uppercase \${p}tracking-widest \${p}mb-2 \${p}block">Confirm Password</label>
|
|
2243
|
+
<input type="password" className="\${p}w-full \${p}px-6 \${p}py-4 \${p}bg-secondary-50 \${p}border-2 \${p}border-transparent \${p}focus-border-primary-500 \${p}rounded-2xl \${p}outline-none \${p}font-bold" placeholder="ā¢ā¢ā¢ā¢ā¢ā¢ā¢ā¢" value={formData.password_confirmation} onChange={(e) => setFormData({...formData, password_confirmation: e.target.value})} required />
|
|
2244
|
+
</div>
|
|
2245
|
+
|
|
2246
|
+
<button type="submit" disabled={isLoading} className="\${p}w-full \${p}py-4 \${p}bg-secondary-900 \${p}text-white \${p}rounded-2xl \${p}font-black \${p}text-lg \${p}shadow-xl \${p}hover-scale-[1.02] \${p}active-scale-95 \${p}transition-all \${p}mt-4">
|
|
2247
|
+
{isLoading ? 'Processing...' : 'Create Account'}
|
|
2248
|
+
</button>
|
|
2249
|
+
</form>
|
|
1865
2250
|
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
</div>
|
|
2251
|
+
<p className="\${p}text-center \${p}mt-10 \${p}text-secondary-600">
|
|
2252
|
+
Already have an account? <a href="/login" className="\${p}text-primary-500 \${p}font-black \${p}hover-underline">Sign in</a>
|
|
2253
|
+
</p>
|
|
1870
2254
|
</div>
|
|
1871
2255
|
</div>
|
|
1872
|
-
)
|
|
2256
|
+
);`}
|
|
1873
2257
|
}
|
|
1874
2258
|
`);
|
|
1875
2259
|
// Create auth routes
|
|
1876
2260
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/auth.ts'), `import { Route } from '@ereactthohir/core';
|
|
1877
2261
|
|
|
1878
|
-
Route.
|
|
1879
|
-
Route.
|
|
1880
|
-
|
|
1881
|
-
Route.get('/register', 'AuthController@showRegister').name('register');
|
|
1882
|
-
Route.post('/register', 'AuthController@register').name('register.store');
|
|
1883
|
-
|
|
1884
|
-
Route.middleware(['auth']).group(() => {
|
|
1885
|
-
Route.post('/logout', 'AuthController@logout').name('logout');
|
|
2262
|
+
Route.group({ prefix: '/auth' }, () => {
|
|
2263
|
+
Route.get('/login', (req, res) => res.view('Login'));
|
|
2264
|
+
Route.get('/register', (req, res) => res.view('Register'));
|
|
1886
2265
|
});
|
|
1887
2266
|
`);
|
|
1888
2267
|
}
|
|
@@ -1890,6 +2269,8 @@ Route.middleware(['auth']).group(() => {
|
|
|
1890
2269
|
* Generate Enterprise App Template
|
|
1891
2270
|
*/
|
|
1892
2271
|
async function generateEnterpriseTemplate(projectDir, uiSystem) {
|
|
2272
|
+
const h = getUIHelper(uiSystem);
|
|
2273
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
1893
2274
|
// Create API service with advanced interceptors
|
|
1894
2275
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/services/api.ts'), `import axios, { AxiosInstance } from 'axios';
|
|
1895
2276
|
|
|
@@ -2019,69 +2400,163 @@ export const useEnterpriseStore = create<EnterpriseState>()(
|
|
|
2019
2400
|
)
|
|
2020
2401
|
);
|
|
2021
2402
|
`);
|
|
2022
|
-
// Create
|
|
2023
|
-
await fs_extra_1.default.
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
}
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2403
|
+
// Create Dashboard page
|
|
2404
|
+
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Dashboard.tsx'), `import React from 'react';
|
|
2405
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, Grid, Paper, IconButton, Avatar, Card, CardContent } from '@mui/material';" : ""}
|
|
2406
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Card, Nav, Navbar } from 'react-bootstrap';" : ""}
|
|
2407
|
+
|
|
2408
|
+
export default function Dashboard() {
|
|
2409
|
+
${uiSystem === 'Material UI' ? `
|
|
2410
|
+
return (
|
|
2411
|
+
<Box sx={{ display: 'flex', minHeight: '100vh', bgcolor: '#f1f5f9' }}>
|
|
2412
|
+
<Box sx={{ flexGrow: 1, p: 4 }}>
|
|
2413
|
+
<Container maxWidth="xl">
|
|
2414
|
+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 6 }}>
|
|
2415
|
+
<Box>
|
|
2416
|
+
<Typography variant="h4" sx={{ fontWeight: 900, mb: 1 }}>Enterprise Dashboard</Typography>
|
|
2417
|
+
<Typography color="textSecondary">Welcome back, Admin</Typography>
|
|
2418
|
+
</Box>
|
|
2419
|
+
<Avatar sx={{ width: 48, height: 48, bgcolor: 'primary.main' }}>AD</Avatar>
|
|
2420
|
+
</Box>
|
|
2421
|
+
|
|
2422
|
+
<Grid container spacing={4}>
|
|
2423
|
+
{[1, 2, 3, 4].map(i => (
|
|
2424
|
+
<Grid item xs={12} sm={6} md={3} key={i}>
|
|
2425
|
+
<Paper sx={{ p: 4, borderRadius: 6, boxShadow: '0 4px 6px -1px rgba(0,0,0,0.1)' }}>
|
|
2426
|
+
<Typography color="textSecondary" sx={{ fontWeight: 700, mb: 1 }}>Metric \${i}</Typography>
|
|
2427
|
+
<Typography variant="h3" sx={{ fontWeight: 900 }}>\${(Math.random() * 100).toFixed(0)}%</Typography>
|
|
2428
|
+
</Paper>
|
|
2429
|
+
</Grid>
|
|
2430
|
+
))}
|
|
2431
|
+
</Grid>
|
|
2432
|
+
|
|
2433
|
+
<Paper sx={{ mt: 6, p: 4, borderRadius: 6 }}>
|
|
2434
|
+
<Typography variant="h6" sx={{ fontWeight: 900, mb: 4 }}>Recent Activities</Typography>
|
|
2435
|
+
<Box sx={{ height: 400, bgcolor: '#f8fafc', borderRadius: 4, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
|
2436
|
+
<Typography color="textSecondary">Performance Data Visualization</Typography>
|
|
2437
|
+
</Box>
|
|
2438
|
+
</Paper>
|
|
2439
|
+
</Container>
|
|
2440
|
+
</Box>
|
|
2441
|
+
</Box>
|
|
2442
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
2443
|
+
return (
|
|
2444
|
+
<div className="bg-light min-vh-100 pb-5">
|
|
2445
|
+
<Navbar bg="white" className="border-bottom py-3 mb-5">
|
|
2446
|
+
<Container>
|
|
2447
|
+
<Navbar.Brand className="fw-black fs-4">ENTERPRISE OS</Navbar.Brand>
|
|
2448
|
+
<Nav className="ms-auto flex-row gap-4 align-items-center">
|
|
2449
|
+
<Nav.Link href="#" className="fw-bold">Settings</Nav.Link>
|
|
2450
|
+
<div className="bg-dark text-white rounded-circle d-flex align-items-center justify-content-center" style={{ width: '40px', height: '40px' }}>A</div>
|
|
2451
|
+
</Nav>
|
|
2452
|
+
</Container>
|
|
2453
|
+
</Navbar>
|
|
2454
|
+
|
|
2455
|
+
<Container>
|
|
2456
|
+
<div className="mb-5">
|
|
2457
|
+
<h2 className="fw-black mb-1">Corporate Insights</h2>
|
|
2458
|
+
<p className="text-muted">Analyzing organizational metrics in real-time</p>
|
|
2459
|
+
</div>
|
|
2044
2460
|
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2461
|
+
<Row className="g-4 mb-5">
|
|
2462
|
+
{[1, 2, 3, 4].map(i => (
|
|
2463
|
+
<Col md={3} key={i}>
|
|
2464
|
+
<Card className="border-0 shadow-sm rounded-4 p-3">
|
|
2465
|
+
<Card.Body>
|
|
2466
|
+
<h6 className="text-muted fw-bold mb-3 uppercase small tracking-wider">KPI \${i}</h6>
|
|
2467
|
+
<h2 className="fw-black mb-0">\${(Math.random() * 10).toFixed(1)}M</h2>
|
|
2468
|
+
</Card.Body>
|
|
2469
|
+
</Card>
|
|
2470
|
+
</Col>
|
|
2471
|
+
))}
|
|
2472
|
+
</Row>
|
|
2049
2473
|
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2474
|
+
<Card className="border-0 shadow-sm rounded-5 overflow-hidden">
|
|
2475
|
+
<Card.Body className="p-0">
|
|
2476
|
+
<div className="p-4 border-bottom d-flex justify-content-between">
|
|
2477
|
+
<h5 className="mb-0 fw-black">Enterprise Resource Distribution</h5>
|
|
2478
|
+
</div>
|
|
2479
|
+
<div className="bg-white p-5 text-center" style={{ height: '400px' }}>
|
|
2480
|
+
<div className="bg-light w-100 h-100 rounded-5 d-flex align-items-center justify-content-center border-dashed">
|
|
2481
|
+
<p className="text-muted mb-0">Graphic Layer (Chart.js / D3)</p>
|
|
2482
|
+
</div>
|
|
2483
|
+
</div>
|
|
2484
|
+
</Card.Body>
|
|
2485
|
+
</Card>
|
|
2486
|
+
</Container>
|
|
2487
|
+
</div>
|
|
2488
|
+
);` : `
|
|
2489
|
+
return (
|
|
2490
|
+
<div className="\${p}min-h-screen \${p}bg-secondary-50 \${p}flex">
|
|
2491
|
+
{/* Sidebar */}
|
|
2492
|
+
<div className="\${p}w-72 \${p}bg-secondary-900 \${p}text-white \${p}p-8 \${p}flex \${p}flex-col">
|
|
2493
|
+
<div className="\${p}text-2xl \${p}font-black \${p}mb-12 \${p}tracking-tighter">ERECT_ENT</div>
|
|
2494
|
+
<div className="\${p}space-y-4 \${p}flex-1">
|
|
2495
|
+
<div className="\${p}px-4 \${p}py-3 \${p}bg-primary-500 \${p}rounded-2xl \${p}font-black">Overview</div>
|
|
2496
|
+
<div className="\${p}px-4 \${p}py-3 \${p}text-secondary-400 \${p}hover-text-white \${p}transition-colors">Team</div>
|
|
2497
|
+
<div className="\${p}px-4 \${p}py-3 \${p}text-secondary-400 \${p}hover-text-white \${p}transition-colors">Compliance</div>
|
|
2498
|
+
<div className="\${p}px-4 \${p}py-3 \${p}text-secondary-400 \${p}hover-text-white \${p}transition-colors">Financials</div>
|
|
2499
|
+
</div>
|
|
2500
|
+
<div className="\${p}pt-8 \${p}border-t \${p}border-secondary-800">
|
|
2501
|
+
<div className="\${p}flex \${p}items-center \${p}gap-4">
|
|
2502
|
+
<div className="\${p}w-10 \${p}h-10 \${p}bg-secondary-700 \${p}rounded-full"></div>
|
|
2503
|
+
<div>
|
|
2504
|
+
<div className="\${p}text-sm \${p}font-black">Dhafa Thohir</div>
|
|
2505
|
+
<div className="\${p}text-xs \${p}text-secondary-500">CEO</div>
|
|
2506
|
+
</div>
|
|
2507
|
+
</div>
|
|
2508
|
+
</div>
|
|
2509
|
+
</div>
|
|
2510
|
+
|
|
2511
|
+
{/* Main Content */}
|
|
2512
|
+
<div className="\${p}flex-1 \${p}p-12 \${p}overflow-y-auto">
|
|
2513
|
+
<header className="\${p}flex \${p}justify-between \${p}items-end \${p}mb-12">
|
|
2514
|
+
<div>
|
|
2515
|
+
<h1 className="\${p}text-4xl \${p}font-black \${p}mb-2">Operational Hub</h1>
|
|
2516
|
+
<p className="\${p}text-secondary-500">Global system status: <span className="\${p}text-success-500 \${p}font-black">OPTIMAL</span></p>
|
|
2517
|
+
</div>
|
|
2518
|
+
<button className="\${p}px-6 \${p}py-3 \${p}bg-white \${p}border-2 \${p}border-secondary-200 \${p}rounded-2xl \${p}font-black \${p}hover-border-secondary-900 \${p}transition-all">
|
|
2519
|
+
Report Sync
|
|
2520
|
+
</button>
|
|
2521
|
+
</header>
|
|
2522
|
+
|
|
2523
|
+
<div className="\${p}grid \${p}grid-cols-3 \${p}gap-8 \${p}mb-8">
|
|
2524
|
+
<div className="\${p}p-8 \${p}bg-white \${p}rounded-[32px] \${p}shadow-sm \${p}border \${p}border-secondary-100">
|
|
2525
|
+
<div className="\${p}text-secondary-400 \${p}text-xs \${p}font-black \${p}uppercase \${p}tracking-widest \${p}mb-2">Total Equity</div>
|
|
2526
|
+
<div className="\${p}text-3xl \${p}font-black">$2.4M</div>
|
|
2527
|
+
</div>
|
|
2528
|
+
<div className="\${p}p-8 \${p}bg-white \${p}rounded-[32px] \${p}shadow-sm \${p}border \${p}border-secondary-100">
|
|
2529
|
+
<div className="\${p}text-secondary-400 \${p}text-xs \${p}font-black \${p}uppercase \${p}tracking-widest \${p}mb-2">Active Nodes</div>
|
|
2530
|
+
<div className="\${p}text-3xl \${p}font-black">104</div>
|
|
2531
|
+
</div>
|
|
2532
|
+
<div className="\${p}p-8 \${p}bg-white \${p}rounded-[32px] \${p}shadow-sm \${p}border \${p}border-secondary-100">
|
|
2533
|
+
<div className="\${p}text-secondary-400 \${p}text-xs \${p}font-black \${p}uppercase \${p}tracking-widest \${p}mb-2">Compliance Score</div>
|
|
2534
|
+
<div className="\${p}text-3xl \${p}font-black">98.2</div>
|
|
2535
|
+
</div>
|
|
2536
|
+
</div>
|
|
2062
2537
|
|
|
2063
|
-
|
|
2538
|
+
<div className="\${p}bg-white \${p}rounded-[40px] \${p}p-10 \${p}shadow-sm \${p}border \${p}border-secondary-100">
|
|
2539
|
+
<div className="\${p}flex \${p}justify-between \${p}items-center \${p}mb-8">
|
|
2540
|
+
<h2 className="\${p}text-xl \${p}font-black">Strategic Performance Matrix</h2>
|
|
2541
|
+
<div className="\${p}flex \${p}gap-2">
|
|
2542
|
+
<div className="\${p}w-3 \${p}h-3 \${p}bg-primary-500 \${p}rounded-full"></div>
|
|
2543
|
+
<div className="\${p}w-3 \${p}h-3 \${p}bg-secondary-200 \${p}rounded-full"></div>
|
|
2544
|
+
</div>
|
|
2545
|
+
</div>
|
|
2546
|
+
<div className="\${p}w-full \${p}h-96 \${p}bg-secondary-50 \${p}rounded-[32px] \${p}flex \${p}items-center \${p}justify-center \${p}border-2 \${p}border-dashed \${p}border-secondary-200">
|
|
2547
|
+
<p className="\${p}text-secondary-400 \${p}font-bold">Real-time Visualization Engine</p>
|
|
2548
|
+
</div>
|
|
2549
|
+
</div>
|
|
2550
|
+
</div>
|
|
2551
|
+
</div>
|
|
2552
|
+
);`}
|
|
2064
2553
|
}
|
|
2065
2554
|
`);
|
|
2066
2555
|
// Create main routes
|
|
2067
2556
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'routes/enterprise.ts'), `import { Route } from '@ereactthohir/core';
|
|
2068
2557
|
|
|
2069
|
-
Route.middleware(['auth'
|
|
2070
|
-
|
|
2071
|
-
Route.get('/dashboard', 'DashboardController@index').name('dashboard');
|
|
2072
|
-
|
|
2073
|
-
// Users Management
|
|
2074
|
-
Route.get('/users', 'UserController@index').name('users.index');
|
|
2075
|
-
Route.get('/users/create', 'UserController@create').name('users.create');
|
|
2076
|
-
Route.post('/users', 'UserController@store').name('users.store');
|
|
2077
|
-
Route.get('/users/:id', 'UserController@show').name('users.show');
|
|
2078
|
-
Route.get('/users/:id/edit', 'UserController@edit').name('users.edit');
|
|
2079
|
-
Route.put('/users/:id', 'UserController@update').name('users.update');
|
|
2080
|
-
Route.delete('/users/:id', 'UserController@destroy').name('users.destroy');
|
|
2081
|
-
|
|
2082
|
-
// Settings
|
|
2083
|
-
Route.get('/settings', 'SettingsController@index').name('settings');
|
|
2084
|
-
Route.put('/settings', 'SettingsController@update').name('settings.update');
|
|
2558
|
+
Route.middleware(['auth']).group(() => {
|
|
2559
|
+
Route.get('/dashboard', (req, res) => res.view('Dashboard'));
|
|
2085
2560
|
});
|
|
2086
2561
|
`);
|
|
2087
2562
|
}
|
|
@@ -2089,6 +2564,8 @@ Route.middleware(['auth', 'verified']).group(() => {
|
|
|
2089
2564
|
* Generate SaaS Template
|
|
2090
2565
|
*/
|
|
2091
2566
|
async function generateSaaSTemplate(projectDir, uiSystem) {
|
|
2567
|
+
const h = getUIHelper(uiSystem);
|
|
2568
|
+
const p = h.cls('rice-', '', 'joko-');
|
|
2092
2569
|
// Create subscription service
|
|
2093
2570
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/services/subscription.ts'), `import apiService from './api';
|
|
2094
2571
|
|
|
@@ -2212,6 +2689,8 @@ export const useSaaSStore = create<SaaSState>((set) => ({
|
|
|
2212
2689
|
`);
|
|
2213
2690
|
// Create Pricing page
|
|
2214
2691
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/pages/Pricing.tsx'), `import React, { useState } from 'react';
|
|
2692
|
+
${uiSystem === 'Material UI' ? "import { Box, Container, Typography, Button, Grid, Card, List, ListItem, ListItemIcon, ListItemText, Switch, Stack } from '@mui/material';" : ""}
|
|
2693
|
+
${uiSystem === 'Bootstrap 5' ? "import { Container, Row, Col, Card, Button, Form } from 'react-bootstrap';" : ""}
|
|
2215
2694
|
|
|
2216
2695
|
const plans = [
|
|
2217
2696
|
{ id: 1, name: 'Basic', description: 'Perfect for side projects and small experiments.', price: '$0', featured: false, features: ['1 Project', '1,000 requests/mo', 'Basic Support', 'Community Access'] },
|
|
@@ -2222,66 +2701,138 @@ const plans = [
|
|
|
2222
2701
|
export default function Pricing() {
|
|
2223
2702
|
const [billing, setBilling] = useState<'monthly' | 'yearly'>('monthly');
|
|
2224
2703
|
|
|
2704
|
+
${uiSystem === 'Material UI' ? `
|
|
2705
|
+
return (
|
|
2706
|
+
<Box sx={{ minHeight: '100vh', bgcolor: '#f8fafc', py: 15 }}>
|
|
2707
|
+
<Container>
|
|
2708
|
+
<Box sx={{ textAlign: 'center', mb: 10 }}>
|
|
2709
|
+
<Typography variant="h2" sx={{ fontWeight: 900, mb: 2, tracking: -2 }}>
|
|
2710
|
+
Scale your <Box component="span" sx={{ color: 'primary.main' }}>Ideas</Box>.
|
|
2711
|
+
</Typography>
|
|
2712
|
+
<Typography color="textSecondary" sx={{ fontSize: '1.2rem', maxW: 600, mx: 'auto', mb: 6 }}>
|
|
2713
|
+
Choose a plan that scales with your growth. No hidden fees.
|
|
2714
|
+
</Typography>
|
|
2715
|
+
<Stack direction="row" spacing={2} justifyContent="center" alignItems="center">
|
|
2716
|
+
<Typography sx={{ fontWeight: 700 }}>Monthly</Typography>
|
|
2717
|
+
<Switch checked={billing === 'yearly'} onChange={() => setBilling(billing === 'monthly' ? 'yearly' : 'monthly')} />
|
|
2718
|
+
<Typography sx={{ fontWeight: 700 }}>Yearly <Box component="span" sx={{ color: 'success.main' }}>-20%</Box></Typography>
|
|
2719
|
+
</Stack>
|
|
2720
|
+
</Box>
|
|
2721
|
+
|
|
2722
|
+
<Grid container spacing={4} alignItems="center">
|
|
2723
|
+
{plans.map((plan) => (
|
|
2724
|
+
<Grid item xs={12} md={4} key={plan.id}>
|
|
2725
|
+
<Card sx={{ p: 5, borderRadius: 10, border: plan.featured ? '2px solid' : 'none', borderColor: 'primary.main', transform: plan.featured ? 'scale(1.05)' : 'none', boxShadow: '0 20px 25px -5px rgba(0,0,0,0.1)' }}>
|
|
2726
|
+
<Typography variant="h5" sx={{ fontWeight: 900, mb: 1 }}>{plan.name}</Typography>
|
|
2727
|
+
<Typography color="textSecondary" sx={{ mb: 4, height: 60 }}>{plan.description}</Typography>
|
|
2728
|
+
<Box sx={{ display: 'flex', alignItems: 'baseline', mb: 4 }}>
|
|
2729
|
+
<Typography variant="h3" sx={{ fontWeight: 900 }}>{plan.price}</Typography>
|
|
2730
|
+
<Typography color="textSecondary" sx={{ ml: 1, fontWeight: 700 }}>/mo</Typography>
|
|
2731
|
+
</Box>
|
|
2732
|
+
<Button fullWidth variant={plan.featured ? "contained" : "outlined"} sx={{ py: 2, borderRadius: 4, fontWeight: 900, mb: 4 }}>Get Started</Button>
|
|
2733
|
+
<List>
|
|
2734
|
+
{plan.features.map(f => (
|
|
2735
|
+
<ListItem key={f} sx={{ px: 0 }}>
|
|
2736
|
+
<ListItemText primary={f} primaryTypographyProps={{ fontWeight: 700, fontSize: '0.9rem' }} />
|
|
2737
|
+
</ListItem>
|
|
2738
|
+
))}
|
|
2739
|
+
</List>
|
|
2740
|
+
</Card>
|
|
2741
|
+
</Grid>
|
|
2742
|
+
))}
|
|
2743
|
+
</Grid>
|
|
2744
|
+
</Container>
|
|
2745
|
+
</Box>
|
|
2746
|
+
);` : uiSystem === 'Bootstrap 5' ? `
|
|
2747
|
+
return (
|
|
2748
|
+
<div className="bg-white min-vh-100 py-5">
|
|
2749
|
+
<Container className="py-5">
|
|
2750
|
+
<div className="text-center mb-5">
|
|
2751
|
+
<h1 className="display-3 fw-black mb-3">Scale your Projects</h1>
|
|
2752
|
+
<p className="lead text-muted mx-auto mb-5" style={{ maxWidth: '600px' }}>Choose a plan that scales with your growth. Simple, transparent pricing.</p>
|
|
2753
|
+
<div className="d-flex justify-content-center align-items-center gap-3">
|
|
2754
|
+
<span className="fw-bold">Monthly</span>
|
|
2755
|
+
<Form.Check type="switch" checked={billing === 'yearly'} onChange={() => setBilling(billing === 'monthly' ? 'yearly' : 'monthly')} />
|
|
2756
|
+
<span className="fw-bold">Yearly <span className="text-success">(Save 20%)</span></span>
|
|
2757
|
+
</div>
|
|
2758
|
+
</div>
|
|
2759
|
+
|
|
2760
|
+
<Row className="g-4 align-items-center">
|
|
2761
|
+
{plans.map(plan => (
|
|
2762
|
+
<Col md={4} key={plan.id}>
|
|
2763
|
+
<Card className={\`border-\${plan.featured ? 'primary' : '0'} shadow-lg rounded-5 p-4 \${plan.featured ? 'scale-105' : ''}\`} style={plan.featured ? { borderWidth: '2px' } : {}}>
|
|
2764
|
+
<Card.Body>
|
|
2765
|
+
<h3 className="fw-black mb-1">{plan.name}</h3>
|
|
2766
|
+
<p className="text-muted mb-4">{plan.description}</p>
|
|
2767
|
+
<div className="d-flex align-items-baseline mb-4">
|
|
2768
|
+
<span className="display-4 fw-black">{plan.price}</span>
|
|
2769
|
+
<span className="text-muted ms-2 fw-bold">/mo</span>
|
|
2770
|
+
</div>
|
|
2771
|
+
<Button variant={plan.featured ? 'primary' : 'outline-dark'} className="w-100 py-3 fw-black rounded-4 mb-4">Get Started</Button>
|
|
2772
|
+
<ul className="list-unstyled">
|
|
2773
|
+
{plan.features.map(f => (
|
|
2774
|
+
<li key={f} className="mb-3 fw-bold text-secondary small">ā {f}</li>
|
|
2775
|
+
))}
|
|
2776
|
+
</ul>
|
|
2777
|
+
</Card.Body>
|
|
2778
|
+
</Card>
|
|
2779
|
+
</Col>
|
|
2780
|
+
))}
|
|
2781
|
+
</Row>
|
|
2782
|
+
</Container>
|
|
2783
|
+
</div>
|
|
2784
|
+
);` : `
|
|
2225
2785
|
return (
|
|
2226
|
-
<div className="
|
|
2227
|
-
<div className="
|
|
2228
|
-
<div className="
|
|
2229
|
-
<h1 className="
|
|
2230
|
-
Scale your <span className="
|
|
2786
|
+
<div className="\${p}min-h-screen \${p}bg-secondary-50 \${p}py-24 \${p}px-6">
|
|
2787
|
+
<div className="\${p}max-w-7xl \${p}mx-auto">
|
|
2788
|
+
<div className="\${p}text-center \${p}mb-16">
|
|
2789
|
+
<h1 className="\${p}text-5xl \${p}md-text-7xl \${p}font-black \${p}tracking-tight \${p}mb-6">
|
|
2790
|
+
Scale your <span className="\${p}gradient-primary \${p}bg-clip-text \${p}text-transparent">Ideas</span>.
|
|
2231
2791
|
</h1>
|
|
2232
|
-
<p className="
|
|
2792
|
+
<p className="\${p}text-xl \${p}text-secondary-600 \${p}max-w-2xl \${p}mx-auto \${p}mb-10">
|
|
2233
2793
|
Choose a plan that scales with your growth. No hidden fees, cancel anytime.
|
|
2234
2794
|
</p>
|
|
2235
2795
|
|
|
2236
2796
|
{/* Billing Toggle */}
|
|
2237
|
-
<div className="
|
|
2797
|
+
<div className="\${p}inline-flex \${p}p-1 \${p}bg-secondary-200 \${p}rounded-2xl \${p}mb-12">
|
|
2238
2798
|
<button
|
|
2239
2799
|
onClick={() => setBilling('monthly')}
|
|
2240
|
-
className={
|
|
2800
|
+
className={\`\${p}px-6 \${p}py-2 \${p}rounded-xl \${p}text-sm \${p}font-bold \${p}transition-all \${billing === 'monthly' ? '\${p}bg-white \${p}shadow-sm' : '\${p}text-secondary-600'}\`}>
|
|
2241
2801
|
Monthly
|
|
2242
2802
|
</button>
|
|
2243
2803
|
<button
|
|
2244
2804
|
onClick={() => setBilling('yearly')}
|
|
2245
|
-
className={
|
|
2246
|
-
Yearly <span className="
|
|
2805
|
+
className={\`\${p}px-6 \${p}py-2 \${p}rounded-xl \${p}text-sm \${p}font-bold \${p}transition-all \${billing === 'yearly' ? '\${p}bg-white \${p}shadow-sm' : '\${p}text-secondary-600'}\`}>
|
|
2806
|
+
Yearly <span className="\${p}text-success-600">-20%</span>
|
|
2247
2807
|
</button>
|
|
2248
2808
|
</div>
|
|
2249
2809
|
</div>
|
|
2250
2810
|
|
|
2251
|
-
<div className="
|
|
2811
|
+
<div className="\${p}grid \${p}grid-cols-1 \${p}md-grid-cols-3 \${p}gap-8">
|
|
2252
2812
|
{plans.map((plan) => (
|
|
2253
|
-
<div key={plan.id} className={
|
|
2254
|
-
{plan.
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
</span>
|
|
2258
|
-
|
|
2259
|
-
<h3 className="rice-text-2xl rice-font-black rice-mb-2">{plan.name}</h3>
|
|
2260
|
-
<p className="rice-text-sm rice-text-secondary-500 rice-mb-8">{plan.description}</p>
|
|
2261
|
-
|
|
2262
|
-
<div className="rice-mb-8">
|
|
2263
|
-
<span className="rice-text-5xl rice-font-black">{plan.price}</span>
|
|
2264
|
-
{plan.price !== 'Custom' && <span className="rice-text-secondary-500 rice-font-medium"> /mo</span>}
|
|
2813
|
+
<div key={plan.id} className={\`\${p}relative \${p}p-10 \${p}bg-white \${p}rounded-[40px] \${p}border-2 \${p}transition-all \${p}hover-shadow-2xl \${plan.featured ? '\${p}border-primary-500 \${p}scale-105 \${p}z-10' : '\${p}border-transparent \${p}shadow-sm'}\`}>
|
|
2814
|
+
<h3 className="\${p}text-2xl \${p}font-black \${p}mb-2">{plan.name}</h3>
|
|
2815
|
+
<p className="\${p}text-secondary-500 \${p}mb-8 \${p}h-12">{plan.description}</p>
|
|
2816
|
+
<div className="\${p}flex \${p}items-baseline \${p}mb-8">
|
|
2817
|
+
<span className="\${p}text-5xl \${p}font-black">{plan.price}</span>
|
|
2818
|
+
<span className="\${p}text-secondary-500 \${p}ml-2 \${p}font-bold">/mo</span>
|
|
2265
2819
|
</div>
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2820
|
+
<button className={\`\${p}w-full \${p}py-4 \${p}rounded-2xl \${p}font-black \${p}transition-all \${p}mb-8 \${plan.featured ? '\${p}bg-primary-500 \${p}text-white \${p}shadow-lg' : '\${p}bg-secondary-900 \${p}text-white'}\`}>
|
|
2821
|
+
Get Started
|
|
2822
|
+
</button>
|
|
2823
|
+
<ul className="\${p}space-y-4">
|
|
2824
|
+
{plan.features.map(f => (
|
|
2825
|
+
<li key={f} className="\${p}flex \${p}items-center \${p}gap-3 \${p}text-sm \${p}font-bold \${p}text-secondary-600">
|
|
2826
|
+
<span className="\${p}text-success-500">ā</span> {f}
|
|
2272
2827
|
</li>
|
|
2273
2828
|
))}
|
|
2274
2829
|
</ul>
|
|
2275
|
-
|
|
2276
|
-
<button className={\`rice-w-full rice-py-4 rice-rounded-2xl rice-font-black rice-transition-all \${plan.featured ? 'rice-bg-primary-500 rice-text-white rice-shadow-lg rice-hover-bg-primary-600' : 'rice-bg-secondary-100 rice-text-secondary-900 rice-hover-bg-secondary-200'}\`}>
|
|
2277
|
-
{plan.price === 'Custom' ? 'Contact Sales' : 'Start Trial'}
|
|
2278
|
-
</button>
|
|
2279
2830
|
</div>
|
|
2280
2831
|
))}
|
|
2281
2832
|
</div>
|
|
2282
2833
|
</div>
|
|
2283
2834
|
</div>
|
|
2284
|
-
)
|
|
2835
|
+
);`}
|
|
2285
2836
|
}
|
|
2286
2837
|
`);
|
|
2287
2838
|
// Create Subscription Management page
|
|
@@ -2589,19 +3140,39 @@ export default function WelcomeComponent() {
|
|
|
2589
3140
|
* Configure Bootstrap 5
|
|
2590
3141
|
*/
|
|
2591
3142
|
async function configureBootstrap(projectDir) {
|
|
3143
|
+
// Create custom bootstrap variations
|
|
3144
|
+
const customBootstrap = `
|
|
3145
|
+
:root {
|
|
3146
|
+
--bs-primary: #0d6efd;
|
|
3147
|
+
--bs-primary-rgb: 13, 110, 253;
|
|
3148
|
+
--bs-border-radius: 1rem;
|
|
3149
|
+
--bs-border-radius-lg: 2rem;
|
|
3150
|
+
--bs-font-sans-serif: 'Inter', system-ui, -apple-system, sans-serif;
|
|
3151
|
+
}
|
|
3152
|
+
.fw-black { font-weight: 900 !important; }
|
|
3153
|
+
.shadow-2xl { shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); }
|
|
3154
|
+
.bg-primary-soft { background-color: rgba(var(--bs-primary-rgb), 0.1) !important; }
|
|
3155
|
+
.rounded-4 { border-radius: 1.5rem !important; }
|
|
3156
|
+
.rounded-5 { border-radius: 2.5rem !important; }
|
|
3157
|
+
`;
|
|
3158
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(projectDir, 'resources/css'));
|
|
3159
|
+
await fs_extra_1.default.appendFile(path_1.default.join(projectDir, 'resources/css/app.css'), customBootstrap);
|
|
2592
3160
|
// Create example component with Bootstrap
|
|
2593
3161
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/views/WelcomeComponent.tsx'), `import React from 'react';
|
|
2594
|
-
import { Container, Row, Col, Button } from 'react-bootstrap';
|
|
3162
|
+
import { Container, Row, Col, Button, Card } from 'react-bootstrap';
|
|
2595
3163
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
2596
3164
|
|
|
2597
3165
|
export default function WelcomeComponent() {
|
|
2598
3166
|
return (
|
|
2599
|
-
<Container className="
|
|
2600
|
-
<Row className="text-center">
|
|
2601
|
-
<Col>
|
|
2602
|
-
<h1 className="display-4 fw-
|
|
2603
|
-
<p className="lead mb-
|
|
2604
|
-
<
|
|
3167
|
+
<Container className="py-5">
|
|
3168
|
+
<Row className="justify-content-center text-center">
|
|
3169
|
+
<Col md={8}>
|
|
3170
|
+
<h1 className="display-4 fw-black mb-4">Bootstrap x EreactThohir</h1>
|
|
3171
|
+
<p className="lead mb-5">Institutional strength meets modern speed.</p>
|
|
3172
|
+
<div className="d-flex gap-3 justify-content-center">
|
|
3173
|
+
<Button variant="primary" size="lg" className="rounded-pill px-5">Get Started</Button>
|
|
3174
|
+
<Button variant="outline-dark" size="lg" className="rounded-pill px-5">Learn More</Button>
|
|
3175
|
+
</div>
|
|
2605
3176
|
</Col>
|
|
2606
3177
|
</Row>
|
|
2607
3178
|
</Container>
|
|
@@ -2613,35 +3184,60 @@ export default function WelcomeComponent() {
|
|
|
2613
3184
|
* Configure Material UI
|
|
2614
3185
|
*/
|
|
2615
3186
|
async function configureMaterialUI(projectDir) {
|
|
3187
|
+
// Create Theme Configuration
|
|
3188
|
+
await fs_extra_1.default.ensureDir(path_1.default.join(projectDir, 'resources/theme'));
|
|
3189
|
+
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/theme/index.ts'), `import { createTheme } from '@mui/material/styles';
|
|
3190
|
+
|
|
3191
|
+
export const theme = createTheme({
|
|
3192
|
+
palette: {
|
|
3193
|
+
primary: { main: '#6366f1', contrastText: '#fff' },
|
|
3194
|
+
secondary: { main: '#f43f5e' },
|
|
3195
|
+
background: { default: '#f8fafc', paper: '#ffffff' },
|
|
3196
|
+
text: { primary: '#0f172a', secondary: '#64748b' }
|
|
3197
|
+
},
|
|
3198
|
+
typography: {
|
|
3199
|
+
fontFamily: '"Outfit", "Inter", sans-serif',
|
|
3200
|
+
h1: { fontWeight: 900 },
|
|
3201
|
+
h2: { fontWeight: 800 },
|
|
3202
|
+
button: { textTransform: 'none', fontWeight: 700 }
|
|
3203
|
+
},
|
|
3204
|
+
shape: { borderRadius: 12 },
|
|
3205
|
+
components: {
|
|
3206
|
+
MuiButton: {
|
|
3207
|
+
styleOverrides: {
|
|
3208
|
+
root: { borderRadius: 12, padding: '10px 24px' }
|
|
3209
|
+
}
|
|
3210
|
+
},
|
|
3211
|
+
MuiPaper: {
|
|
3212
|
+
styleOverrides: {
|
|
3213
|
+
root: { border: '1px solid #e2e8f0', boxShadow: 'none' }
|
|
3214
|
+
}
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
});
|
|
3218
|
+
`);
|
|
2616
3219
|
// Create example component with Material UI
|
|
2617
3220
|
await fs_extra_1.default.writeFile(path_1.default.join(projectDir, 'resources/views/WelcomeComponent.tsx'), `import React from 'react';
|
|
2618
|
-
import { Box, Container, Typography, Button, Stack } from '@mui/material';
|
|
3221
|
+
import { Box, Container, Typography, Button, Stack, Paper } from '@mui/material';
|
|
3222
|
+
import { ThemeProvider } from '@mui/material/styles';
|
|
3223
|
+
import { theme } from '../theme';
|
|
2619
3224
|
|
|
2620
3225
|
export default function WelcomeComponent() {
|
|
2621
3226
|
return (
|
|
2622
|
-
<
|
|
2623
|
-
<
|
|
2624
|
-
sx={{
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
minHeight: '100vh',
|
|
2629
|
-
textAlign: 'center',
|
|
2630
|
-
}}
|
|
2631
|
-
>
|
|
2632
|
-
<Stack spacing={3}>
|
|
2633
|
-
<Typography variant="h1" component="h1">
|
|
2634
|
-
Welcome to EreactThohir
|
|
3227
|
+
<ThemeProvider theme={theme}>
|
|
3228
|
+
<Container maxWidth="md">
|
|
3229
|
+
<Box sx={{ py: 10, textAlign: 'center' }}>
|
|
3230
|
+
<Typography variant="h2" sx={{ mb: 2 }}>Material UI Starter</Typography>
|
|
3231
|
+
<Typography variant="h6" color="textSecondary" sx={{ mb: 4 }}>
|
|
3232
|
+
Powered by institutional strength and Google's Design System.
|
|
2635
3233
|
</Typography>
|
|
2636
|
-
<
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
</Box>
|
|
2644
|
-
</Container>
|
|
3234
|
+
<Stack direction="row" spacing={2} justifyContent="center">
|
|
3235
|
+
<Button variant="contained" size="large">Documentation</Button>
|
|
3236
|
+
<Button variant="outlined" size="large">Github</Button>
|
|
3237
|
+
</Stack>
|
|
3238
|
+
</Box>
|
|
3239
|
+
</Container>
|
|
3240
|
+
</ThemeProvider>
|
|
2645
3241
|
);
|
|
2646
3242
|
}
|
|
2647
3243
|
`);
|
|
@@ -2937,4 +3533,507 @@ export default function WelcomeComponent() {
|
|
|
2937
3533
|
// or we could overwrite the main entry point if we knew where it was.
|
|
2938
3534
|
// For now, we'll just provide the component.
|
|
2939
3535
|
}
|
|
3536
|
+
/**
|
|
3537
|
+
* Generate Welcome Page Content based on UI System
|
|
3538
|
+
*/
|
|
3539
|
+
function generateWelcomePage(uiSystem, name) {
|
|
3540
|
+
if (uiSystem === 'JokoUI')
|
|
3541
|
+
return generateJokoWelcome(name);
|
|
3542
|
+
if (uiSystem === 'Tailwind CSS' || uiSystem === 'DaisyUI' || uiSystem === 'Shadcn/ui')
|
|
3543
|
+
return generateTailwindWelcome(name);
|
|
3544
|
+
if (uiSystem === 'Bootstrap 5')
|
|
3545
|
+
return generateBootstrapWelcome(name);
|
|
3546
|
+
if (uiSystem === 'Material UI')
|
|
3547
|
+
return generateMaterialWelcome(name);
|
|
3548
|
+
return generateRiceWelcome(name);
|
|
3549
|
+
}
|
|
3550
|
+
function generateBootstrapWelcome(name) {
|
|
3551
|
+
return `import React from 'react';
|
|
3552
|
+
import { Container, Row, Col, Button, Nav, Navbar } from 'react-bootstrap';
|
|
3553
|
+
import 'bootstrap/dist/css/bootstrap.min.css';
|
|
3554
|
+
|
|
3555
|
+
export default function Welcome() {
|
|
3556
|
+
return (
|
|
3557
|
+
<div style={{ backgroundColor: '#f8fafc', minHeight: '100vh' }}>
|
|
3558
|
+
<Navbar bg="white" expand="lg" className="py-4 shadow-sm">
|
|
3559
|
+
<Container>
|
|
3560
|
+
<Navbar.Brand href="#" className="fw-black fs-3">
|
|
3561
|
+
<span className="text-primary">E</span>reactThohir
|
|
3562
|
+
</Navbar.Brand>
|
|
3563
|
+
<Navbar.Toggle />
|
|
3564
|
+
<Navbar.Collapse className="justify-content-end">
|
|
3565
|
+
<Nav className="gap-4 fw-bold">
|
|
3566
|
+
<Nav.Link href="#docs">Docs</Nav.Link>
|
|
3567
|
+
<Nav.Link href="#showcase">Showcase</Nav.Link>
|
|
3568
|
+
<Button variant="dark" className="rounded-pill px-4">Get Started</Button>
|
|
3569
|
+
</Nav>
|
|
3570
|
+
</Navbar.Collapse>
|
|
3571
|
+
</Container>
|
|
3572
|
+
</Navbar>
|
|
3573
|
+
|
|
3574
|
+
<Container className="pt-5 mt-5">
|
|
3575
|
+
<Row className="align-items-center">
|
|
3576
|
+
<Col lg={6} className="text-center text-lg-start">
|
|
3577
|
+
<div className="badge bg-primary-soft text-primary px-3 py-2 rounded-pill mb-4" style={{ backgroundColor: '#e0f2fe' }}>
|
|
3578
|
+
NEW VERSION 1.3.5 AVAILABLE
|
|
3579
|
+
</div>
|
|
3580
|
+
<h1 className="display-1 fw-black mb-4 tracking-tight" style={{ lineHeight: 0.9 }}>
|
|
3581
|
+
Modernize <br/>
|
|
3582
|
+
<span className="text-primary">Web Apps.</span>
|
|
3583
|
+
</h1>
|
|
3584
|
+
<p className="lead text-secondary mb-5 fs-4">
|
|
3585
|
+
The ultimate Bootstrap 5 starter for EReactThohir.
|
|
3586
|
+
Clean, fast, and extraordinarily powerful.
|
|
3587
|
+
</p>
|
|
3588
|
+
<div className="d-flex gap-3 justify-content-center justify-content-lg-start">
|
|
3589
|
+
<Button variant="primary" size="lg" className="px-5 py-3 rounded-4 shadow-lg fw-bold">
|
|
3590
|
+
Start Building
|
|
3591
|
+
</Button>
|
|
3592
|
+
<Button variant="outline-dark" size="lg" className="px-5 py-3 rounded-4 fw-bold">
|
|
3593
|
+
Examples
|
|
3594
|
+
</Button>
|
|
3595
|
+
</div>
|
|
3596
|
+
</Col>
|
|
3597
|
+
<Col lg={6} className="mt-5 mt-lg-0">
|
|
3598
|
+
<div className="bg-white p-5 rounded-5 shadow-2xl border">
|
|
3599
|
+
<div className="row g-4">
|
|
3600
|
+
<div className="col-6">
|
|
3601
|
+
<div className="p-4 bg-light rounded-4 text-center">
|
|
3602
|
+
<span className="fs-1 d-block mb-2">ā”</span>
|
|
3603
|
+
<span className="fw-bold">Fast SSR</span>
|
|
3604
|
+
</div>
|
|
3605
|
+
</div>
|
|
3606
|
+
<div className="col-6">
|
|
3607
|
+
<div className="p-4 bg-light rounded-4 text-center">
|
|
3608
|
+
<span className="fs-1 d-block mb-2">š”ļø</span>
|
|
3609
|
+
<span className="fw-bold">Secure</span>
|
|
3610
|
+
</div>
|
|
3611
|
+
</div>
|
|
3612
|
+
<div className="col-6">
|
|
3613
|
+
<div className="p-4 bg-light rounded-4 text-center">
|
|
3614
|
+
<span className="fs-1 d-block mb-2">š¦</span>
|
|
3615
|
+
<span className="fw-bold">Modular</span>
|
|
3616
|
+
</div>
|
|
3617
|
+
</div>
|
|
3618
|
+
<div className="col-6">
|
|
3619
|
+
<div className="p-4 bg-light rounded-4 text-center">
|
|
3620
|
+
<span className="fs-1 d-block mb-2">šØ</span>
|
|
3621
|
+
<span className="fw-bold">Customizable</span>
|
|
3622
|
+
</div>
|
|
3623
|
+
</div>
|
|
3624
|
+
</div>
|
|
3625
|
+
</div>
|
|
3626
|
+
</Col>
|
|
3627
|
+
</Row>
|
|
3628
|
+
</Container>
|
|
3629
|
+
|
|
3630
|
+
<footer className="py-5 mt-5 border-top">
|
|
3631
|
+
<Container className="text-center">
|
|
3632
|
+
<p className="text-secondary small">© 2024 EReactThohir ⢠Integrated with Bootstrap 5 Ecosystem</p>
|
|
3633
|
+
</Container>
|
|
3634
|
+
</footer>
|
|
3635
|
+
</div>
|
|
3636
|
+
);
|
|
3637
|
+
}
|
|
3638
|
+
`;
|
|
3639
|
+
}
|
|
3640
|
+
function generateMaterialWelcome(name) {
|
|
3641
|
+
return `import React from 'react';
|
|
3642
|
+
import {
|
|
3643
|
+
Box,
|
|
3644
|
+
Container,
|
|
3645
|
+
Typography,
|
|
3646
|
+
Button,
|
|
3647
|
+
Stack,
|
|
3648
|
+
AppBar,
|
|
3649
|
+
Toolbar,
|
|
3650
|
+
createTheme,
|
|
3651
|
+
ThemeProvider,
|
|
3652
|
+
CssBaseline,
|
|
3653
|
+
Paper,
|
|
3654
|
+
Grid
|
|
3655
|
+
} from '@mui/material';
|
|
3656
|
+
|
|
3657
|
+
const theme = createTheme({
|
|
3658
|
+
palette: {
|
|
3659
|
+
primary: { main: '#6366f1' },
|
|
3660
|
+
secondary: { main: '#ec4899' },
|
|
3661
|
+
background: { default: '#f1f5f9' }
|
|
3662
|
+
},
|
|
3663
|
+
typography: {
|
|
3664
|
+
fontFamily: "'Inter', sans-serif",
|
|
3665
|
+
h1: { fontWeight: 900, letterSpacing: '-0.05em' },
|
|
3666
|
+
},
|
|
3667
|
+
shape: { borderRadius: 16 }
|
|
3668
|
+
});
|
|
3669
|
+
|
|
3670
|
+
export default function Welcome() {
|
|
3671
|
+
return (
|
|
3672
|
+
<ThemeProvider theme={theme}>
|
|
3673
|
+
<CssBaseline />
|
|
3674
|
+
<Box sx={{ minHeight: '100vh', position: 'relative', overflow: 'hidden' }}>
|
|
3675
|
+
<AppBar position="static" color="transparent" elevation={0} sx={{ py: 2 }}>
|
|
3676
|
+
<Container>
|
|
3677
|
+
<Toolbar disableGutters sx={{ justifyContent: 'space-between' }}>
|
|
3678
|
+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
|
|
3679
|
+
<Box sx={{ width: 40, height: 40, bgcolor: 'primary.main', borderRadius: 3, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontWeight: 'black', fontSize: 20 }}>M</Box>
|
|
3680
|
+
<Typography variant="h6" sx={{ fontWeight: 900, color: 'text.primary' }}>EReactMUI</Typography>
|
|
3681
|
+
</Box>
|
|
3682
|
+
<Stack direction="row" spacing={4} sx={{ display: { xs: 'none', md: 'flex' } }}>
|
|
3683
|
+
<Button color="inherit" sx={{ fontWeight: 700 }}>Docs</Button>
|
|
3684
|
+
<Button color="inherit" sx={{ fontWeight: 700 }}>Marketplace</Button>
|
|
3685
|
+
<Button variant="contained" sx={{ fontWeight: 900, px: 4 }}>Login</Button>
|
|
3686
|
+
</Stack>
|
|
3687
|
+
</Toolbar>
|
|
3688
|
+
</Container>
|
|
3689
|
+
</AppBar>
|
|
3690
|
+
|
|
3691
|
+
<Container sx={{ pt: 15, pb: 10 }}>
|
|
3692
|
+
<Grid container spacing={8} alignItems="center">
|
|
3693
|
+
<Grid item xs={12} lg={7}>
|
|
3694
|
+
<Box sx={{ display: 'inline-block', px: 2, py: 0.5, bgcolor: 'secondary.main', color: 'white', borderRadius: 2, fontWeight: 900, fontSize: '0.75rem', mb: 3 }}>
|
|
3695
|
+
ENTERPRISE READY
|
|
3696
|
+
</Box>
|
|
3697
|
+
<Typography variant="h1" sx={{ fontSize: { xs: '3.5rem', md: '5.5rem' }, mb: 4, lineHeight: 1 }}>
|
|
3698
|
+
Premium <Typography component="span" variant="inherit" color="primary">Material</Typography> Experience.
|
|
3699
|
+
</Typography>
|
|
3700
|
+
<Typography variant="h5" color="textSecondary" sx={{ mb: 6, lineHeight: 1.6 }}>
|
|
3701
|
+
Combine Google's Material Design 3 with EreactThohir's architecture.
|
|
3702
|
+
Build flawless interfaces with institutional strength.
|
|
3703
|
+
</Typography>
|
|
3704
|
+
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={3}>
|
|
3705
|
+
<Button variant="contained" size="large" sx={{ py: 2, px: 5, fontSize: '1.1rem', fontWeight: 900 }}>
|
|
3706
|
+
Launch App
|
|
3707
|
+
</Button>
|
|
3708
|
+
<Button variant="outlined" size="large" sx={{ py: 2, px: 5, fontSize: '1.1rem', fontWeight: 900 }}>
|
|
3709
|
+
View Library
|
|
3710
|
+
</Button>
|
|
3711
|
+
</Stack>
|
|
3712
|
+
</Grid>
|
|
3713
|
+
<Grid item xs={12} lg={5}>
|
|
3714
|
+
<Paper elevation={0} sx={{ p: 4, bgcolor: 'white', border: '1px solid #e2e8f0', borderRadius: 8 }}>
|
|
3715
|
+
<Stack spacing={3}>
|
|
3716
|
+
<Box sx={{ p: 2, borderRadius: 4, bgcolor: '#f8fafc', display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
3717
|
+
<Box sx={{ fontSize: 32 }}>š</Box>
|
|
3718
|
+
<Box>
|
|
3719
|
+
<Typography sx={{ fontWeight: 900 }}>High Quality</Typography>
|
|
3720
|
+
<Typography variant="body2" color="textSecondary">Premium assets included</Typography>
|
|
3721
|
+
</Box>
|
|
3722
|
+
</Box>
|
|
3723
|
+
<Box sx={{ p: 2, borderRadius: 4, bgcolor: '#f8fafc', display: 'flex', alignItems: 'center', gap: 2 }}>
|
|
3724
|
+
<Box sx={{ fontSize: 32 }}>š</Box>
|
|
3725
|
+
<Box>
|
|
3726
|
+
<Typography sx={{ fontWeight: 900 }}>Fast Delivery</Typography>
|
|
3727
|
+
<Typography variant="body2" color="textSecondary">Optimized build pipeline</Typography>
|
|
3728
|
+
</Box>
|
|
3729
|
+
</Box>
|
|
3730
|
+
</Stack>
|
|
3731
|
+
</Paper>
|
|
3732
|
+
</Grid>
|
|
3733
|
+
</Grid>
|
|
3734
|
+
</Container>
|
|
3735
|
+
|
|
3736
|
+
<Box component="footer" sx={{ py: 8, textAlign: 'center', borderTop: '1px solid #e2e8f0' }}>
|
|
3737
|
+
<Typography color="textSecondary" variant="body2">
|
|
3738
|
+
© 2024 EReactThohir Framework ⢠Designed for Performance
|
|
3739
|
+
</Typography>
|
|
3740
|
+
</Box>
|
|
3741
|
+
</Box>
|
|
3742
|
+
</ThemeProvider>
|
|
3743
|
+
);
|
|
3744
|
+
}
|
|
3745
|
+
`;
|
|
3746
|
+
}
|
|
3747
|
+
function generateRiceWelcome(name) {
|
|
3748
|
+
return `import React from 'react';
|
|
3749
|
+
|
|
3750
|
+
export default function Welcome() {
|
|
3751
|
+
return (
|
|
3752
|
+
<div className="rice-min-h-screen rice-bg-white rice-relative rice-overflow-hidden rice-font-sans">
|
|
3753
|
+
{/* Background Decorative Elements */}
|
|
3754
|
+
<div className="rice-absolute rice-inset-0 rice-pointer-events-none">
|
|
3755
|
+
<div className="rice-absolute rice-top-[-10%] rice-right-[-5%] rice-w-[500px] rice-h-[500px] rice-bg-primary-500 rice-opacity-10 rice-blur-[120px] rice-rounded-full" />
|
|
3756
|
+
<div className="rice-absolute rice-bottom-[-10%] rice-left-[-5%] rice-w-[600px] rice-h-[600px] rice-bg-accent-500 rice-opacity-10 rice-blur-[120px] rice-rounded-full" />
|
|
3757
|
+
</div>
|
|
3758
|
+
|
|
3759
|
+
{/* Navigation */}
|
|
3760
|
+
<nav className="rice-relative rice-z-10 rice-flex rice-items-center rice-justify-between rice-px-8 rice-py-6 rice-max-w-7xl rice-mx-auto">
|
|
3761
|
+
<div className="rice-flex rice-items-center rice-gap-3">
|
|
3762
|
+
<div className="rice-w-12 rice-h-12 rice-bg-secondary-900 rice-rounded-2xl rice-flex rice-items-center rice-justify-center rice-text-white rice-font-black rice-text-2xl rice-shadow-lg">E</div>
|
|
3763
|
+
<span className="rice-text-2xl rice-font-black rice-tracking-tighter rice-text-secondary-900">EreactThohir</span>
|
|
3764
|
+
</div>
|
|
3765
|
+
<div className="rice-hidden rice-md-flex rice-items-center rice-gap-10 rice-text-sm rice-font-bold rice-text-secondary-600">
|
|
3766
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Documentation</a>
|
|
3767
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Showcase</a>
|
|
3768
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">Community</a>
|
|
3769
|
+
<a href="/auth/login" className="rice-px-6 rice-py-2.5 rice-bg-secondary-900 rice-text-white rice-rounded-full rice-hover-scale-105 rice-shadow-primary rice-transition-all">Get Started</a>
|
|
3770
|
+
</div>
|
|
3771
|
+
</nav>
|
|
3772
|
+
|
|
3773
|
+
<main className="rice-relative rice-z-10 rice-max-w-7xl rice-mx-auto rice-px-8 rice-pt-32 rice-pb-40">
|
|
3774
|
+
<div className="rice-text-center rice-max-w-5xl rice-mx-auto">
|
|
3775
|
+
<div className="rice-inline-flex rice-items-center rice-gap-2 rice-px-5 rice-py-2.5 rice-bg-secondary-100 rice-rounded-full rice-mb-10 rice-animate-pulse rice-border rice-border-secondary-200">
|
|
3776
|
+
<span className="rice-w-2.5 rice-h-2.5 rice-bg-primary-500 rice-rounded-full" />
|
|
3777
|
+
<span className="rice-text-xs rice-font-black rice-text-secondary-900 rice-uppercase rice-tracking-widest">Framework v1.3.5 "Evolution" is here</span>
|
|
3778
|
+
</div>
|
|
3779
|
+
|
|
3780
|
+
<h1 className="rice-text-7xl rice-md-text-9xl rice-font-black rice-tracking-tighter rice-mb-10 rice-leading-[0.9]">
|
|
3781
|
+
The New Standard of <br/>
|
|
3782
|
+
<span className="rice-gradient-primary rice-bg-clip-text rice-text-transparent">Modern Web</span> Apps.
|
|
3783
|
+
</h1>
|
|
3784
|
+
|
|
3785
|
+
<p className="rice-text-xl rice-md-text-2xl rice-text-secondary-600 rice-mb-16 rice-leading-relaxed rice-max-w-3xl rice-mx-auto">
|
|
3786
|
+
Experience the raw speed of React combined with the solid architecture of EReactThohir.
|
|
3787
|
+
Production-ready components, built with high-end Rice UI aesthetics.
|
|
3788
|
+
</p>
|
|
3789
|
+
|
|
3790
|
+
<div className="rice-flex rice-flex-wrap rice-justify-center rice-gap-6">
|
|
3791
|
+
<a href="/auth/register" className="rice-px-12 rice-py-6 rice-bg-secondary-900 rice-text-white rice-text-xl rice-font-black rice-rounded-3xl rice-shadow-2xl rice-hover-lift rice-transition-all rice-duration-300">
|
|
3792
|
+
Build Your Vision
|
|
3793
|
+
</a>
|
|
3794
|
+
<a href="#" className="rice-px-12 rice-py-6 rice-bg-white rice-border rice-text-secondary-900 rice-text-xl rice-font-black rice-rounded-3xl rice-hover-bg-secondary-50 rice-transition-all rice-duration-300">
|
|
3795
|
+
Watch Demo
|
|
3796
|
+
</a>
|
|
3797
|
+
</div>
|
|
3798
|
+
</div>
|
|
3799
|
+
|
|
3800
|
+
{/* Feature Grid with Glassmorphism */}
|
|
3801
|
+
<div className="rice-mt-48 rice-grid rice-grid-cols-1 rice-md-grid-cols-3 rice-gap-10">
|
|
3802
|
+
<FeatureCard
|
|
3803
|
+
title="MVC Redefined"
|
|
3804
|
+
desc="Full-featured routing, controllers, and models inspired by Laravel's elegance but built for JS/TS."
|
|
3805
|
+
icon="šļø"
|
|
3806
|
+
/>
|
|
3807
|
+
<FeatureCard
|
|
3808
|
+
title="Speed of Light"
|
|
3809
|
+
desc="Advanced SSR with partial hydration ensures your lighthouse score stays at 100% effortlessly."
|
|
3810
|
+
icon="ā”"
|
|
3811
|
+
/>
|
|
3812
|
+
<FeatureCard
|
|
3813
|
+
title="Rice UI Design"
|
|
3814
|
+
desc="Premade high-end components with glassmorphism and vibrance. Just drop and go."
|
|
3815
|
+
icon="šØ"
|
|
3816
|
+
/>
|
|
3817
|
+
</div>
|
|
3818
|
+
</main>
|
|
3819
|
+
|
|
3820
|
+
<footer className="rice-py-20 rice-border-t rice-bg-secondary-50">
|
|
3821
|
+
<div className="rice-max-w-7xl rice-mx-auto rice-px-8 rice-flex rice-flex-col rice-md-flex-row rice-items-center rice-justify-between rice-gap-10">
|
|
3822
|
+
<div>
|
|
3823
|
+
<p className="rice-text-secondary-900 rice-font-black rice-text-xl rice-mb-2">EreactThohir</p>
|
|
3824
|
+
<p className="rice-text-secondary-500 rice-text-sm">Ā© 2024. Crafted for excellence by Dhafa Nazula Permadi.</p>
|
|
3825
|
+
</div>
|
|
3826
|
+
<div className="rice-flex rice-gap-8 rice-text-secondary-400 rice-text-2xl">
|
|
3827
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">š</a>
|
|
3828
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">GitHub</a>
|
|
3829
|
+
<a href="#" className="rice-hover-text-secondary-900 rice-transition-all">LinkedIn</a>
|
|
3830
|
+
</div>
|
|
3831
|
+
</div>
|
|
3832
|
+
</footer>
|
|
3833
|
+
</div>
|
|
3834
|
+
);
|
|
3835
|
+
}
|
|
3836
|
+
|
|
3837
|
+
function FeatureCard({ title, desc, icon }: any) {
|
|
3838
|
+
return (
|
|
3839
|
+
<div className="rice-p-10 rice-bg-white rice-border rice-rounded-[40px] rice-hover-shadow-2xl rice-hover-lift rice-transition-all rice-duration-500 rice-group">
|
|
3840
|
+
<div className="rice-w-16 rice-h-16 rice-bg-primary-500 rice-bg-opacity-10 rice-rounded-3xl rice-flex rice-items-center rice-justify-center rice-mb-8 rice-text-3xl rice-group-hover-scale-110 rice-transition-all">
|
|
3841
|
+
{icon}
|
|
3842
|
+
</div>
|
|
3843
|
+
<h3 className="rice-text-2xl rice-font-black rice-mb-4 rice-text-secondary-900">{title}</h3>
|
|
3844
|
+
<p className="rice-text-secondary-500 rice-leading-relaxed rice-font-medium">{desc}</p>
|
|
3845
|
+
</div>
|
|
3846
|
+
);
|
|
3847
|
+
}
|
|
3848
|
+
`;
|
|
3849
|
+
}
|
|
3850
|
+
function generateTailwindWelcome(name) {
|
|
3851
|
+
return `import React from 'react';
|
|
3852
|
+
|
|
3853
|
+
export default function Welcome() {
|
|
3854
|
+
return (
|
|
3855
|
+
<div className="min-h-screen bg-slate-50 font-sans selection:bg-blue-500 selection:text-white">
|
|
3856
|
+
{/* Tailwind Mesh Gradient */}
|
|
3857
|
+
<div className="absolute inset-0 overflow-hidden pointer-events-none -z-10">
|
|
3858
|
+
<div className="absolute top-[-10%] right-[-10%] w-[800px] h-[800px] bg-blue-100 rounded-full blur-[120px] opacity-60"></div>
|
|
3859
|
+
<div className="absolute bottom-[-10%] left-[-10%] w-[800px] h-[800px] bg-indigo-100 rounded-full blur-[120px] opacity-60"></div>
|
|
3860
|
+
</div>
|
|
3861
|
+
|
|
3862
|
+
<nav className="flex items-center justify-between p-8 max-w-7xl mx-auto">
|
|
3863
|
+
<div className="flex items-center gap-3">
|
|
3864
|
+
<div className="w-10 h-10 bg-blue-600 rounded-xl flex items-center justify-center text-white font-black text-xl shadow-lg ring-4 ring-blue-50">E</div>
|
|
3865
|
+
<span className="text-xl font-bold tracking-tight text-slate-900">EreactThohir</span>
|
|
3866
|
+
</div>
|
|
3867
|
+
<div className="hidden md:flex items-center gap-8">
|
|
3868
|
+
<a href="#" className="text-sm font-semibold text-slate-600 hover:text-blue-600 transition-colors">Documentation</a>
|
|
3869
|
+
<a href="#" className="text-sm font-semibold text-slate-600 hover:text-blue-600 transition-colors">Components</a>
|
|
3870
|
+
<a href="/login" className="px-5 py-2.5 bg-slate-900 text-white text-sm font-bold rounded-full hover:bg-blue-600 hover:scale-105 transition-all shadow-xl shadow-slate-200">
|
|
3871
|
+
Launch Project
|
|
3872
|
+
</a>
|
|
3873
|
+
</div>
|
|
3874
|
+
</nav>
|
|
3875
|
+
|
|
3876
|
+
<main className="max-w-7xl mx-auto px-8 pt-24 pb-32">
|
|
3877
|
+
<div className="max-w-3xl">
|
|
3878
|
+
<div className="inline-flex items-center gap-2 px-3 py-1 bg-blue-50 text-blue-700 rounded-full mb-8 border border-blue-100">
|
|
3879
|
+
<span className="relative flex h-2 w-2">
|
|
3880
|
+
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
|
3881
|
+
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-500"></span>
|
|
3882
|
+
</span>
|
|
3883
|
+
<span className="text-xs font-bold uppercase tracking-wider">Tailwind Support Active</span>
|
|
3884
|
+
</div>
|
|
3885
|
+
|
|
3886
|
+
<h1 className="text-6xl md:text-8xl font-black text-slate-900 tracking-tight leading-[1.1] mb-8">
|
|
3887
|
+
The Developer's <span className="text-blue-600">Superpower.</span>
|
|
3888
|
+
</h1>
|
|
3889
|
+
|
|
3890
|
+
<p className="text-xl md:text-2xl text-slate-600 leading-relaxed mb-12">
|
|
3891
|
+
Build your next big idea with EReactThohir and the massive Tailwind CSS ecosystem.
|
|
3892
|
+
No limits, just raw creative potential.
|
|
3893
|
+
</p>
|
|
3894
|
+
|
|
3895
|
+
<div className="flex flex-wrap gap-4">
|
|
3896
|
+
<button className="px-8 py-4 bg-blue-600 text-white font-bold rounded-2xl shadow-2xl shadow-blue-200 hover:bg-blue-700 hover:-translate-y-1 transition-all">
|
|
3897
|
+
Start Coding Now
|
|
3898
|
+
</button>
|
|
3899
|
+
<button className="px-8 py-4 bg-white border border-slate-200 text-slate-900 font-bold rounded-2xl hover:bg-slate-50 transition-all">
|
|
3900
|
+
View Examples
|
|
3901
|
+
</button>
|
|
3902
|
+
</div>
|
|
3903
|
+
</div>
|
|
3904
|
+
|
|
3905
|
+
<div className="mt-32 grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
3906
|
+
<FeatureCard title="Responsive" desc="Every pixel optimized for mobile, tablet, and desktop out of the box." />
|
|
3907
|
+
<FeatureCard title="Tailwind Ready" desc="Fully integrated with JIT engine and your custom design tokens." />
|
|
3908
|
+
<FeatureCard title="Type Safe" desc="End-to-end type safety for a predictable development experience." />
|
|
3909
|
+
</div>
|
|
3910
|
+
</main>
|
|
3911
|
+
</div>
|
|
3912
|
+
);
|
|
3913
|
+
}
|
|
3914
|
+
|
|
3915
|
+
function FeatureCard({ title, desc }: any) {
|
|
3916
|
+
return (
|
|
3917
|
+
<div className="p-8 bg-white/50 backdrop-blur-xl border border-white rounded-[32px] hover:border-blue-200 hover:shadow-2xl transition-all group">
|
|
3918
|
+
<h3 className="text-xl font-bold mb-3 text-slate-900 group-hover:text-blue-600 transition-colors uppercase tracking-tight">{title}</h3>
|
|
3919
|
+
<p className="text-slate-600 leading-relaxed">{desc}</p>
|
|
3920
|
+
</div>
|
|
3921
|
+
);
|
|
3922
|
+
}
|
|
3923
|
+
`;
|
|
3924
|
+
}
|
|
3925
|
+
function generateJokoWelcome(name) {
|
|
3926
|
+
return `import React from 'react';
|
|
3927
|
+
|
|
3928
|
+
export default function Welcome() {
|
|
3929
|
+
return (
|
|
3930
|
+
<div className="joko-flex joko-flex-col joko-min-h-screen joko-bg-secondary-50">
|
|
3931
|
+
{/* Formal Header */}
|
|
3932
|
+
<header className="joko-p-8 joko-bg-white joko-border-b joko-flex joko-items-center joko-justify-between">
|
|
3933
|
+
<div className="joko-flex joko-items-center joko-gap-4">
|
|
3934
|
+
<div className="joko-w-10 joko-h-10 joko-bg-primary-600 joko-rounded-md joko-flex joko-items-center joko-justify-center joko-text-white joko-font-bold">JK</div>
|
|
3935
|
+
<span className="joko-text-2xl joko-font-bold joko-tracking-tight joko-text-primary-900">JokoUI + EReactThohir</span>
|
|
3936
|
+
</div>
|
|
3937
|
+
<nav className="joko-flex joko-gap-8 joko-text-sm joko-font-bold">
|
|
3938
|
+
<a href="#" className="joko-text-secondary-600 hover:joko-text-primary-600">PANDUAN</a>
|
|
3939
|
+
<a href="#" className="joko-text-secondary-600 hover:joko-text-primary-600">KOMPONEN</a>
|
|
3940
|
+
<Button variant="primary" style={{ padding: '0.5rem 1rem' }}>MEMULAI</Button>
|
|
3941
|
+
</nav>
|
|
3942
|
+
</header>
|
|
3943
|
+
|
|
3944
|
+
<main className="joko-flex-1 joko-flex joko-items-center joko-justify-center joko-p-8">
|
|
3945
|
+
<div className="joko-max-w-4xl joko-w-full">
|
|
3946
|
+
<div className="joko-card joko-text-center">
|
|
3947
|
+
<span className="joko-text-primary-600 joko-font-bold joko-tracking-[0.2em] joko-text-xs joko-mb-6 joko-block">VERSI TERBARU v1.0.0</span>
|
|
3948
|
+
<h1 className="joko-text-6xl joko-font-bold joko-mb-8 joko-text-secondary-900 joko-leading-tight">
|
|
3949
|
+
Membangun Aplikasi dengan <br/>
|
|
3950
|
+
<span className="joko-text-primary-600">Kepercayaan</span> dan <span className="joko-text-accent-600">Kekuatan.</span>
|
|
3951
|
+
</h1>
|
|
3952
|
+
<p className="joko-text-xl joko-text-secondary-600 joko-mb-12 joko-max-w-2xl joko-mx-auto">
|
|
3953
|
+
Framework EReactThohir dengan JokoUI. Solusi formal untuk kebutuhan enterprise tingkat tinggi.
|
|
3954
|
+
Handal, Sederhana, dan Berwibawa.
|
|
3955
|
+
</p>
|
|
3956
|
+
|
|
3957
|
+
<div className="joko-flex joko-justify-center joko-gap-6">
|
|
3958
|
+
<button className="joko-btn joko-btn-primary joko-text-lg joko-px-10">
|
|
3959
|
+
Buat Proyek Baru
|
|
3960
|
+
</button>
|
|
3961
|
+
<button className="joko-btn joko-bg-white joko-border joko-border-secondary-300 joko-text-secondary-900 joko-text-lg joko-px-10">
|
|
3962
|
+
Dokumentasi
|
|
3963
|
+
</button>
|
|
3964
|
+
</div>
|
|
3965
|
+
</div>
|
|
3966
|
+
|
|
3967
|
+
<div className="joko-grid joko-grid-cols-3 joko-gap-8 joko-mt-12">
|
|
3968
|
+
<StatCard label="KEANDALAN" value="100%" />
|
|
3969
|
+
<StatCard label="KECEPATAN" value="0.2s" />
|
|
3970
|
+
<StatCard label="KEAMANAN" value="EXTRA" />
|
|
3971
|
+
</div>
|
|
3972
|
+
</div>
|
|
3973
|
+
</main>
|
|
3974
|
+
|
|
3975
|
+
<footer className="joko-p-12 joko-bg-primary-900 joko-text-white joko-text-center">
|
|
3976
|
+
<p className="joko-text-primary-300 joko-text-sm joko-font-bold joko-tracking-widest">ERECTTHOHIR ECOSYSTEM ⢠2024</p>
|
|
3977
|
+
</footer>
|
|
3978
|
+
</div>
|
|
3979
|
+
);
|
|
3980
|
+
}
|
|
3981
|
+
|
|
3982
|
+
function StatCard({ label, value }: any) {
|
|
3983
|
+
return (
|
|
3984
|
+
<div className="joko-bg-white joko-p-6 joko-border joko-border-secondary-200 joko-rounded-lg joko-text-center">
|
|
3985
|
+
<p className="joko-text-xs joko-font-bold joko-text-secondary-400 joko-mb-2 joko-tracking-tighter">{label}</p>
|
|
3986
|
+
<p className="joko-text-3xl joko-font-bold joko-text-primary-600">{value}</p>
|
|
3987
|
+
</div>
|
|
3988
|
+
);
|
|
3989
|
+
}
|
|
3990
|
+
|
|
3991
|
+
function Button({ children, variant, style }: any) {
|
|
3992
|
+
const base = "joko-btn";
|
|
3993
|
+
const variantCls = variant === 'primary' ? 'joko-btn-primary' : '';
|
|
3994
|
+
return <button className={\`\${base} \${variantCls}\`} style={style}>{children}</button>;
|
|
3995
|
+
}
|
|
3996
|
+
`;
|
|
3997
|
+
}
|
|
3998
|
+
function getUIHelper(uiSystem) {
|
|
3999
|
+
const isRice = uiSystem === 'Rice UI (default, official)';
|
|
4000
|
+
const isTailwind = uiSystem === 'Tailwind CSS' || uiSystem === 'DaisyUI' || uiSystem === 'Shadcn/ui';
|
|
4001
|
+
const isJoko = uiSystem === 'JokoUI';
|
|
4002
|
+
const isBootstrap = uiSystem === 'Bootstrap 5';
|
|
4003
|
+
const isMaterial = uiSystem === 'Material UI';
|
|
4004
|
+
const isMantine = uiSystem === 'Mantine';
|
|
4005
|
+
const isChakra = uiSystem === 'Chakra UI';
|
|
4006
|
+
return {
|
|
4007
|
+
cls: (rice, tailwind, joko, bootstrap = '', material = '') => {
|
|
4008
|
+
if (isRice)
|
|
4009
|
+
return rice;
|
|
4010
|
+
if (isTailwind)
|
|
4011
|
+
return tailwind;
|
|
4012
|
+
if (isJoko)
|
|
4013
|
+
return joko;
|
|
4014
|
+
if (isBootstrap && bootstrap)
|
|
4015
|
+
return bootstrap;
|
|
4016
|
+
if (isMaterial && material)
|
|
4017
|
+
return material;
|
|
4018
|
+
return tailwind;
|
|
4019
|
+
},
|
|
4020
|
+
mode: () => {
|
|
4021
|
+
if (isRice)
|
|
4022
|
+
return 'rice';
|
|
4023
|
+
if (isTailwind)
|
|
4024
|
+
return 'tailwind';
|
|
4025
|
+
if (isJoko)
|
|
4026
|
+
return 'joko';
|
|
4027
|
+
if (isBootstrap)
|
|
4028
|
+
return 'bootstrap';
|
|
4029
|
+
if (isMaterial)
|
|
4030
|
+
return 'material';
|
|
4031
|
+
if (isMantine)
|
|
4032
|
+
return 'mantine';
|
|
4033
|
+
if (isChakra)
|
|
4034
|
+
return 'chakra';
|
|
4035
|
+
return 'none';
|
|
4036
|
+
}
|
|
4037
|
+
};
|
|
4038
|
+
}
|
|
2940
4039
|
//# sourceMappingURL=create.js.map
|