create-fullstack-boilerplate 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +390 -0
  2. package/index.js +78 -0
  3. package/lib/addDB.js +77 -0
  4. package/lib/addRoute.js +264 -0
  5. package/lib/copyProject.js +25 -0
  6. package/lib/dataTypes.js +79 -0
  7. package/lib/installDeps.js +11 -0
  8. package/lib/prompts.js +289 -0
  9. package/lib/setupExtraDB.js +172 -0
  10. package/lib/setupMainDB.js +9 -0
  11. package/lib/testDBConnection.js +31 -0
  12. package/lib/utils.js +39 -0
  13. package/package.json +45 -0
  14. package/template/Backend/.env +7 -0
  15. package/template/Backend/DB/DBInit.js +28 -0
  16. package/template/Backend/DB/dbConfigs.js +4 -0
  17. package/template/Backend/Models/index.js +54 -0
  18. package/template/Backend/README.md +535 -0
  19. package/template/Backend/middleware/authMiddleware.js +19 -0
  20. package/template/Backend/package-lock.json +2997 -0
  21. package/template/Backend/package.json +32 -0
  22. package/template/Backend/routes/authRoutes.js +15 -0
  23. package/template/Backend/routes/dashboardRoutes.js +13 -0
  24. package/template/Backend/routes/index.js +15 -0
  25. package/template/Backend/routes/settingsRoutes.js +9 -0
  26. package/template/Backend/server.js +70 -0
  27. package/template/Backend/services/authService.js +68 -0
  28. package/template/Backend/services/cryptoService.js +14 -0
  29. package/template/Backend/services/dashboardService.js +39 -0
  30. package/template/Backend/services/settingsService.js +43 -0
  31. package/template/Frontend/.env +3 -0
  32. package/template/Frontend/README.md +576 -0
  33. package/template/Frontend/eslint.config.js +29 -0
  34. package/template/Frontend/index.html +13 -0
  35. package/template/Frontend/package-lock.json +3690 -0
  36. package/template/Frontend/package.json +39 -0
  37. package/template/Frontend/public/PMDLogo.png +0 -0
  38. package/template/Frontend/public/pp.jpg +0 -0
  39. package/template/Frontend/public/tabicon.png +0 -0
  40. package/template/Frontend/src/App.jsx +71 -0
  41. package/template/Frontend/src/assets/fonts/ArticulatCFDemiBold/font.woff +0 -0
  42. package/template/Frontend/src/assets/fonts/ArticulatCFDemiBold/font.woff2 +0 -0
  43. package/template/Frontend/src/assets/fonts/ArticulatCFNormal/font.woff +0 -0
  44. package/template/Frontend/src/assets/fonts/ArticulatCFNormal/font.woff2 +0 -0
  45. package/template/Frontend/src/assets/fonts/ArticulatCFRegular/font.woff +0 -0
  46. package/template/Frontend/src/assets/fonts/ArticulatCFRegular/font.woff2 +0 -0
  47. package/template/Frontend/src/assets/fonts/MixtaProRegularItalic/font.woff +0 -0
  48. package/template/Frontend/src/assets/fonts/MixtaProRegularItalic/font.woff2 +0 -0
  49. package/template/Frontend/src/assets/fonts/fonts_sohne/OTF/S/303/266hneMono-Buch.otf +0 -0
  50. package/template/Frontend/src/assets/fonts/fonts_sohne/OTF/S/303/266hneMono-Leicht.otf +0 -0
  51. package/template/Frontend/src/assets/fonts/fonts_sohne/WOFF2/soehne-mono-buch.woff2 +0 -0
  52. package/template/Frontend/src/assets/fonts/fonts_sohne/WOFF2/soehne-mono-leicht.woff2 +0 -0
  53. package/template/Frontend/src/components/Layout.jsx +61 -0
  54. package/template/Frontend/src/components/Loader.jsx +19 -0
  55. package/template/Frontend/src/components/ProtectedRoute.jsx +19 -0
  56. package/template/Frontend/src/components/Sidebar.jsx +286 -0
  57. package/template/Frontend/src/components/ThemeToggle.jsx +30 -0
  58. package/template/Frontend/src/config/axiosClient.js +46 -0
  59. package/template/Frontend/src/config/encryption.js +11 -0
  60. package/template/Frontend/src/config/routes.js +65 -0
  61. package/template/Frontend/src/contexts/AuthContext.jsx +144 -0
  62. package/template/Frontend/src/contexts/ThemeContext.jsx +69 -0
  63. package/template/Frontend/src/index.css +88 -0
  64. package/template/Frontend/src/main.jsx +11 -0
  65. package/template/Frontend/src/pages/Dashboard.jsx +137 -0
  66. package/template/Frontend/src/pages/Login.jsx +195 -0
  67. package/template/Frontend/src/pages/NotFound.jsx +70 -0
  68. package/template/Frontend/src/pages/Settings.jsx +69 -0
  69. package/template/Frontend/tailwind.config.js +90 -0
  70. package/template/Frontend/vite.config.js +37 -0
  71. package/template/Readme.md +0 -0
