next-auth-mfelfelani72 0.0.16 → 0.0.18

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 (61) hide show
  1. package/dist/components/Login.d.ts +13 -4
  2. package/dist/components/Login.js +8 -8
  3. package/dist/components/Register.d.ts +1 -5
  4. package/dist/components/Register.js +25 -60
  5. package/dist/components/base/LanguageSwitcher.d.ts +1 -0
  6. package/dist/components/base/LanguageSwitcher.js +135 -0
  7. package/dist/components/demo/UiLogin.d.ts +10 -2
  8. package/dist/components/demo/UiLogin.js +5 -11
  9. package/dist/components/demo/UiRegister.d.ts +12 -2
  10. package/dist/components/demo/UiRegister.js +5 -26
  11. package/dist/configs/env.d.ts +30 -0
  12. package/dist/configs/env.js +129 -0
  13. package/dist/configs/language.d.ts +32 -0
  14. package/dist/configs/language.js +43 -0
  15. package/dist/core/auth.d.ts +11 -0
  16. package/dist/core/auth.js +33 -0
  17. package/dist/hooks/useTranslation.d.ts +4 -0
  18. package/dist/hooks/useTranslation.js +34 -0
  19. package/dist/index.d.ts +4 -10
  20. package/dist/index.js +3 -10
  21. package/dist/interfaces/dictionary.d.ts +18 -0
  22. package/dist/{Interfaces.js → interfaces/dictionary.js} +2 -2
  23. package/dist/interfaces/global.d.ts +65 -0
  24. package/dist/interfaces/global.js +1 -0
  25. package/dist/{libs → libraries/auth}/loginHandler.d.ts +1 -7
  26. package/dist/libraries/auth/loginHandler.js +55 -0
  27. package/dist/libraries/cn.d.ts +1 -0
  28. package/dist/libraries/cn.js +12 -0
  29. package/dist/libraries/debounce.d.ts +10 -0
  30. package/dist/libraries/debounce.js +17 -0
  31. package/dist/libraries/detectComponentResponsive.d.ts +10 -0
  32. package/dist/libraries/detectComponentResponsive.js +24 -0
  33. package/dist/libraries/detectDeviceFromUA.d.ts +8 -0
  34. package/dist/libraries/detectDeviceFromUA.js +14 -0
  35. package/dist/libraries/fonts.d.ts +10 -0
  36. package/dist/libraries/fonts.js +93 -0
  37. package/dist/libraries/translation.d.ts +15 -0
  38. package/dist/libraries/translation.js +70 -0
  39. package/dist/locale/auth/en.json +30 -0
  40. package/dist/locale/auth/fa.json +34 -0
  41. package/dist/locale/en.d.ts +38 -0
  42. package/dist/locale/en.js +10 -0
  43. package/dist/locale/fa.d.ts +42 -0
  44. package/dist/locale/fa.js +10 -0
  45. package/dist/locale/index.d.ts +131 -0
  46. package/dist/locale/index.js +14 -0
  47. package/dist/proxy.d.ts +14 -0
  48. package/dist/proxy.js +58 -0
  49. package/dist/stores/AppStore.d.ts +53 -0
  50. package/dist/stores/AppStore.js +141 -0
  51. package/dist/stores/LangStore.d.ts +10 -0
  52. package/dist/stores/LangStore.js +87 -0
  53. package/dist/types.d.ts +10 -0
  54. package/dist/types.js +1 -0
  55. package/dist/utilities/app/cookieUtils.d.ts +20 -0
  56. package/dist/utilities/app/cookieUtils.js +98 -0
  57. package/package.json +21 -15
  58. package/dist/Interfaces.d.ts +0 -47
  59. package/dist/libs/loginHandler.js +0 -37
  60. package/dist/libs/registerHandler.d.ts +0 -11
  61. package/dist/libs/registerHandler.js +0 -49
@@ -1,5 +1,14 @@
1
1
  import React from "react";
2
- import type { LoginInterface, ClientLoginInterface } from "../Interfaces";
3
- export default function Login({ loginRoute, onGoogleLogin, UiComponent, dict, lang, }: LoginInterface & {
4
- UiComponent?: React.ComponentType<ClientLoginInterface>;
5
- }): import("react/jsx-runtime").JSX.Element;
2
+ import type { LoginProps } from "../types";
3
+ interface LoginComponentProps {
4
+ onSubmit: (formData: FormData) => void;
5
+ errors?: {
6
+ username?: string;
7
+ password?: string;
8
+ };
9
+ message?: string | null;
10
+ }
11
+ export default function Login({ loginRoute, UiComponent, }: LoginProps & {
12
+ UiComponent?: React.ComponentType<LoginComponentProps>;
13
+ }): React.JSX.Element;
14
+ export {};
@@ -2,15 +2,15 @@
2
2
  * @Author: Mohammad Felfelani
3
3
  * @Email: mfelfelani72@gmail.com
4
4
  * @Team:
5
- * @Date: 2025-10-02 08:02:55
5
+ * @Date: 2025-12-31 06:00:17
6
6
  * @Description:
7
7
  */
8
8
  "use client";
9
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
9
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
10
10
  import { useState } from "react";
11
11
  // Components
12
12
  import UiLogin from "./demo/UiLogin";
