@skalfa/skalfa-app 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 (112) hide show
  1. package/.env.example +44 -0
  2. package/README.md +28 -0
  3. package/app/auth/edit/page.tsx +65 -0
  4. package/app/auth/login/page.tsx +63 -0
  5. package/app/auth/me/page.tsx +58 -0
  6. package/app/auth/register/page.tsx +69 -0
  7. package/app/auth/verify/page.tsx +53 -0
  8. package/app/dashboard/layout.tsx +47 -0
  9. package/app/dashboard/page.tsx +9 -0
  10. package/app/dashboard/user/page.tsx +77 -0
  11. package/app/index.ts +14 -0
  12. package/app/layout.tsx +38 -0
  13. package/app/page.tsx +13 -0
  14. package/barrels.json +6 -0
  15. package/blueprints/starter.blueprint.json +103 -0
  16. package/components/base.components/accordion/Accordion.component.tsx +82 -0
  17. package/components/base.components/breadcrumb/Breadcrumb.component.tsx +80 -0
  18. package/components/base.components/button/Button.component.tsx +91 -0
  19. package/components/base.components/button/IconButton.component.tsx +88 -0
  20. package/components/base.components/button/button.decorate.ts +82 -0
  21. package/components/base.components/card/AlertCard.component.tsx +69 -0
  22. package/components/base.components/card/Card.component.tsx +25 -0
  23. package/components/base.components/card/DashboardCard.component.tsx +44 -0
  24. package/components/base.components/card/GalleryCard.component.tsx +50 -0
  25. package/components/base.components/card/ProductCard.component.tsx +65 -0
  26. package/components/base.components/card/ProfileCard.component.tsx +71 -0
  27. package/components/base.components/carousel/Carousel.component.tsx +113 -0
  28. package/components/base.components/chip/Chip.component.tsx +39 -0
  29. package/components/base.components/document/DocumentViewer.component.tsx +164 -0
  30. package/components/base.components/document/ExportExcel.component.tsx +340 -0
  31. package/components/base.components/document/ImportExcel.component.tsx +315 -0
  32. package/components/base.components/document/PrintTable.component.tsx +204 -0
  33. package/components/base.components/document/RenderPDF.component.tsx +416 -0
  34. package/components/base.components/index.ts +85 -0
  35. package/components/base.components/input/Checkbox.component.tsx +109 -0
  36. package/components/base.components/input/Input.component.tsx +332 -0
  37. package/components/base.components/input/InputCheckbox.component.tsx +174 -0
  38. package/components/base.components/input/InputCurrency.component.tsx +163 -0
  39. package/components/base.components/input/InputDate.component.tsx +352 -0
  40. package/components/base.components/input/InputDatetime.component.tsx +260 -0
  41. package/components/base.components/input/InputDocument.component.tsx +352 -0
  42. package/components/base.components/input/InputImage.component.tsx +533 -0
  43. package/components/base.components/input/InputMap.component.tsx +318 -0
  44. package/components/base.components/input/InputNumber.component.tsx +192 -0
  45. package/components/base.components/input/InputOtp.component.tsx +169 -0
  46. package/components/base.components/input/InputPassword.component.tsx +236 -0
  47. package/components/base.components/input/InputRadio.component.tsx +175 -0
  48. package/components/base.components/input/InputTime.component.tsx +276 -0
  49. package/components/base.components/input/InputValues.component.tsx +68 -0
  50. package/components/base.components/input/Radio.component.tsx +102 -0
  51. package/components/base.components/input/Select.component.tsx +541 -0
  52. package/components/base.components/modal/BottomSheet.component.tsx +246 -0
  53. package/components/base.components/modal/FloatingPage.component.tsx +104 -0
  54. package/components/base.components/modal/Modal.component.tsx +96 -0
  55. package/components/base.components/modal/ModalConfirm.component.tsx +218 -0
  56. package/components/base.components/modal/Toast.component.tsx +126 -0
  57. package/components/base.components/nav/Bottombar.component.tsx +116 -0
  58. package/components/base.components/nav/Footer.component.tsx +144 -0
  59. package/components/base.components/nav/Headbar.component.tsx +104 -0
  60. package/components/base.components/nav/Navbar.component.tsx +100 -0
  61. package/components/base.components/nav/Sidebar.component.tsx +301 -0
  62. package/components/base.components/nav/Tabbar.component.tsx +60 -0
  63. package/components/base.components/nav/Wizard.component.tsx +73 -0
  64. package/components/base.components/supervision/FormSupervision.component.tsx +434 -0
  65. package/components/base.components/supervision/TableSupervision.component.tsx +697 -0
  66. package/components/base.components/table/ControlBar.component.tsx +497 -0
  67. package/components/base.components/table/FilterComponent.tsx +518 -0
  68. package/components/base.components/table/Pagination.component.tsx +159 -0
  69. package/components/base.components/table/Table.component.tsx +469 -0
  70. package/components/base.components/typography/TypographyArticle.component.tsx +26 -0
  71. package/components/base.components/typography/TypographyColumn.component.tsx +20 -0
  72. package/components/base.components/typography/TypographyContent.component.tsx +20 -0
  73. package/components/base.components/typography/TypographyTips.component.tsx +20 -0
  74. package/components/base.components/wrap/Draggable.component.tsx +303 -0
  75. package/components/base.components/wrap/IDBProvider.tsx +12 -0
  76. package/components/base.components/wrap/Image.component.tsx +10 -0
  77. package/components/base.components/wrap/OutsideClick.component.tsx +48 -0
  78. package/components/base.components/wrap/ScrollContainer.component.tsx +104 -0
  79. package/components/base.components/wrap/ShortcutProvider.tsx +57 -0
  80. package/components/base.components/wrap/Swipe.component.tsx +93 -0
  81. package/components/construct.components/example.tsx +1 -0
  82. package/components/construct.components/index.ts +5 -0
  83. package/components/index.ts +3 -0
  84. package/components/structure.components/example.tsx +1 -0
  85. package/components/structure.components/index.ts +5 -0
  86. package/contexts/AppProvider.tsx +12 -0
  87. package/contexts/Auth.context.tsx +64 -0
  88. package/contexts/Toggle.context.tsx +44 -0
  89. package/contexts/index.ts +7 -0
  90. package/eslint.config.mjs +34 -0
  91. package/langs/index.ts +1 -0
  92. package/langs/validation.langs.ts +17 -0
  93. package/next.config.ts +17 -0
  94. package/package.json +43 -0
  95. package/postcss.config.mjs +12 -0
  96. package/public/204.svg +19 -0
  97. package/public/500.svg +39 -0
  98. package/public/images/avatar.jpg +0 -0
  99. package/public/images/example.png +0 -0
  100. package/schema/idb/app.schema.ts +9 -0
  101. package/schema/index.ts +5 -0
  102. package/styles/globals.css +231 -0
  103. package/styles/tailwind.safelist +69 -0
  104. package/tailwind.config.ts +10 -0
  105. package/tsconfig.json +35 -0
  106. package/utils/commands/barrels.ts +28 -0
  107. package/utils/commands/blueprint.ts +421 -0
  108. package/utils/commands/light.ts +21 -0
  109. package/utils/commands/logger.ts +42 -0
  110. package/utils/commands/stubs/table-blueprint.stub +13 -0
  111. package/utils/commands/use-pdf.ts +29 -0
  112. package/utils/index.ts +3 -0