@@ -0,0 +1,195 @@
1
+ import { useState } from 'react';
2
+ import { useNavigate, Link } from 'react-router-dom';
3
+ import { Eye, EyeOff, Mail, Lock, AlertCircle, User } from 'lucide-react';
4
+ import { useAuth } from '../contexts/AuthContext';
5
+ const Login = () => {
6
+ const navigate = useNavigate();
7
+ const { handleLogin } = useAuth();
8
+
9
+ const [formData, setFormData] = useState({
10
+ email: '',
11
+ password: ''
12
+ });
13
+ const [isLoading, setIsLoading] = useState(false);
14
+ const [error, setError] = useState('');
15
+ const [showPassword, setShowPassword] = useState(false);
16
+ const [rememberMe, setRememberMe] = useState(false);
17
+
18
+ const handleChange = (e) => {
19
+ const { name, value } = e.target;
20
+ setFormData(prev => ({ ...prev, [name]: value }));
21
+ setError('');
22
+ };
23
+
24
+ const handleSubmit = async (e) => {
25
+ e.preventDefault();
26
+ setIsLoading(true);
27
+ setError('');
28
+
29
+ if (!formData.email || !formData.password) {
30
+ setError('Please fill in all fields');
31
+ setIsLoading(false);
32
+ return;
33
+ }
34
+
35
+ try {
36
+ const result = await handleLogin(formData.email, formData.password);
37
+
38
+ if (result.success) {
39
+ navigate('/dashboard');
40
+ } else {
41
+ setError(result.error);
42
+ }
43
+ } catch (error) {
44
+ console.error('Login error:', error);
45
+ setError('An unexpected error occurred. Please try again.');
46
+ } finally {
47
+ setIsLoading(false);
48
+ }
49
+ };
50
+
51
+ const handleForgotPassword = () => {
52
+ console.log('Forgot password clicked');
53
+ // Navigate to forgot password page when implemented
54
+ // navigate('/forgot-password');
55
+ };
56
+
57
+ return (
58
+ <div className="h-screen flex items-center justify-center relative overflow-hidden bg-gradient-to-br from-slate-50 via-blue-50 to-indigo-100">
59
+ {/* Decorative diagonal lines */}
60
+ <div className="absolute inset-0 overflow-hidden pointer-events-none">
61
+ <div className="absolute -top-20 -right-20 w-40 h-full bg-gradient-to-b from-blue-400/20 via-indigo-400/10 to-transparent transform rotate-12"></div>
62
+ <div className="absolute -bottom-20 -left-20 w-40 h-full bg-gradient-to-t from-indigo-400/20 via-blue-400/10 to-transparent transform -rotate-12"></div>
63
+ </div>
64
+
65
+ {/* Main content */}
66
+ <div className="relative z-10 w-full max-w-md mx-4">
67
+ {/* Main Card */}
68
+ <div className="bg-white/90 backdrop-blur-sm shadow-2xl rounded-2xl border border-white/20 overflow-hidden">
69
+ {/* Header */}
70
+ <div className="px-6 pt-6 pb-4 text-center">
71
+ <div className="relative mb-4">
72
+ <img src={'/PMDLogo.png'} alt="PMD Logo" className='w-max h-14 mx-auto' />
73
+ </div>
74
+
75
+ <h1 className="text-2xl font-articulatcf-demibold text-gray-800 mb-1">Welcome Back</h1>
76
+ <p className="text-gray-600 font-articulat-cf text-sm">Sign in to your account</p>
77
+
78
+ {/* Accent line */}
79
+ <div className="w-12 h-0.5 bg-gradient-to-r from-blue-500 to-indigo-500 rounded-full mx-auto mt-3"></div>
80
+ </div>
81
+
82
+ {/* Error Alert */}
83
+ {error && (
84
+ <div className="mx-6 mb-4">
85
+ <div className="bg-red-50 border border-red-200 rounded-lg p-3 flex items-start space-x-2">
86
+ <AlertCircle className="w-4 h-4 text-red-500 flex-shrink-0 mt-0.5" />
87
+ <span className="text-xs text-red-700 font-articulat-cf">{error}</span>
88
+ </div>
89
+ </div>
90
+ )}
91
+
92
+ <div className='flex flex-col w-full my-6 px-6 justify-start items-start'>
93
+ <p><strong><i>Temp Email:</i></strong> admin@npmjs.com</p>
94
+ <p><strong><i>Temp Pass:</i></strong> admin@786</p>
95
+ </div>
96
+
97
+ {/* Form */}
98
+ <form onSubmit={handleSubmit} className="px-6 pb-4 space-y-8">
99
+ {/* Email Field */}
100
+ <div className="space-y-3">
101
+ <label className="flex items-start text-md font-articulat-cf font-semibold text-gray-700">
102
+ <Mail className="w-5 h-5 mr-1.5 text-blue-500" />
103
+ Email Address
104
+ </label>
105
+ <input
106
+ type="email"
107
+ name="email"
108
+ value={formData.email}
109
+ onChange={handleChange}
110
+ placeholder="Enter your email"
111
+ className="w-full px-3 py-2.5 bg-gray-50 border border-gray-200 rounded-lg font-articulat-cf text-gray-800 placeholder:text-gray-400 text-sm"
112
+ required
113
+ disabled={isLoading}
114
+ autoComplete="email"
115
+ />
116
+ </div>
117
+
118
+ {/* Password Field */}
119
+ <div className="space-y-3">
120
+ <label className="flex items-start text-md font-articulat-cf font-medium text-gray-700">
121
+ <Lock className="w-5 h-5 mr-1.5 text-blue-500" />
122
+ Password
123
+ </label>
124
+ <div className="relative">
125
+ <input
126
+ type={showPassword ? "text" : "password"}
127
+ name="password"
128
+ value={formData.password}
129
+ onChange={handleChange}
130
+ placeholder="Enter your password"
131
+ className="w-full px-3 py-2.5 bg-gray-50 border border-gray-200 rounded-lg font-articulat-cf text-gray-800 placeholder:text-gray-400 pr-10 text-sm"
132
+ required
133
+ disabled={isLoading}
134
+ autoComplete="current-password"
135
+ />
136
+ <button
137
+ type="button"
138
+ onClick={() => setShowPassword(!showPassword)}
139
+ className="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-400 hover:text-gray-600 transition-colors"
140
+ disabled={isLoading}
141
+ >
142
+ {showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
143
+ </button>
144
+ </div>
145
+ </div>
146
+
147
+ {/* Remember Me & Forgot Password */}
148
+ <div className="flex items-center justify-between">
149
+ <label className="flex items-center cursor-pointer">
150
+ <input
151
+ type="checkbox"
152
+ checked={rememberMe}
153
+ onChange={(e) => setRememberMe(e.target.checked)}
154
+ disabled={isLoading}
155
+ className="w-3.5 h-3.5 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 focus:ring-1"
156
+ />
157
+ <span className="ml-2 text-xs text-gray-600 font-articulat-cf">Remember me</span>
158
+ </label>
159
+ <button
160
+ type="button"
161
+ onClick={handleForgotPassword}
162
+ className="text-xs text-blue-600 hover:text-blue-700 font-articulat-cf font-medium transition-colors"
163
+ disabled={isLoading}
164
+ >
165
+ Forgot password?
166
+ </button>
167
+ </div>
168
+
169
+ {/* Submit Button */}
170
+ <button
171
+ type="submit"
172
+ disabled={isLoading}
173
+ className="mx-auto w-max bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white font-articulatcf-demibold py-2.5 px-4 rounded-lg transition-all duration-200 shadow-lg hover:shadow-xl disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center text-sm"
174
+ >
175
+ {isLoading ? (
176
+ <>
177
+ <div className="w-4 h-4 border-2 border-white/20 border-t-white rounded-full animate-spin mr-2"></div>
178
+ Signing In...
179
+ </>
180
+ ) : (
181
+ <>
182
+ <User className="w-4 h-4 mr-2" />
183
+ Sign In
184
+ </>
185
+ )}
186
+ </button>
187
+ </form>
188
+
189
+ </div>
190
+ </div>
191
+ </div>
192
+ );
193
+ };
194
+
195
+ export default Login;
@@ -0,0 +1,70 @@
1
+ import { useTheme } from "../contexts/ThemeContext";
2
+ import { useNavigate } from "react-router-dom";
3
+ import { Home, User, AlertCircle } from "lucide-react";
4
+
5
+ const NotFound = () => {
6
+ const { isDark } = useTheme();
7
+ const navigate = useNavigate();
8
+
9
+ return (
10
+ <div className={`min-h-screen w-full flex items-center justify-center p-4 ${isDark ? 'bg-gray-900' : 'bg-gray-50'} transition-colors duration-200`}>
11
+ <div className="max-w-2xl w-full text-center">
12
+ {/* Animated 404 Icon */}
13
+ <div className="mb-8 relative">
14
+ <div className={`inline-flex items-center justify-center w-32 h-32 rounded-full ${isDark ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'} border-2 shadow-xl mb-4`}>
15
+ <AlertCircle className={`w-16 h-16 ${isDark ? 'text-blue-400' : 'text-blue-500'}`} strokeWidth={1.5} />
16
+ </div>
17
+ </div>
18
+
19
+ {/* 404 Large Text */}
20
+ <h1 className={`text-8xl md:text-9xl font-bold mb-6 ${isDark ? 'text-gray-100' : 'text-gray-900'}`}>
21
+ 404
22
+ </h1>
23
+
24
+ {/* Error Message */}
25
+ <h2 className={`text-2xl md:text-3xl font-bold mb-4 ${isDark ? 'text-gray-200' : 'text-gray-800'}`}>
26
+ Page Not Found
27
+ </h2>
28
+
29
+ <p className={`text-lg mb-8 ${isDark ? 'text-gray-400' : 'text-gray-600'} max-w-md mx-auto`}>
30
+ The page you're looking for doesn't exist or has been moved.
31
+ </p>
32
+
33
+ {/* Divider */}
34
+ <div className={`w-24 h-1 mx-auto mb-8 rounded-full ${isDark ? 'bg-blue-600' : 'bg-blue-500'}`}></div>
35
+
36
+ {/* Navigation Buttons */}
37
+ <div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
38
+ <button
39
+ onClick={() => navigate('/')}
40
+ className={`flex items-center justify-center gap-2 px-8 py-3 rounded-lg font-medium transition-all duration-200 w-full sm:w-auto cursor-pointer ${isDark
41
+ ? 'bg-blue-600 hover:bg-blue-700 text-white'
42
+ : 'bg-blue-500 hover:bg-blue-600 text-white'
43
+ } shadow-lg hover:shadow-xl transform hover:-translate-y-0.5`}
44
+ >
45
+ <Home className="w-5 h-5" />
46
+ <span>Go to Main Page</span>
47
+ </button>
48
+
49
+ <button
50
+ onClick={() => navigate('/profile')}
51
+ className={`flex items-center justify-center gap-2 px-8 py-3 rounded-lg font-medium transition-all duration-200 w-full sm:w-auto cursor-pointer ${isDark
52
+ ? 'bg-gray-800 hover:bg-gray-700 text-gray-200 border border-gray-700'
53
+ : 'bg-white hover:bg-gray-50 text-gray-700 border border-gray-300'
54
+ } shadow-lg hover:shadow-xl transform hover:-translate-y-0.5`}
55
+ >
56
+ <User className="w-5 h-5" />
57
+ <span>View Profile</span>
58
+ </button>
59
+ </div>
60
+
61
+ {/* Additional Help */}
62
+ <p className={`mt-12 text-sm ${isDark ? 'text-gray-500' : 'text-gray-500'}`}>
63
+ Need help? Contact our support team
64
+ </p>
65
+ </div>
66
+ </div>
67
+ );
68
+ };
69
+
70
+ export default NotFound;
@@ -0,0 +1,69 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useTheme } from '../contexts/ThemeContext';
3
+ import { axiosSettingsClient } from '../config/axiosClient';
4
+ import SpinningLoader from '../components/Loader';
5
+
6
+ const Settings = () => {
7
+ const { isDark } = useTheme();
8
+ const [sections, setSections] = useState([]);
9
+ const [loading, setLoading] = useState(false);
10
+ const [error, setError] = useState(null);
11
+
12
+ const fetchSettingsInfo = async () => {
13
+ setLoading(true);
14
+ setError(null);
15
+
16
+ try {
17
+ const response = await axiosSettingsClient.get('getSettingsHealth');
18
+ setSections(response.data);
19
+ } catch (err) {
20
+ setError(err.message);
21
+ } finally {
22
+ setLoading(false);
23
+ }
24
+ };
25
+
26
+ useEffect(() => {
27
+ fetchSettingsInfo();
28
+ }, []);
29
+
30
+ return (
31
+ <div className={`min-h-screen py-14 px-8 transition-colors duration-300
32
+ ${isDark ? "bg-[#0d0d0d] text-gray-200" : "bg-gray-100 text-gray-800"}`}>
33
+
34
+ <h1 className="text-4xl font-extrabold text-center mb-10 tracking-wide">
35
+ ⚙️ Settings Overview
36
+ </h1>
37
+
38
+ {loading && <div className="flex justify-center"><SpinningLoader size={50} /></div>}
39
+ {error && <p className="text-center text-red-500">{error}</p>}
40
+
41
+ <div className="grid gap-6 max-w-5xl mx-auto">
42
+ {sections.map((section, index) => (
43
+ <div key={index}
44
+ className={`p-6 rounded-2xl shadow-xl border transition-all duration-300
45
+ ${isDark
46
+ ? "bg-[#111] border-gray-800 hover:border-gray-600"
47
+ : "bg-white border-gray-200 hover:border-gray-300"}`}>
48
+
49
+ <h2 className="text-2xl font-semibold flex items-center gap-2 mb-4">
50
+ <span className="text-3xl">{section.icon}</span> {section.title}
51
+ </h2>
52
+
53
+ <ul className="space-y-2">
54
+ {section.items.map((item, i) => (
55
+ <li key={i} className="flex items-start gap-3">
56
+ <span className="text-blue-500 mt-1">•</span>
57
+ <span className="opacity-90">{item}</span>
58
+ </li>
59
+ ))}
60
+ </ul>
61
+
62
+ </div>
63
+ ))}
64
+ </div>
65
+ </div>
66
+ );
67
+ };
68
+
69
+ export default Settings;
@@ -0,0 +1,90 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: [
4
+ "./index.html",
5
+ "./src/**/*.{js,ts,jsx,tsx}",
6
+ ],
7
+ theme: {
8
+ extend: {
9
+ animation: {
10
+ 'fade-in': 'fadeIn 0.5s ease-in-out',
11
+ 'slide-in': 'slideIn 0.3s ease-out',
12
+ 'bounce-subtle': 'bounceSubtle 0.6s ease-in-out',
13
+ },
14
+ keyframes: {
15
+ fadeIn: {
16
+ '0%': { opacity: '0' },
17
+ '100%': { opacity: '1' },
18
+ },
19
+ slideIn: {
20
+ '0%': { transform: 'translateX(-100%)' },
21
+ '100%': { transform: 'translateX(0)' },
22
+ },
23
+ bounceSubtle: {
24
+ '0%, 100%': { transform: 'translateY(0)' },
25
+ '50%': { transform: 'translateY(-5px)' },
26
+ }
27
+ }
28
+ },
29
+ },
30
+ plugins: [
31
+ require('daisyui'),
32
+ ],
33
+ daisyui: {
34
+ themes: [
35
+ {
36
+ light: {
37
+ "primary": "#3b82f6",
38
+ "primary-content": "#ffffff",
39
+ "secondary": "#6366f1",
40
+ "secondary-content": "#ffffff",
41
+ "accent": "#06b6d4",
42
+ "accent-content": "#ffffff",
43
+ "neutral": "#374151",
44
+ "neutral-content": "#ffffff",
45
+ "base-100": "#ffffff",
46
+ "base-200": "#f8fafc",
47
+ "base-300": "#e2e8f0",
48
+ "base-content": "#1f2937",
49
+ "info": "#0ea5e9",
50
+ "info-content": "#ffffff",
51
+ "success": "#10b981",
52
+ "success-content": "#ffffff",
53
+ "warning": "#f59e0b",
54
+ "warning-content": "#ffffff",
55
+ "error": "#ef4444",
56
+ "error-content": "#ffffff",
57
+ },
58
+ dark: {
59
+ "primary": "#3b82f6",
60
+ "primary-content": "#ffffff",
61
+ "secondary": "#6366f1",
62
+ "secondary-content": "#ffffff",
63
+ "accent": "#06b6d4",
64
+ "accent-content": "#ffffff",
65
+ "neutral": "#1f2937",
66
+ "neutral-content": "#ffffff",
67
+ "base-100": "#0f172a",
68
+ "base-200": "#1e293b",
69
+ "base-300": "#334155",
70
+ "base-content": "#f1f5f9",
71
+ "info": "#0ea5e9",
72
+ "info-content": "#ffffff",
73
+ "success": "#10b981",
74
+ "success-content": "#ffffff",
75
+ "warning": "#f59e0b",
76
+ "warning-content": "#ffffff",
77
+ "error": "#ef4444",
78
+ "error-content": "#ffffff",
79
+ }
80
+ }
81
+ ],
82
+ darkTheme: "dark",
83
+ base: true,
84
+ styled: true,
85
+ utils: true,
86
+ prefix: "",
87
+ logs: true,
88
+ themeRoot: ":root",
89
+ },
90
+ }
@@ -0,0 +1,37 @@
1
+ import { defineConfig } from 'vite'
2
+ import react from '@vitejs/plugin-react-swc'
3
+ import tailwindcss from '@tailwindcss/vite'
4
+ import path from 'path'
5
+
6
+ // https://vite.dev/config/
7
+ export default defineConfig({
8
+ plugins: [tailwindcss(), react()],
9
+ resolve: {
10
+ alias: {
11
+ '@': path.resolve(__dirname, './src'),
12
+ },
13
+ },
14
+ css: {
15
+ preprocessorOptions: {
16
+ scss: {
17
+ additionalData: `@import "@/styles/variables.scss";`
18
+ }
19
+ }
20
+ },
21
+ server: {
22
+ port: 5173,
23
+ open: false
24
+ },
25
+ build: {
26
+ outDir: 'dist',
27
+ sourcemap: true,
28
+ rollupOptions: {
29
+ output: {
30
+ manualChunks: {
31
+ vendor: ['react', 'react-dom'],
32
+ aws: ['aws-amplify'],
33
+ }
34
+ }
35
+ }
36
+ }
37
+ })
File without changes