13
- export default function Login({ loginRoute, onGoogleLogin, UiComponent, dict, lang, }) {
13
+ export default function Login({ loginRoute, UiComponent, }) {
14
14
  // States
15
15
  const [errors, setErrors] = useState({});
16
16
  const [message, setMessage] = useState(null);
@@ -19,12 +19,12 @@ export default function Login({ loginRoute, onGoogleLogin, UiComponent, dict, la
19
19
  const handleSubmit = async (formData) => {
20
20
  setMessage(null);
21
21
  setErrors({});
22
- const username = formData.get("username") || "";
22
+ const email = formData.get("username") || "";
23
23
  const password = formData.get("password") || "";
24
24
  const newErrors = {};
25
- if (!username.trim())
25
+ if (!email.trim())
26
26
  newErrors.username = "Username is required";
27
- else if (username.length < 3)
27
+ else if (email.length < 3)
28
28
  newErrors.username = "Username must be at least 3 characters";
29
29
  if (!password)
30
30
  newErrors.password = "Password is required";
@@ -40,7 +40,7 @@ export default function Login({ loginRoute, onGoogleLogin, UiComponent, dict, la
40
40
  const res = await fetch(loginRoute, {
41
41
  method: "POST",
42
42
  headers: { "Content-Type": "application/json" },
43
- body: JSON.stringify({ email: username, password }),
43
+ body: JSON.stringify({ email, password }),
44
44
  });
45
45
  const data = await res.json();
46
46
  if (!res.ok) {
@@ -57,5 +57,5 @@ export default function Login({ loginRoute, onGoogleLogin, UiComponent, dict, la
57
57
  }
58
58
  };
59
59
  const RenderUi = UiComponent || UiLogin;
60
- return (_jsxs(_Fragment, { children: [_jsx(RenderUi, { onSubmit: handleSubmit, errors: errors, message: message }), loading && (_jsx("p", { className: "text-center text-gray-200 mt-2", children: "Logging in..." })), onGoogleLogin && (_jsx("div", { className: "flex justify-center mt-4", children: _jsx("button", { onClick: onGoogleLogin, className: "px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition", children: "Sign in with Google" }) }))] }));
60
+ return (_jsx(_Fragment, { children: _jsx("div", { className: "relative z-10 w-full max-w-md px-4", children: _jsx(RenderUi, { onSubmit: handleSubmit, errors: errors, message: message }) }) }));
61
61
  }
@@ -1,5 +1 @@
1
- import React from "react";
2
- import type { RegisterInterface, ClientRegisterInterface } from "../Interfaces";
3
- export default function Register({ registerRoute, onGoogleRegister, UiComponent, dict, lang, }: RegisterInterface & {
4
- UiComponent?: React.ComponentType<ClientRegisterInterface>;
5
- }): import("react/jsx-runtime").JSX.Element;
1
+ export default function Register(): import("react").JSX.Element;
@@ -1,76 +1,41 @@
1
- /*
2
- * @Author: Mohammad Felfelani
3
- * @Email: mfelfelani72@gmail.com
4
- * @Team:
5
- * @Date: 2025-10-02 06:57:46
6
- * @Description:
7
- */
8
1
  "use client";
9
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
10
3
  import { useState } from "react";
11
- // Components
12
4
  import UiRegister from "./demo/UiRegister";
13
- export default function Register({ registerRoute, onGoogleRegister, UiComponent, dict, lang, }) {
14
- // States
5
+ export default function Register() {
15
6
  const [errors, setErrors] = useState({});
16
7
  const [message, setMessage] = useState(null);
17
- const [loading, setLoading] = useState(false);
18
- // Functions
19
- const handleSubmit = async (formData) => {
20
- setMessage(null);
21
- setErrors({});
22
- const name = formData.get("name") || "";
23
- const email = formData.get("email") || "";
24
- const password = formData.get("password") || "";
25
- const password_confirmation = formData.get("password_confirmation") || "";
8
+ const validate = (formData) => {
9
+ var _a, _b, _c, _d;
26
10
  const newErrors = {};
27
- if (!name.trim())
11
+ const name = (_a = formData.get("name")) === null || _a === void 0 ? void 0 : _a.toString().trim();
12
+ const email = (_b = formData.get("email")) === null || _b === void 0 ? void 0 : _b.toString().trim();
13
+ const password = (_c = formData.get("password")) === null || _c === void 0 ? void 0 : _c.toString();
14
+ const confirmPassword = (_d = formData.get("confirmPassword")) === null || _d === void 0 ? void 0 : _d.toString();
15
+ if (!name)
28
16
  newErrors.name = "Name is required";
29
- else if (name.length < 2)
30
- newErrors.name = "Name must be at least 2 characters";
31
- if (!email.trim())
17
+ if (!email)
32
18
  newErrors.email = "Email is required";
33
- else if (!/\S+@\S+\.\S+/.test(email))
34
- newErrors.email = "Email is invalid";
35
19
  if (!password)
36
20
  newErrors.password = "Password is required";
37
21
  else if (password.length < 6)
38
22
  newErrors.password = "Password must be at least 6 characters";
39
- if (!password_confirmation)
40
- newErrors.password_confirmation = "Please confirm your password";
41
- else if (password !== password_confirmation)
42
- newErrors.password_confirmation = "Passwords do not match";
43
- if (Object.keys(newErrors).length > 0) {
44
- setErrors(newErrors);
45
- setMessage("Please fix the errors below.");
46
- return;
47
- }
48
- setLoading(true);
49
- try {
50
- const res = await fetch(registerRoute, {
51
- method: "POST",
52
- headers: { "Content-Type": "application/json" },
53
- body: JSON.stringify({
54
- name,
55
- email,
56
- password,
57
- password_confirmation,
58
- }),
59
- });
60
- const data = await res.json();
61
- if (!res.ok) {
62
- setMessage((data === null || data === void 0 ? void 0 : data.message) || "Registration failed");
63
- return;
64
- }
65
- setMessage((data === null || data === void 0 ? void 0 : data.message) || "Registration successful");
66
- }
67
- catch (err) {
68
- setMessage((err === null || err === void 0 ? void 0 : err.message) || "Network error");
23
+ if (!confirmPassword)
24
+ newErrors.confirmPassword = "Confirm your password";
25
+ else if (password !== confirmPassword)
26
+ newErrors.confirmPassword = "Passwords do not match";
27
+ return newErrors;
28
+ };
29
+ const handleSubmit = (formData) => {
30
+ const validationErrors = validate(formData);
31
+ setErrors(validationErrors);
32
+ if (Object.keys(validationErrors).length === 0) {
33
+ setMessage(null);
34
+ // onSubmitServer(formData);
69
35
  }
70
- finally {
71
- setLoading(false);
36
+ else {
37
+ setMessage("Please fix the errors below.");
72
38
  }
73
39
  };
74
- const RenderUi = UiComponent || UiRegister;
75
- return (_jsxs(_Fragment, { children: [_jsx(RenderUi, { onSubmit: handleSubmit, errors: errors, message: message, dict: dict, lang: lang }), loading && (_jsx("p", { className: "text-center text-gray-200 mt-2", children: "Registering..." })), onGoogleRegister && (_jsx("div", { className: "flex justify-center mt-4", children: _jsx("button", { onClick: onGoogleRegister, className: "px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition", children: "Sign up with Google" }) }))] }));
40
+ return (_jsx(UiRegister, { onSubmit: handleSubmit, errors: errors, message: message }));
76
41
  }
@@ -0,0 +1 @@
1
+ export default function LanguageSwitcher(): import("react").JSX.Element;
@@ -0,0 +1,135 @@
1
+ /*
2
+ * @Author: Mohammad Felfelani
3
+ * @Email: mfelfelani72@gmail.com
4
+ * @Team:
5
+ * @Date: 2025-10-08 10:10:51
6
+ * @Description: Language Switcher with Glassmorphism Style
7
+ */
8
+ "use client";
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ import { useRouter, usePathname } from "next/navigation";
11
+ import { useState, useRef, useEffect } from "react";
12
+ // Components
13
+ import { LanguageIcon } from "forma-ui";
14
+ // Zustand
15
+ import { useLangStore } from "@/stores/LangStore";
16
+ // Interfaces
17
+ import { languages, getNativeName, getFlag, } from "@/configs/language";
18
+ export default function LanguageSwitcher() {
19
+ // Hooks
20
+ const router = useRouter();
21
+ const pathname = usePathname();
22
+ // States
23
+ const { lang, setLang } = useLangStore();
24
+ const [pendingLang, setPendingLang] = useState(null);
25
+ // States and Refs
26
+ const [isOpen, setIsOpen] = useState(false);
27
+ const [menuPos, setMenuPos] = useState({
28
+ top: 0,
29
+ left: 0,
30
+ width: 0,
31
+ position: "bottom",
32
+ });
33
+ const btnRef = useRef(null);
34
+ const menuRef = useRef(null);
35
+ // Functions
36
+ const getNewPath = (newLang) => {
37
+ const segments = pathname.split("/").filter(Boolean);
38
+ if (segments.length > 0 && segments[0] in languages) {
39
+ segments[0] = newLang;
40
+ }
41
+ else {
42
+ segments.unshift(newLang);
43
+ }
44
+ return "/" + segments.join("/");
45
+ };
46
+ const handleChange = (newLang) => {
47
+ if (newLang === lang)
48
+ return;
49
+ const newPath = getNewPath(newLang);
50
+ setPendingLang(newLang);
51
+ setIsOpen(false);
52
+ router.replace(newPath);
53
+ };
54
+ useEffect(() => {
55
+ if (pendingLang && pathname) {
56
+ const currentLangFromUrl = pathname.split("/").filter(Boolean)[0];
57
+ if (currentLangFromUrl === pendingLang) {
58
+ setLang(pendingLang);
59
+ setPendingLang(null);
60
+ }
61
+ }
62
+ }, [pathname, pendingLang, setLang]);
63
+ useEffect(() => {
64
+ if (isOpen && btnRef.current) {
65
+ const rect = btnRef.current.getBoundingClientRect();
66
+ const menuWidth = rect.width + 50;
67
+ const menuHeight = Object.keys(languages).length * 48 + 16;
68
+ let left = rect.left - 25;
69
+ let horizontalPosition = "left";
70
+ if (left + menuWidth > window.innerWidth) {
71
+ left = window.innerWidth - menuWidth - 10;
72
+ horizontalPosition = "right";
73
+ }
74
+ if (left < 10) {
75
+ left = 10;
76
+ }
77
+ let top = rect.bottom + 8;
78
+ let verticalPosition = "bottom";
79
+ if (top + menuHeight > window.innerHeight - 10) {
80
+ top = rect.top - menuHeight - 16;
81
+ verticalPosition = "top";
82
+ }
83
+ if (top < 10) {
84
+ top = 10;
85
+ }
86
+ setMenuPos({
87
+ top,
88
+ left,
89
+ width: menuWidth,
90
+ position: verticalPosition === "top" ? "top" : "bottom",
91
+ });
92
+ }
93
+ }, [isOpen]);
94
+ useEffect(() => {
95
+ const handleClickOutside = (event) => {
96
+ if (btnRef.current &&
97
+ !btnRef.current.contains(event.target) &&
98
+ menuRef.current &&
99
+ !menuRef.current.contains(event.target)) {
100
+ setIsOpen(false);
101
+ }
102
+ };
103
+ document.addEventListener("mousedown", handleClickOutside);
104
+ return () => {
105
+ document.removeEventListener("mousedown", handleClickOutside);
106
+ };
107
+ }, []);
108
+ const getMenuAnimationClass = () => {
109
+ switch (menuPos.position) {
110
+ case "top":
111
+ return "origin-bottom scale-95";
112
+ case "bottom":
113
+ default:
114
+ return "origin-top scale-95";
115
+ }
116
+ };
117
+ return (_jsxs("div", { className: "relative inline-block", children: [_jsxs("button", { ref: btnRef, onClick: () => setIsOpen((prev) => !prev), className: "flex items-center gap-2 px-3 py-1.5 rounded-lg transition-all duration-300 cursor-pointer\n bg-white/10 dark:bg-Neutral-700/40\n backdrop-blur-md backdrop-saturate-150\n border border-white/40 dark:border-Neutral-600/30\n shadow-[0_8px_32px_rgba(0,0,0,0.08)] dark:shadow-[0_8px_32px_rgba(0,0,0,0.3)]\n hover:bg-white/50 dark:hover:bg-Neutral-600/50\n hover:shadow-[0_8px_32px_rgba(0,0,0,0.12)] dark:hover:shadow-[0_8px_32px_rgba(0,0,0,0.4)]\n hover:border-white/60 dark:hover:border-Neutral-500/40", children: [_jsx("span", { className: "text-md", children: _jsx(LanguageIcon, { className: "text-Neutral-100" }) }), _jsx("svg", { className: `w-4 h-4 text-Neutral-100 transition-transform duration-300 ${isOpen ? "rotate-180" : ""}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), isOpen && (_jsx("div", { ref: menuRef, className: `fixed py-2 rounded-xl transition-all duration-200 transform ${getMenuAnimationClass()}
118
+ bg-white/70 dark:bg-Neutral-800/50
119
+ backdrop-blur-xl backdrop-saturate-150
120
+ border border-white/50 dark:border-Neutral-600/30
121
+ shadow-[0_20px_60px_rgba(0,0,0,0.15)] dark:shadow-[0_20px_60px_rgba(0,0,0,0.4)]
122
+ before:absolute before:inset-0 before:rounded-xl before:pointer-events-none
123
+ before:bg-linear-to-br before:from-white/20 before:to-transparent before:opacity-50`, style: {
124
+ top: menuPos.top,
125
+ left: menuPos.left,
126
+ width: menuPos.width,
127
+ }, children: Object.keys(languages).map((l) => {
128
+ const currentLang = l;
129
+ const isActive = currentLang === lang;
130
+ return (_jsxs("button", { onClick: () => handleChange(currentLang), disabled: isActive, className: `w-full flex items-center gap-3 px-4 py-3 text-left transition-all duration-200
131
+ ${isActive
132
+ ? "text-primary-600 dark:text-primary-400 cursor-default bg-white/20 dark:bg-white/10"
133
+ : "text-Neutral-400 hover:text-primary-600 dark:hover:text-primary-400 hover:bg-white/30 dark:hover:bg-Neutral-700/40 cursor-pointer"}`, children: [_jsx("span", { className: "text-lg", children: getFlag(currentLang) }), _jsx("span", { className: "font-medium", children: getNativeName(currentLang) }), isActive && (_jsx("div", { className: "w-2 h-2 bg-primary-500 dark:bg-primary-400 rounded-full ml-auto shadow-[0_0_12px_rgba(99,102,241,0.4)]" }))] }, currentLang));
134
+ }) }))] }));
135
+ }
@@ -1,2 +1,10 @@
1
- import { ClientLoginInterface } from "@/Interfaces";
2
- export default function UiLogin({ onSubmit, errors, message, }: ClientLoginInterface): import("react/jsx-runtime").JSX.Element;
1
+ interface ClientLoginProps {
2
+ onSubmit: (formData: FormData) => void;
3
+ errors?: {
4
+ username?: string;
5
+ password?: string;
6
+ };
7
+ message?: string | null;
8
+ }
9
+ export default function UiLogin({ onSubmit, errors, message, }: ClientLoginProps): import("react").JSX.Element;
10
+ export {};
@@ -1,26 +1,20 @@
1
- /*
2
- * @Author: Mohammad Felfelani
3
- * @Email: mfelfelani72@gmail.com
4
- * @Team:
5
- * @Date: 2025-10-02 08:04:22
6
- * @Description:
7
- */
8
1
  "use client";
9
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
3
  import { useState, useEffect } from "react";
11
4
  import Image from "next/image";
12
5
  import Link from "next/link";
6
+ import { useTranslation } from "@/hooks/useTranslation";
13
7
  export default function UiLogin({ onSubmit, errors, message, }) {
14
- // States
8
+ const { t } = useTranslation();
15
9
  const [visible, setVisible] = useState(false);
16
- // Functions
17
10
  useEffect(() => {
11
+ // trigger the animation on mount
18
12
  setVisible(true);
19
13
  }, []);
20
14
  return (_jsx("div", { className: "fixed inset-0 overflow-hidden flex items-center justify-center bg-gradient-to-br from-purple-900 via-purple-800 to-black p-4", children: _jsxs("div", { className: `w-full max-w-md bg-white/20 backdrop-blur-md rounded-2xl shadow-xl p-8 border border-white/30
21
15
  transform transition-all duration-700 ease-out
22
16
  ${visible ? "opacity-100 scale-100" : "opacity-0 scale-95"}
23
- `, children: [_jsx("div", { className: "flex justify-center mb-6", children: _jsx(Image, { src: "/logo.png", alt: "Logo", width: 80, height: 80, className: "rounded-full shadow" }) }), _jsx("h1", { className: "text-2xl font-bold text-center text-white mb-2", children: "Welcome Back" }), _jsx("p", { className: "text-center text-gray-200 mb-6 text-sm", children: "Login with your credentials to continue" }), message && (_jsx("div", { role: "alert", className: "mb-4 text-center text-red-300 font-medium", children: message })), _jsxs("form", { onSubmit: (e) => {
17
+ `, children: [_jsx("div", { className: "relative w-40 h-20 mx-auto mb-8", children: _jsx(Image, { src: "/images/png/logo.png", alt: "Logo", fill: true, sizes: "auto", className: "object-contain", priority: true }) }), _jsx("h1", { className: "text-2xl font-bold text-center text-white mb-2", children: t("login") }), _jsx("p", { className: "text-center text-gray-200 mb-6 text-sm", children: "Login with your credentials to continue" }), message && (_jsx("div", { role: "alert", className: "mb-4 text-center text-red-300 font-medium", children: message })), _jsxs("form", { onSubmit: (e) => {
24
18
  e.preventDefault();
25
19
  const formData = new FormData(e.currentTarget);
26
20
  onSubmit(formData);
@@ -28,5 +22,5 @@ export default function UiLogin({ onSubmit, errors, message, }) {
28
22
  ? "border-red-500"
29
23
  : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.username) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.username }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "password", className: "block text-sm font-medium text-white mb-1", children: "Password" }), _jsx("input", { id: "password", name: "password", type: "password", placeholder: "Enter your password", required: true, className: `w-full px-4 py-2 rounded-lg bg-white/20 focus:bg-white/30 border focus:outline-none focus:ring-2 text-white placeholder-gray-200 ${(errors === null || errors === void 0 ? void 0 : errors.password)
30
24
  ? "border-red-500"
31
- : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.password) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.password }))] }), _jsx("button", { type: "submit", className: "w-full py-2 bg-purple-700/80 text-white rounded-lg hover:bg-purple-800 transition", children: "Log In" }), _jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [_jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-red-500 hover:bg-red-600 text-white transition font-bold text-lg", children: "G" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-600 hover:bg-blue-700 text-white transition font-bold text-lg", children: "F" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-400 hover:bg-blue-500 text-white transition font-bold text-lg", children: "T" })] }), _jsxs("p", { className: "text-center text-sm text-gray-200 mt-4", children: ["Don\u2019t have an account?", " ", _jsx(Link, { href: "/en/register", className: "underline hover:text-white", scroll: false, children: "Register" })] })] })] }) }));
25
+ : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.password) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.password }))] }), _jsx("button", { type: "submit", className: "w-full py-2 bg-purple-700/80 text-white rounded-lg hover:bg-purple-800 transition", children: "Log In" }), _jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [_jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-red-500 hover:bg-red-600 text-white transition font-bold text-lg", children: "G" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-600 hover:bg-blue-700 text-white transition font-bold text-lg", children: "F" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-400 hover:bg-blue-500 text-white transition font-bold text-lg", children: "T" })] }), _jsxs("p", { className: "text-center text-sm text-gray-200 mt-4", children: ["Don\u2019t have an account?", " ", _jsx(Link, { href: "/en/register", className: "underline hover:text-white", children: "Register" })] })] })] }) }));
32
26
  }
@@ -1,2 +1,12 @@
1
- import { ClientRegisterInterface } from "@/Interfaces";
2
- export default function UiRegister({ onSubmit, errors, message, dict, lang, }: ClientRegisterInterface): import("react/jsx-runtime").JSX.Element;
1
+ interface UiRegisterProps {
2
+ onSubmit: (formData: FormData) => void;
3
+ errors?: {
4
+ name?: string;
5
+ email?: string;
6
+ password?: string;
7
+ confirmPassword?: string;
8
+ };
9
+ message?: string | null;
10
+ }
11
+ export default function UiRegister({ onSubmit, errors, message, }: UiRegisterProps): import("react").JSX.Element;
12
+ export {};
@@ -1,36 +1,15 @@
1
- /*
2
- * @Author: Mohammad Felfelani
3
- * @Email: mfelfelani72@gmail.com
4
- * @Team:
5
- * @Date: 2025-10-02 08:04:22
6
- * @Description:
7
- */
8
1
  "use client";
9
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
3
  import { useState, useEffect } from "react";
11
4
  import Image from "next/image";
12
5
  import Link from "next/link";
13
- export default function UiRegister({ onSubmit, errors, message, dict, lang, }) {
14
- // States
6
+ export default function UiRegister({ onSubmit, errors, message, }) {
15
7
  const [visible, setVisible] = useState(false);
16
- // Functions
17
8
  useEffect(() => {
18
- setVisible(true);
9
+ setVisible(true); // simple fade+scale animation
19
10
  }, []);
20
- return (_jsx("div", { className: "fixed inset-0 overflow-hidden flex items-center justify-center bg-gradient-to-br from-purple-900 via-purple-800 to-black p-4", children: _jsxs("div", { className: `w-full max-w-md bg-white/20 backdrop-blur-md rounded-2xl shadow-xl p-8 border border-white/30
21
- transform transition-all duration-700 ease-out
22
- ${visible ? "opacity-100 scale-100" : "opacity-0 scale-95"}
23
- `, children: [_jsx("div", { className: "flex justify-center mb-6", children: _jsx(Image, { src: "/logo.png", alt: "Logo", width: 80, height: 80, className: "rounded-full shadow" }) }), _jsx("h1", { className: "text-2xl font-bold text-center text-white mb-2", children: "Create Account" }), _jsx("p", { className: "text-center text-gray-200 mb-6 text-sm", children: "Sign up to get started" }), message && (_jsx("div", { role: "alert", className: "mb-4 text-center text-red-300 font-medium", children: message })), _jsxs("form", { onSubmit: (e) => {
11
+ return (_jsx("div", { className: "fixed inset-0 flex items-center justify-center bg-gradient-to-br from-purple-900 via-purple-800 to-black p-4", children: _jsxs("div", { className: `w-full max-w-md bg-white/20 backdrop-blur-md rounded-2xl shadow-xl p-8 border border-white/30 transform transition-all duration-700 ease-out ${visible ? "opacity-100 scale-100" : "opacity-0 scale-95"}`, children: [_jsx("div", { className: "flex justify-center mb-6", children: _jsx(Image, { src: "/logo.png", alt: "Logo", width: 80, height: 80, className: "rounded-full shadow" }) }), _jsx("h1", { className: "text-2xl font-bold text-center text-white mb-2", children: "Create Account" }), _jsx("p", { className: "text-center text-gray-200 mb-6 text-sm", children: "Sign up to get started" }), message && (_jsx("div", { role: "alert", className: "mb-4 text-center text-red-300 font-medium", children: message })), _jsxs("form", { onSubmit: (e) => {
24
12
  e.preventDefault();
25
- const formData = new FormData(e.currentTarget);
26
- onSubmit(formData);
27
- }, noValidate: true, className: "space-y-5", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: "name", className: "block text-sm font-medium text-white mb-1", children: "Full Name" }), _jsx("input", { id: "name", name: "name", type: "text", placeholder: "Enter your full name", required: true, className: `w-full px-4 py-2 rounded-lg bg-white/20 focus:bg-white/30 border focus:outline-none focus:ring-2 text-white placeholder-gray-200 ${(errors === null || errors === void 0 ? void 0 : errors.name)
28
- ? "border-red-500"
29
- : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.name) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.name }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "email", className: "block text-sm font-medium text-white mb-1", children: "Email" }), _jsx("input", { id: "email", name: "email", type: "email", placeholder: "Enter your email", required: true, className: `w-full px-4 py-2 rounded-lg bg-white/20 focus:bg-white/30 border focus:outline-none focus:ring-2 text-white placeholder-gray-200 ${(errors === null || errors === void 0 ? void 0 : errors.email)
30
- ? "border-red-500"
31
- : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.email) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.email }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "password", className: "block text-sm font-medium text-white mb-1", children: "Password" }), _jsx("input", { id: "password", name: "password", type: "password", placeholder: "Enter your password", required: true, className: `w-full px-4 py-2 rounded-lg bg-white/20 focus:bg-white/30 border focus:outline-none focus:ring-2 text-white placeholder-gray-200 ${(errors === null || errors === void 0 ? void 0 : errors.password)
32
- ? "border-red-500"
33
- : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.password) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.password }))] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "password_confirmation", className: "block text-sm font-medium text-white mb-1", children: "Confirm Password" }), _jsx("input", { id: "password_confirmation", name: "password_confirmation", type: "password", placeholder: "Confirm your password", required: true, className: `w-full px-4 py-2 rounded-lg bg-white/20 focus:bg-white/30 border focus:outline-none focus:ring-2 text-white placeholder-gray-200 ${(errors === null || errors === void 0 ? void 0 : errors.password_confirmation)
34
- ? "border-red-500"
35
- : "border-gray-300 focus:ring-purple-400"}` }), (errors === null || errors === void 0 ? void 0 : errors.password_confirmation) && (_jsx("p", { className: "mt-1 text-sm text-red-300", children: errors.password_confirmation }))] }), _jsx("button", { type: "submit", className: "w-full py-2 bg-purple-700/80 text-white rounded-lg hover:bg-purple-800 transition", children: "Sign Up" }), _jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [_jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-red-500 hover:bg-red-600 text-white transition font-bold text-lg", children: "G" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-600 hover:bg-blue-700 text-white transition font-bold text-lg", children: "F" }), _jsx("button", { type: "button", className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-400 hover:bg-blue-500 text-white transition font-bold text-lg", children: "T" })] }), _jsxs("p", { className: "text-center text-sm text-gray-200 mt-4", children: ["Already have an account?", " ", _jsx(Link, { href: `/${lang}/login`, className: "underline hover:text-white", scroll: false, children: "Login" })] })] })] }) }));
13
+ onSubmit(new FormData(e.currentTarget));
14
+ }, className: "space-y-5", children: [_jsx("input", { name: "name", placeholder: "Full Name", className: "w-full px-4 py-2 rounded-lg bg-white/20 text-white placeholder-gray-200" }), _jsx("input", { name: "email", type: "email", placeholder: "Email", className: "w-full px-4 py-2 rounded-lg bg-white/20 text-white placeholder-gray-200" }), _jsx("input", { name: "password", type: "password", placeholder: "Password", className: "w-full px-4 py-2 rounded-lg bg-white/20 text-white placeholder-gray-200" }), _jsx("input", { name: "confirmPassword", type: "password", placeholder: "Confirm Password", className: "w-full px-4 py-2 rounded-lg bg-white/20 text-white placeholder-gray-200" }), _jsx("button", { type: "submit", className: "w-full py-2 bg-purple-700/80 text-white rounded-lg hover:bg-purple-800 transition", children: "Sign Up" })] }), _jsxs("div", { className: "flex justify-center gap-4 mt-4", children: [_jsx("button", { className: "flex items-center justify-center w-10 h-10 rounded-full bg-red-500 hover:bg-red-600 text-white font-bold text-lg transition", children: "G" }), _jsx("button", { className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-600 hover:bg-blue-700 text-white font-bold text-lg transition", children: "F" }), _jsx("button", { className: "flex items-center justify-center w-10 h-10 rounded-full bg-blue-400 hover:bg-blue-500 text-white font-bold text-lg transition", children: "T" })] }), _jsxs("p", { className: "text-center text-sm text-gray-200 mt-4", children: ["Already have an account?", " ", _jsx(Link, { href: "/en/login", className: "underline hover:text-white", children: "Log in" })] })] }) }));
36
15
  }
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ declare const serverSchema: z.ZodObject<{
3
+ AUTH_SECRET: z.ZodString;
4
+ DATABASE_URL: z.ZodString;
5
+ NEXTAUTH_URL: z.ZodOptional<z.ZodString>;
6
+ }, z.core.$strip>;
7
+ declare const clientSchema: z.ZodObject<{
8
+ NEXT_PUBLIC_APP_URL: z.ZodString;
9
+ NEXT_PUBLIC_API_URL: z.ZodString;
10
+ }, z.core.$strip>;
11
+ export type ServerEnv = z.infer<typeof serverSchema>;
12
+ export type ClientEnv = z.infer<typeof clientSchema>;
13
+ declare class EnvManager {
14
+ private _server;
15
+ private _client;
16
+ private _serverValidationErrors;
17
+ private _clientValidationErrors;
18
+ private _initialized;
19
+ private validate;
20
+ get server(): ServerEnv;
21
+ get client(): ClientEnv;
22
+ isServerValid(): boolean;
23
+ isClientValid(): boolean;
24
+ getServerErrors(): z.ZodError | null;
25
+ getClientErrors(): z.ZodError | null;
26
+ reset(): void;
27
+ }
28
+ export declare const env: EnvManager;
29
+ export declare function checkEnv(): boolean;
30
+ export {};
@@ -0,0 +1,129 @@
1
+ // src/config/env.ts
2
+ import { z } from "zod";
3
+ // Define schemas
4
+ const serverSchema = z.object({
5
+ AUTH_SECRET: z.string().min(32, "AUTH_SECRET must be at least 32 characters"),
6
+ DATABASE_URL: z.string().url("DATABASE_URL must be a valid URL"),
7
+ NEXTAUTH_URL: z.string().url().optional(),
8
+ });
9
+ const clientSchema = z.object({
10
+ NEXT_PUBLIC_APP_URL: z.string().url("NEXT_PUBLIC_APP_URL must be a valid URL"),
11
+ NEXT_PUBLIC_API_URL: z.string().url("NEXT_PUBLIC_API_URL must be a valid URL"),
12
+ });
13
+ // Helper to safely validate
14
+ function validateEnv(schema, env) {
15
+ const result = schema.safeParse(env);
16
+ if (result.success) {
17
+ return { success: true, data: result.data };
18
+ }
19
+ return { success: false, errors: result.error };
20
+ }
21
+ // Lazy validation - only runs when accessed
22
+ class EnvManager {
23
+ constructor() {
24
+ this._server = null;
25
+ this._client = null;
26
+ this._serverValidationErrors = null;
27
+ this._clientValidationErrors = null;
28
+ this._initialized = false;
29
+ }
30
+ validate() {
31
+ if (this._initialized)
32
+ return;
33
+ // Validate server env
34
+ const serverResult = validateEnv(serverSchema, process.env);
35
+ if (serverResult.success) {
36
+ this._server = serverResult.data;
37
+ }
38
+ else {
39
+ this._serverValidationErrors = serverResult.errors;
40
+ }
41
+ // Validate client env
42
+ const clientResult = validateEnv(clientSchema, process.env);
43
+ if (clientResult.success) {
44
+ this._client = clientResult.data;
45
+ }
46
+ else {
47
+ this._clientValidationErrors = clientResult.errors;
48
+ }
49
+ this._initialized = true;
50
+ }
51
+ get server() {
52
+ var _a;
53
+ this.validate();
54
+ if (this._server) {
55
+ return this._server;
56
+ }
57
+ throw new Error(`Missing or invalid server environment variables:\n` +
58
+ ((_a = this._serverValidationErrors) === null || _a === void 0 ? void 0 : _a.issues.map(i => ` - ${i.path.join('.')}: ${i.message}`).join('\n')) +
59
+ `\n\nPlease add these to your .env.local file.`);
60
+ }
61
+ get client() {
62
+ var _a;
63
+ this.validate();
64
+ if (this._client) {
65
+ return this._client;
66
+ }
67
+ throw new Error(`Missing or invalid client environment variables:\n` +
68
+ ((_a = this._clientValidationErrors) === null || _a === void 0 ? void 0 : _a.issues.map(i => ` - ${i.path.join('.')}: ${i.message}`).join('\n')) +
69
+ `\n\nPlease add these to your .env.local file.`);
70
+ }
71
+ // Check if all env vars are valid without throwing
72
+ isServerValid() {
73
+ this.validate();
74
+ return this._server !== null;
75
+ }
76
+ isClientValid() {
77
+ this.validate();
78
+ return this._client !== null;
79
+ }
80
+ // Get validation errors without throwing
81
+ getServerErrors() {
82
+ this.validate();
83
+ return this._serverValidationErrors;
84
+ }
85
+ getClientErrors() {
86
+ this.validate();
87
+ return this._clientValidationErrors;
88
+ }
89
+ // Reset validation (useful for testing)
90
+ reset() {
91
+ this._initialized = false;
92
+ this._server = null;
93
+ this._client = null;
94
+ this._serverValidationErrors = null;
95
+ this._clientValidationErrors = null;
96
+ }
97
+ }
98
+ // Singleton instance
99
+ export const env = new EnvManager();
100
+ // Helper for package consumers to check their env
101
+ export function checkEnv() {
102
+ const errors = [];
103
+ if (!env.isServerValid()) {
104
+ const serverErrors = env.getServerErrors();
105
+ if (serverErrors) {
106
+ errors.push('Server environment variables:');
107
+ serverErrors.issues.forEach(issue => {
108
+ errors.push(` - ${issue.path.join('.')}: ${issue.message}`);
109
+ });
110
+ }
111
+ }
112
+ if (!env.isClientValid()) {
113
+ const clientErrors = env.getClientErrors();
114
+ if (clientErrors) {
115
+ errors.push('Client environment variables:');
116
+ clientErrors.issues.forEach(issue => {
117
+ errors.push(` - ${issue.path.join('.')}: ${issue.message}`);
118
+ });
119
+ }
120
+ }
121
+ if (errors.length > 0) {
122
+ console.warn('⚠️ Environment variable validation issues found:');
123
+ console.warn(errors.join('\n'));
124
+ console.warn('\nPlease add the required variables to your .env.local file');
125
+ return false;
126
+ }
127
+ console.log('✅ All environment variables are valid!');
128
+ return true;
129
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @Author: Mohammad Felfelani
3
+ * @Email: mfelfelani72@gmail.com
4
+ * @Team:
5
+ * @Date: 2025-10-04 07:17:02
6
+ * @Description:
7
+ */
8
+ export declare const languages: {
9
+ readonly en: {
10
+ readonly dir: "ltr";
11
+ readonly locale: "en_US";
12
+ readonly schemaLocale: "en-US";
13
+ readonly name: "English";
14
+ readonly flag: "🇺🇸";
15
+ readonly nativeName: "English";
16
+ };
17
+ readonly fa: {
18
+ readonly dir: "rtl";
19
+ readonly locale: "fa_IR";
20
+ readonly schemaLocale: "fa-IR";
21
+ readonly name: "Persian";
22
+ readonly flag: "🇮🇷";
23
+ readonly nativeName: "فارسی";
24
+ };
25
+ };
26
+ export type Lang = keyof typeof languages;
27
+ export declare function getLocale(lang: Lang): string;
28
+ export declare function getSchemaLocale(lang: Lang): string;
29
+ export declare function getDirection(lang: Lang): "ltr" | "rtl";
30
+ export declare function getName(lang: Lang): string;
31
+ export declare function getNativeName(lang: Lang): string;
32
+ export declare function getFlag(lang: Lang): string;