@@ -0,0 +1,103 @@
1
+ [
2
+ {
3
+ "model" : "iam/user",
4
+ "schema" : {
5
+ "name" : "type:string,200 required min:1 max:200 fillable searchable selectable",
6
+ "email" : "type:string,100 unique index required min:5 max:100 fillable searchable selectable",
7
+ "password" : "type:string,200 required min:8 max:50 fillable hidden",
8
+ "image" : "type:string,100 required fillable selectable file",
9
+ "email_verification_at" : "type:timestamp"
10
+ },
11
+ "relations": {
12
+ "roles": "[]:Role expandable fillable",
13
+ "permission": "[1]Permission"
14
+ },
15
+ "seeders" : [
16
+ ["Admin", "admin@mail.com", "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli", null, "0001-01-01 01:01:01.000+00"],
17
+ ["User", "user@mail.com", "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli", null, "0001-01-01 01:01:01.000+00"]
18
+ ],
19
+ "migrations" : false,
20
+
21
+ "pages": {
22
+ "iam/user": {
23
+ "features": "create import export print",
24
+ "schema": {
25
+ "Nama" : "name column:sortable form:text|required|min:1|max:200|6",
26
+ "Email" : "email column:sortable form:text|required|email|min:5|max:100|6",
27
+ "Password" : "password form:input-password|required,create|min:8|max:50",
28
+ "Foto" : "image form:image|6"
29
+ }
30
+ }
31
+ }
32
+ },
33
+ {
34
+ "model" : "iam/role",
35
+ "schema" : {
36
+ "name" : "type:string,25 index required min:1 max:25 fillable searchable selectable"
37
+ },
38
+ "controllers" : ["iam/role"],
39
+ "seeders" : [["Admin"], ["User"]],
40
+ "migrations" : false,
41
+
42
+ "pages": {
43
+ "iam/user": {
44
+ "features": "create",
45
+ "schema": {
46
+ "Nama" : "name column:sortable form:text|required|min:1|max:25"
47
+ }
48
+ }
49
+ }
50
+ },
51
+ {
52
+ "model" : "iam/user-role",
53
+ "schema" : {
54
+ "user_id" : "type:bigInteger unsigned index required fillable selectable",
55
+ "role_id" : "type:bigInteger unsigned index required fillable selectable"
56
+ },
57
+ "relations": {
58
+ "role" : "Role",
59
+ "user" : "User"
60
+ },
61
+ "controllers" : false,
62
+ "seeders" : [[1, 1], [2, 2]],
63
+ "migrations" : false,
64
+ "pages": false
65
+ },
66
+ {
67
+ "model" : "iam/role-permission",
68
+ "schema" : {
69
+ "user_id" : "type:bigInteger unsigned index fillable selectable",
70
+ "role_id" : "type:bigInteger unsigned index fillable selectable",
71
+ "permissions" : "type:json nullable fillable selectable"
72
+ },
73
+ "migrations" : false
74
+ },
75
+ {
76
+ "model" : "iam/user-access-token",
77
+ "controllers" : false,
78
+ "schema" : {
79
+ "user_id" : "type:bigInteger unsigned index fillable selectable",
80
+ "agent" : "type:string,100 nullable index fillable selectable",
81
+ "token" : "type:string,200 fillable selectable hidden",
82
+ "permissions" : "type:json nullable fillable selectable",
83
+ "last_used_ip" : "type:string,100 nullable fillable selectable",
84
+ "last_used_at" : "type:timestamp nullable fillable selectable",
85
+ "expired_at" : "type:timestamp nullable fillable selectable"
86
+ },
87
+ "migrations" : false,
88
+ "pages": false
89
+ },
90
+ {
91
+ "model" : "iam/user-mail-token",
92
+ "controllers" : false,
93
+ "schema" : {
94
+ "user_id" : "type:bigInteger unsigned index fillable selectable",
95
+ "type" : "type:string,10 fillable selectable hidden",
96
+ "token" : "type:string,200 fillable selectable hidden",
97
+ "used_at" : "type:timestamp fillable selectable",
98
+ "expired_at" : "type:timestamp fillable selectable"
99
+ },
100
+ "migrations" : false,
101
+ "pages": false
102
+ }
103
+ ]
@@ -0,0 +1,82 @@
1
+ "use client"
2
+
3
+ import { ReactNode, useEffect, useState } from "react";
4
+ import { faChevronDown, faChevronLeft } from "@fortawesome/free-solid-svg-icons";
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
+ import { cn, pcn } from "@utils";
7
+
8
+
9
+
10
+ type CT = "container" | "head" | "active" | "base";
11
+
12
+ export interface AccordionProps {
13
+ setActive ?: number | null;
14
+ items : { head: ReactNode; content: ReactNode }[];
15
+ horizontal ?: boolean;
16
+ className ?: string;
17
+ };
18
+
19
+
20
+
21
+ export function AccordionComponent({
22
+ items,
23
+ setActive = null,
24
+ horizontal = false,
25
+
26
+ /** Use custom class with: "container::", "head::", "active::". */
27
+ className = "",
28
+ }: AccordionProps) {
29
+ const [isActive, setIsActive] = useState<number | null>(setActive);
30
+
31
+ useEffect(() => {
32
+ setIsActive(setActive);
33
+ }, [setActive]);
34
+
35
+ const styles = {
36
+ container: cn(
37
+ "bg-white border rounded-lg flex",
38
+ horizontal ? "flex-row w-min border-r-0" : "flex-col border-b-0",
39
+ pcn<CT>(className, "container"),
40
+ ),
41
+ head: cn(
42
+ "flex justify-between items-center gap-4 font-semibold cursor-pointer",
43
+ horizontal ? "flex-col px-2 py-4" : "py-2 px-4",
44
+ pcn<CT>(className, "head"),
45
+ ),
46
+ };
47
+
48
+ return (
49
+ <div className={styles?.container}>
50
+ {items.map(({ head, content }, key) => (
51
+ <div
52
+ key={key}
53
+ className={cn(horizontal ? "border-r flex" : "border-b")}
54
+ >
55
+ <div
56
+ className={styles?.head}
57
+ onClick={() => setIsActive(isActive === key ? null : key)}
58
+ >
59
+ <div>{head}</div>
60
+ <div
61
+ className={cn(
62
+ "w-min transition-transform",
63
+ isActive !== key && "rotate-180",
64
+ )}
65
+ >
66
+ <FontAwesomeIcon icon={horizontal ? faChevronLeft : faChevronDown} />
67
+ </div>
68
+ </div>
69
+ <div
70
+ className={cn(
71
+ "transition-all overflow-hidden",
72
+ horizontal ? isActive === key ? "max-w-max pr-4 py-2" : "max-w-0 px-0"
73
+ : isActive === key ? "max-h-max pb-4 px-4" : "max-h-0 pb-0 px-4",
74
+ pcn<CT>(className, "base"),
75
+ isActive === key && pcn<CT>(className, "active"),
76
+ )}
77
+ >{content}</div>
78
+ </div>
79
+ ))}
80
+ </div>
81
+ );
82
+ }
@@ -0,0 +1,80 @@
1
+ "use client"
2
+
3
+ import { Fragment, ReactNode } from "react";
4
+ import Link from "next/link";
5
+ import { faChevronRight } from "@fortawesome/free-solid-svg-icons";
6
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7
+ import { cn, pcn } from "@utils";
8
+
9
+
10
+
11
+ type CT = "container" | "active" | "base";
12
+
13
+ export interface BreadcrumbItemProps {
14
+ path : string;
15
+ label : string;
16
+ className ?: string;
17
+ };
18
+
19
+ export interface BreadcrumbProps {
20
+ items : BreadcrumbItemProps[];
21
+ square ?: boolean;
22
+ separatorContent ?: string | ReactNode;
23
+
24
+ /** Use custom class with: "container::", "active::". */
25
+ className ?: string;
26
+ };
27
+
28
+
29
+ export function BreadcrumbComponent({
30
+ items,
31
+ className = "",
32
+ square = false,
33
+ separatorContent,
34
+ }: BreadcrumbProps) {
35
+ return (
36
+ <nav
37
+ className={cn(
38
+ "w-full overflow-x-auto overflow-y-hidden whitespace-nowrap",
39
+ pcn<CT>(className, "container"),
40
+ )}
41
+ >
42
+ <ol className="flex">
43
+ {items.map((item, index) => {
44
+ const isActive = index === items.length - 1;
45
+
46
+ return (
47
+ <Fragment key={item.path}>
48
+ <li>
49
+ <Link
50
+ href={item.path}
51
+ className={cn(
52
+ "capitalize",
53
+ pcn<CT>(className, "base"),
54
+ square && "py-2 px-4 rounded-[6px] bg-light-foreground/10",
55
+ isActive && "text-primary",
56
+ isActive && square && "text-primary bg-primary/10",
57
+ isActive && pcn<CT>(className, "active"),
58
+ )}
59
+ >
60
+ {item.label}
61
+ </Link>
62
+ </li>
63
+
64
+ {!isActive && (
65
+ <li className="mx-2">
66
+ {separatorContent || (
67
+ <FontAwesomeIcon
68
+ icon={faChevronRight}
69
+ className="text-light-foreground"
70
+ />
71
+ )}
72
+ </li>
73
+ )}
74
+ </Fragment>
75
+ );
76
+ })}
77
+ </ol>
78
+ </nav>
79
+ );
80
+ }
@@ -0,0 +1,91 @@
1
+ "use client"
2
+
3
+ import { ReactNode } from "react";
4
+ import Link from "next/link";
5
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
+ import { cn, pcn } from "@utils";
7
+ import { buttonVariant, buttonContainer, buttonRadius } from "./button.decorate";
8
+
9
+
10
+
11
+ type CT = "icon" | "loading" | "base";
12
+
13
+ export interface ButtonProps {
14
+ type ?: "submit" | "button";
15
+ label ?: string | ReactNode;
16
+ variant ?: "solid" | "outline" | "light" | "simple";
17
+ paint ?: "primary" | "secondary" | "success" | "danger" | "warning";
18
+ rounded ?: boolean | string;
19
+ block ?: boolean;
20
+ disabled ?: boolean;
21
+ size ?: "xs" | "sm" | "md" | "lg";
22
+ onClick ?: any;
23
+ href ?: string;
24
+ icon ?: any;
25
+ loading ?: boolean;
26
+ hover ?: boolean;
27
+
28
+ /** Use custom class with: "icon::", "loading::". */
29
+ className?: string;
30
+ };
31
+
32
+
33
+
34
+
35
+ export function ButtonComponent({
36
+ type = "button",
37
+ label,
38
+ variant = "solid",
39
+ paint = "primary",
40
+ rounded,
41
+ block,
42
+ disabled,
43
+ size = "md",
44
+ onClick,
45
+ href,
46
+ icon,
47
+ loading,
48
+ className = "",
49
+ }: ButtonProps) {
50
+ const buttonClasses = cn(
51
+ "button",
52
+ buttonVariant[variant][paint],
53
+ buttonContainer[size],
54
+ rounded ? "rounded-full" : buttonRadius[size],
55
+ block && "w-full justify-center",
56
+ pcn<CT>(className, "base"),
57
+ );
58
+
59
+ const loadingClasses = cn(
60
+ "button-loading",
61
+ size === "sm" ? "w-3 h-3" : size === "lg" ? "w-5 h-5" : "w-4 h-4",
62
+ pcn<CT>(className, "loading"),
63
+ );
64
+
65
+ const iconClasses = cn(
66
+ size === "xs"? "text-xs" : size === "sm" ? "text-sm mb-0.5" : size === "lg" ? "text-xl mb-0.5" : "text-base mb-0.5",
67
+ pcn<CT>(className, "icon"),
68
+ );
69
+
70
+ return (
71
+ <ButtonComponentWrapper
72
+ type={type}
73
+ className={buttonClasses}
74
+ disabled={disabled || loading}
75
+ onClick={onClick}
76
+ href={href}
77
+ >
78
+ {loading ? (
79
+ <div className={loadingClasses}></div>
80
+ ) : (
81
+ icon && <FontAwesomeIcon icon={icon} className={iconClasses} />
82
+ )}
83
+ {label}
84
+ </ButtonComponentWrapper>
85
+ );
86
+ }
87
+
88
+
89
+ const ButtonComponentWrapper = (props: ButtonProps & {children?: ReactNode}) => {
90
+ return !props.href ? <button {...props} >{props.children}</button> : <Link href={props.href || ""} {...props}></Link>
91
+ }
@@ -0,0 +1,88 @@
1
+ "use client"
2
+
3
+ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4
+ import { cn, pcn } from "@utils";
5
+ import { buttonVariant, buttonRadius, iconButtonContainer } from "./button.decorate";
6
+
7
+
8
+
9
+ type CT = "icon" | "loading" | "base";
10
+
11
+ export interface IconButtonProps {
12
+ icon ?: any;
13
+ type ?: "submit" | "button";
14
+ variant ?: "solid" | "outline" | "light" | "simple";
15
+ rounded ?: boolean | string;
16
+ disabled ?: boolean;
17
+ size ?: "xs" | "sm" | "md" | "lg";
18
+ onClick ?: any;
19
+ loading ?: boolean;
20
+ hover ?: boolean;
21
+ tips ?: string | undefined;
22
+ paint ?: "primary" | "secondary" | "success" | "danger" | "warning";
23
+ customPaint ?: {
24
+ bg ?: string;
25
+ color ?: string;
26
+ border ?: string;
27
+ };
28
+
29
+ /** Use custom class with: "icon::", "loading::". */
30
+ className?: string;
31
+ };
32
+
33
+
34
+
35
+ export function IconButtonComponent({
36
+ type = "button",
37
+ variant = "solid",
38
+ paint = "primary",
39
+ size = "md",
40
+ rounded,
41
+ disabled,
42
+ onClick,
43
+ icon,
44
+ loading,
45
+ tips,
46
+ className = "",
47
+ }: IconButtonProps) {
48
+ const buttonClasses = cn(
49
+ "button",
50
+ buttonVariant[variant][paint],
51
+ iconButtonContainer[size],
52
+ rounded ? "rounded-full" : buttonRadius[size],
53
+ pcn<CT>(className, "base")
54
+ );
55
+
56
+ const loadingClasses = cn(
57
+ "button-loading",
58
+ size === "sm" ? "w-3 h-3" : size === "lg" ? "w-5 h-5" : "w-4 h-4",
59
+ pcn<CT>(className, "loading")
60
+ );
61
+
62
+ const iconClasses = cn(
63
+ size === "xs"
64
+ ? "text-xs"
65
+ : size === "sm"
66
+ ? "text-sm mb-0.5"
67
+ : size === "lg"
68
+ ? "text-xl mb-0.5"
69
+ : "text-base mb-0.5",
70
+ pcn<CT>(className, "icon")
71
+ );
72
+
73
+ return (
74
+ <button
75
+ type={type}
76
+ className={buttonClasses}
77
+ disabled={disabled || loading}
78
+ onClick={onClick}
79
+ title={tips}
80
+ >
81
+ {loading ? (
82
+ <div className={loadingClasses}></div>
83
+ ) : (
84
+ <FontAwesomeIcon icon={icon} className={iconClasses} />
85
+ )}
86
+ </button>
87
+ );
88
+ }
@@ -0,0 +1,82 @@
1
+ export const buttonContainer = {
2
+ lg: "px-14 py-3 flex items-center gap-3",
3
+ md: "px-8 py-2 flex items-center gap-2",
4
+ sm: "px-6 py-2 text-xs flex items-center gap-2",
5
+ xs: "px-3 py-1 text-xs flex items-center gap-1.5",
6
+ };
7
+
8
+ export const iconButtonContainer = {
9
+ lg: "w-10 h-10 flex items-center justify-center",
10
+ md: "w-8 h-8 flex items-center justify-center",
11
+ sm: "w-7 h-7 text-xs flex items-center justify-center",
12
+ xs: "w-6 h-6 text-xs flex items-center justify-center",
13
+ };
14
+
15
+ export const buttonVariant = {
16
+ solid: {
17
+ primary: "bg-primary text-white",
18
+ secondary: "bg-secondary text-white",
19
+ warning: "bg-warning text-white",
20
+ danger: "bg-danger text-white",
21
+ success: "bg-success text-white",
22
+ },
23
+ outline: {
24
+ primary: "border text-primary",
25
+ secondary: "border text-secondary",
26
+ warning: "border text-warning",
27
+ danger: "border text-danger",
28
+ success: "border text-success",
29
+ },
30
+ light: {
31
+ primary: "bg-light-primary text-primary",
32
+ secondary: "bg-light-secondary text-secondary",
33
+ warning: "bg-light-warning text-warning",
34
+ danger: "bg-light-danger text-danger",
35
+ success: "bg-light-success text-success",
36
+ },
37
+ simple: {
38
+ primary: "text-primary",
39
+ secondary: "text-secondary",
40
+ warning: "text-warning",
41
+ danger: "text-danger",
42
+ success: "text-success",
43
+ },
44
+ };
45
+
46
+ export const buttonIcon = {
47
+ solid: {
48
+ primary: "text-white",
49
+ secondary: "text-white",
50
+ warning: "text-white",
51
+ danger: "text-white",
52
+ success: "text-white",
53
+ },
54
+ outline: {
55
+ primary: "text-primary",
56
+ secondary: "text-secondary",
57
+ warning: "text-warning",
58
+ danger: "text-danger",
59
+ success: "text-success",
60
+ },
61
+ light: {
62
+ primary: "text-primary",
63
+ secondary: "text-secondary",
64
+ warning: "text-warning",
65
+ danger: "text-danger",
66
+ success: "text-success",
67
+ },
68
+ simple: {
69
+ primary: "text-primary",
70
+ secondary: "text-secondary",
71
+ warning: "text-warning",
72
+ danger: "text-danger",
73
+ success: "text-success",
74
+ },
75
+ };
76
+
77
+ export const buttonRadius = {
78
+ lg: "rounded-sm",
79
+ md: "rounded-sm",
80
+ sm: "rounded-sm",
81
+ xs: "rounded-xs",
82
+ };
@@ -0,0 +1,69 @@
1
+ "use client"
2
+
3
+ import { ReactNode } from "react";
4
+ import { cn, pcn } from "@utils";
5
+
6
+
7
+
8
+ type CT = "badge" | "title" | "base";
9
+
10
+ export interface AlertCardProps {
11
+ title ?: string | ReactNode;
12
+ leftContent ?: string | ReactNode;
13
+ badge ?: string | ReactNode;
14
+ content ?: string | ReactNode;
15
+ footer ?: string | ReactNode;
16
+
17
+ /** Use custom class with: "badge::", "title::". */
18
+ className ?: string;
19
+ }
20
+
21
+
22
+
23
+ export function AlertCardComponent({
24
+ title,
25
+ leftContent,
26
+ badge,
27
+ content,
28
+ footer,
29
+ className = "",
30
+ }: AlertCardProps) {
31
+ return (
32
+ <>
33
+ <section
34
+ className={cn(
35
+ "rounded-[6px] bg-white p-4 border sm:p-6",
36
+ pcn<CT>(className, "base"),
37
+ )}
38
+ >
39
+ <div className="flex items-start sm:gap-8">
40
+ {leftContent}
41
+
42
+ <div>
43
+ <strong
44
+ className={cn(
45
+ "rounded-[4px] border text-primary bg-primary/20 px-3 py-1.5 text-xs font-bold",
46
+ pcn<CT>(className, "badge"),
47
+ )}
48
+ >
49
+ {badge}
50
+ </strong>
51
+
52
+ <h3
53
+ className={cn(
54
+ "mt-4 text-lg font-medium sm:text-xl",
55
+ pcn<CT>(className, "title"),
56
+ )}
57
+ >
58
+ {title}
59
+ </h3>
60
+
61
+ {content}
62
+
63
+ {footer && <div className="pt-4">{footer}</div>}
64
+ </div>
65
+ </div>
66
+ </section>
67
+ </>
68
+ );
69
+ }
@@ -0,0 +1,25 @@
1
+ "use client"
2
+
3
+ import { cn } from "@utils";
4
+
5
+
6
+
7
+ export interface CardProps {
8
+ children : React.ReactNode;
9
+ className ?: string;
10
+ }
11
+
12
+
13
+
14
+ export function CardComponent({
15
+ children,
16
+ className,
17
+ }: CardProps) {
18
+ return (
19
+ <>
20
+ <div className={cn("px-4 py-2.5 rounded-[6px] border bg-white", className)}>
21
+ {children}
22
+ </div>
23
+ </>
24
+ );
25
+ }
@@ -0,0 +1,44 @@
1
+ "use client"
2
+
3
+ import Link from "next/link";
4
+ import { ReactNode } from "react";
5
+ import { cn } from "@utils";
6
+
7
+
8
+
9
+ export interface DashboardCardProps {
10
+ content ?: string | ReactNode;
11
+ title ?: string | ReactNode;
12
+ rightContent ?: string | ReactNode;
13
+ path ?: string;
14
+ className ?: string;
15
+ }
16
+
17
+
18
+
19
+ export function DashboardCardComponent({
20
+ content,
21
+ title,
22
+ rightContent,
23
+ path,
24
+ className,
25
+ } : DashboardCardProps) {
26
+ return (
27
+ <>
28
+ <Link href={path || ""}>
29
+ <div
30
+ className={cn(
31
+ `bg-white border py-4 px-6 rounded-[6px] flex justify-between gap-4 items-center`,
32
+ className,
33
+ )}
34
+ >
35
+ <div>
36
+ <div className="flex gap-4 items-center">{content}</div>
37
+ {title}
38
+ </div>
39
+ <div>{rightContent}</div>
40
+ </div>
41
+ </Link>
42
+ </>
43
+ );
44
+ }