@simplysm/sd-cli 13.0.71 → 13.0.72

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 (98) hide show
  1. package/dist/commands/init.d.ts +4 -5
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +26 -8
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/sd-cli-entry.d.ts.map +1 -1
  6. package/dist/sd-cli-entry.js +0 -20
  7. package/dist/sd-cli-entry.js.map +1 -1
  8. package/package.json +4 -4
  9. package/src/commands/init.ts +40 -21
  10. package/src/sd-cli-entry.ts +0 -24
  11. package/templates/init/{.prettierrc.yaml.hbs → .prettierrc.yaml} +1 -1
  12. package/templates/init/eslint.config.ts +15 -0
  13. package/templates/init/mise.toml +3 -0
  14. package/templates/init/package.json.hbs +8 -7
  15. package/templates/init/packages/client-admin/index.html.hbs +144 -0
  16. package/templates/init/packages/client-admin/package.json.hbs +26 -0
  17. package/templates/init/packages/client-admin/public/assets/logo-landscape.png +0 -0
  18. package/templates/init/packages/client-admin/public/assets/logo.png +0 -0
  19. package/templates/init/packages/client-admin/src/App.tsx +42 -0
  20. package/templates/init/packages/client-admin/src/dev/DevDialog.tsx +34 -0
  21. package/templates/{add-client/__CLIENT__/src/main.css.hbs → init/packages/client-admin/src/main.css} +1 -1
  22. package/templates/init/packages/client-admin/src/main.tsx.hbs +146 -0
  23. package/templates/init/packages/client-admin/src/providers/AppServiceProvider.tsx.hbs +103 -0
  24. package/templates/init/packages/client-admin/src/providers/AppStructureProvider.tsx +84 -0
  25. package/templates/init/packages/client-admin/src/providers/AuthProvider.tsx.hbs +71 -0
  26. package/templates/init/packages/client-admin/src/providers/configureSharedData.ts.hbs +67 -0
  27. package/templates/init/packages/client-admin/src/views/auth/LoginView.tsx +132 -0
  28. package/templates/init/packages/client-admin/src/views/home/HomeView.tsx +108 -0
  29. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeDetail.tsx.hbs +262 -0
  30. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeSheet.tsx.hbs +271 -0
  31. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleDetail.tsx.hbs +154 -0
  32. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionDetail.tsx.hbs +123 -0
  33. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionView.tsx +52 -0
  34. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleSheet.tsx.hbs +125 -0
  35. package/templates/init/packages/client-admin/src/views/home/main/MainView.tsx.hbs +13 -0
  36. package/templates/init/packages/client-admin/src/views/home/my-info/MyInfoDetail.tsx.hbs +248 -0
  37. package/templates/init/packages/client-admin/src/views/home/system/system-log/SystemLogSheet.tsx.hbs +169 -0
  38. package/templates/init/packages/client-admin/src/views/not-found/NotFoundView.tsx +15 -0
  39. package/templates/init/packages/client-admin/tailwind.config.ts +10 -0
  40. package/templates/init/packages/db-main/package.json.hbs +13 -0
  41. package/templates/init/packages/db-main/src/MainDbContext.ts +20 -0
  42. package/templates/init/packages/db-main/src/dataLogExt.ts +127 -0
  43. package/templates/init/packages/db-main/src/index.ts +10 -0
  44. package/templates/init/packages/db-main/src/tables/Employee.ts +24 -0
  45. package/templates/init/packages/db-main/src/tables/EmployeeConfig.ts +13 -0
  46. package/templates/init/packages/db-main/src/tables/Role.ts +9 -0
  47. package/templates/init/packages/db-main/src/tables/RolePermission.ts +13 -0
  48. package/templates/init/packages/db-main/src/tables/_DataLog.ts +19 -0
  49. package/templates/init/packages/db-main/src/tables/_Log.ts +16 -0
  50. package/templates/init/packages/server/package.json.hbs +20 -0
  51. package/templates/init/packages/server/public-dev/dev//354/264/210/352/270/260/355/231/224.xlsx +0 -0
  52. package/templates/init/packages/server/src/index.ts +4 -0
  53. package/templates/init/packages/server/src/main.ts.hbs +34 -0
  54. package/templates/init/packages/server/src/services/AuthService.ts.hbs +171 -0
  55. package/templates/init/packages/server/src/services/DevService.ts.hbs +94 -0
  56. package/templates/init/packages/server/src/services/EmployeeService.ts.hbs +122 -0
  57. package/templates/init/packages/server/src/services/RoleService.ts.hbs +59 -0
  58. package/templates/init/{pnpm-workspace.yaml.hbs → pnpm-workspace.yaml} +3 -1
  59. package/templates/init/sd.config.ts.hbs +30 -1
  60. package/templates/init/tests/e2e/package.json.hbs +16 -0
  61. package/templates/init/tests/e2e/src/e2e.spec.ts +36 -0
  62. package/templates/init/tests/e2e/src/employee-crud.ts +204 -0
  63. package/templates/init/tests/e2e/src/login.ts +61 -0
  64. package/templates/init/tests/e2e/vitest.setup.ts.hbs +220 -0
  65. package/templates/init/tsconfig.json.hbs +0 -11
  66. package/templates/init/{vitest.config.ts.hbs → vitest.config.ts} +16 -12
  67. package/dist/commands/add-client.d.ts +0 -18
  68. package/dist/commands/add-client.d.ts.map +0 -1
  69. package/dist/commands/add-client.js +0 -79
  70. package/dist/commands/add-client.js.map +0 -6
  71. package/dist/commands/add-server.d.ts +0 -18
  72. package/dist/commands/add-server.d.ts.map +0 -1
  73. package/dist/commands/add-server.js +0 -83
  74. package/dist/commands/add-server.js.map +0 -6
  75. package/dist/utils/config-editor.d.ts +0 -17
  76. package/dist/utils/config-editor.d.ts.map +0 -1
  77. package/dist/utils/config-editor.js +0 -79
  78. package/dist/utils/config-editor.js.map +0 -6
  79. package/src/commands/add-client.ts +0 -126
  80. package/src/commands/add-server.ts +0 -138
  81. package/src/utils/config-editor.ts +0 -141
  82. package/templates/add-client/__CLIENT__/index.html.hbs +0 -13
  83. package/templates/add-client/__CLIENT__/package.json.hbs +0 -16
  84. package/templates/add-client/__CLIENT__/src/App.tsx.hbs +0 -65
  85. package/templates/add-client/__CLIENT__/src/appStructure.ts.hbs +0 -20
  86. package/templates/add-client/__CLIENT__/src/main.tsx.hbs +0 -24
  87. package/templates/add-client/__CLIENT__/src/pages/HomePage.tsx.hbs +0 -9
  88. package/templates/add-client/__CLIENT__/tailwind.config.ts.hbs +0 -15
  89. package/templates/add-server/__SERVER__/package.json.hbs +0 -10
  90. package/templates/add-server/__SERVER__/src/main.ts.hbs +0 -14
  91. package/templates/init/.gitignore.hbs +0 -26
  92. package/templates/init/.npmrc.hbs +0 -1
  93. package/templates/init/eslint.config.ts.hbs +0 -5
  94. package/templates/init/mise.toml.hbs +0 -3
  95. package/tests/config-editor.spec.ts +0 -160
  96. /package/templates/init/{.prettierignore.hbs → .prettierignore} +0 -0
  97. /package/templates/{add-client/__CLIENT__ → init/packages/client-admin}/public/favicon.ico +0 -0
  98. /package/templates/init/{stylelint.config.ts.hbs → stylelint.config.ts} +0 -0
@@ -0,0 +1,154 @@
1
+ import { createMemo } from "solid-js";
2
+ import { CrudDetail, FormTable, TextInput, useSharedData } from "@simplysm/solid";
3
+ import { expr } from "@{{projectName}}/db-main";
4
+ import { useAuth } from "../../../../providers/AuthProvider";
5
+ import { useAppService } from "../../../../providers/AppServiceProvider";
6
+ import type { AppSharedData } from "../../../../providers/configureSharedData";
7
+
8
+ type DetailData = {
9
+ name?: string;
10
+ isDeleted: boolean;
11
+ };
12
+
13
+ export function RoleDetail(props: { itemId?: number }) {
14
+ const auth = useAuth();
15
+ const appService = useAppService();
16
+ const sharedData = useSharedData<AppSharedData>();
17
+
18
+ const perms = createMemo(() => {
19
+ const p = auth.authInfo()?.permissions ?? {};
20
+ return {
21
+ edit: Boolean(p["/home/base/role-permission/edit"]),
22
+ };
23
+ });
24
+
25
+ async function handleLoad() {
26
+ if (props.itemId == null) {
27
+ return {
28
+ data: { isDeleted: false } as DetailData,
29
+ info: { isNew: true, isDeleted: false },
30
+ };
31
+ }
32
+
33
+ return appService.orm.connectWithoutTransaction(async (db) => {
34
+ const role = await db
35
+ .role()
36
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
37
+ .where((c) => [expr.eq(c.id, props.itemId)])
38
+ .select((c) => ({
39
+ name: c.name,
40
+ isDeleted: c.isDeleted,
41
+ }))
42
+ .single();
43
+
44
+ if (!role) throw new Error("권한그룹을 찾을 수 없습니다.");
45
+
46
+ return {
47
+ data: {
48
+ name: role.name,
49
+ isDeleted: role.isDeleted,
50
+ } as DetailData,
51
+ info: {
52
+ isNew: false,
53
+ isDeleted: role.isDeleted,
54
+ },
55
+ };
56
+ });
57
+ }
58
+
59
+ async function handleSubmit(data: DetailData) {
60
+ // 이름 중복 검증
61
+ await appService.orm.connect(async (db) => {
62
+ const count = await db
63
+ .role()
64
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
65
+ .where((c) => [
66
+ expr.eq(c.name, data.name ?? ""),
67
+
68
+ props.itemId == null
69
+ ? expr.eq(c.id, -1) // 신규: 절대 매칭 안 되게
70
+ : expr.not(expr.eq(c.id, props.itemId)),
71
+ expr.eq(c.isDeleted, false),
72
+ ])
73
+ .count();
74
+
75
+ if (count > 0) {
76
+ throw new Error("이미 존재하는 권한그룹 이름입니다.");
77
+ }
78
+ });
79
+
80
+ // 저장
81
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
82
+ const savedId = await appService.orm.connect(async (db) => {
83
+ if (props.itemId == null) {
84
+ const [inserted] = await db.role().insert(
85
+ [
86
+ {
87
+ id: undefined,
88
+ name: data.name ?? "",
89
+ isDeleted: false,
90
+ },
91
+ ],
92
+ ["id"],
93
+ );
94
+ return inserted.id;
95
+ } else {
96
+ await db
97
+ .role()
98
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
99
+ .where((_c) => [expr.eq(_c.id, props.itemId)])
100
+ .update((_c) => ({
101
+ name: data.name ?? "",
102
+ }));
103
+ return props.itemId;
104
+ }
105
+ });
106
+
107
+ await sharedData.role.emit([savedId]);
108
+ return true;
109
+ }
110
+
111
+ async function handleToggleDelete(del: boolean) {
112
+ await appService.orm.connect(async (db) => {
113
+ await db
114
+ .role()
115
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
116
+ .where((_c) => [expr.eq(_c.id, props.itemId!)])
117
+ .update((_c) => ({
118
+ isDeleted: del,
119
+ }));
120
+ });
121
+ await sharedData.role.emit([props.itemId!]);
122
+ return true;
123
+ }
124
+
125
+ return (
126
+ <CrudDetail<DetailData>
127
+ editable={perms().edit}
128
+ deletable={props.itemId != null}
129
+ load={handleLoad}
130
+ submit={handleSubmit}
131
+ toggleDelete={handleToggleDelete}
132
+ >
133
+ {(ctx) => (
134
+ <div class="p-2">
135
+ <FormTable>
136
+ <tbody>
137
+ <tr>
138
+ <th>이름</th>
139
+ <td>
140
+ <TextInput
141
+ required
142
+ disabled={!perms().edit}
143
+ value={ctx.data.name ?? ""}
144
+ onValueChange={(v) => ctx.setData("name", v)}
145
+ />
146
+ </td>
147
+ </tr>
148
+ </tbody>
149
+ </FormTable>
150
+ </div>
151
+ )}
152
+ </CrudDetail>
153
+ );
154
+ }
@@ -0,0 +1,123 @@
1
+ import { createMemo, createSignal } from "solid-js";
2
+ import { reconcile } from "solid-js/store";
3
+ import {
4
+ type AppPerm,
5
+ Button,
6
+ CrudDetail,
7
+ PermissionTable,
8
+ SharedDataSelect,
9
+ useSharedData,
10
+ } from "@simplysm/solid";
11
+ import { expr } from "@{{projectName}}/db-main";
12
+ import type { AppSharedData, RoleSharedItem } from "../../../../providers/configureSharedData";
13
+ import { useAuth } from "../../../../providers/AuthProvider";
14
+ import { useAppService } from "../../../../providers/AppServiceProvider";
15
+ import { useAppStructure } from "../../../../providers/AppStructureProvider";
16
+
17
+ export function RolePermissionDetail(props: { roleId: number }) {
18
+ const auth = useAuth();
19
+ const appService = useAppService();
20
+ const appStructure = useAppStructure();
21
+ const sharedData = useSharedData<AppSharedData>();
22
+
23
+ const perms = createMemo(() => {
24
+ const p = auth.authInfo()?.permissions ?? {};
25
+ return {
26
+ edit: Boolean(p["/home/base/role-permission/edit"]),
27
+ };
28
+ });
29
+
30
+ const [copySourceRoleId, setCopySourceRoleId] = createSignal<number>();
31
+
32
+ async function loadPermissionsByRoleId(roleId: number): Promise<Record<string, boolean>> {
33
+ return appService.orm.connectWithoutTransaction(async (db) => {
34
+ const rows = await db
35
+ .rolePermission()
36
+ .where((c) => [expr.eq(c.roleId, roleId)])
37
+ .select((c) => ({
38
+ code: c.code,
39
+ valueJson: c.valueJson,
40
+ }))
41
+ .result();
42
+
43
+ const record: Record<string, boolean> = {};
44
+ for (const row of rows) {
45
+ record[row.code] = JSON.parse(row.valueJson);
46
+ }
47
+ return record;
48
+ });
49
+ }
50
+
51
+ async function handleLoad() {
52
+ const data = await loadPermissionsByRoleId(props.roleId);
53
+ return {
54
+ data,
55
+ info: { isNew: false, isDeleted: false },
56
+ };
57
+ }
58
+
59
+ async function handleSubmit(data: Record<string, boolean>) {
60
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
61
+ await appService.orm.connect(async (db) => {
62
+ await db
63
+ .rolePermission()
64
+ // eslint-disable-next-line solid/reactivity -- 비동기 콜백 내부
65
+ .where((c) => [expr.eq(c.roleId, props.roleId)])
66
+ .delete();
67
+
68
+ const entries = Object.entries(data).filter(([, v]) => v);
69
+ if (entries.length > 0) {
70
+ await db.rolePermission().insert(
71
+ entries.map(([code, value]) => ({
72
+ roleId: props.roleId,
73
+ code,
74
+ valueJson: JSON.stringify(value),
75
+ })),
76
+ );
77
+ }
78
+ });
79
+ return true;
80
+ }
81
+
82
+ return (
83
+ <CrudDetail<Record<string, boolean>>
84
+ class={"p-2"}
85
+ editable={perms().edit}
86
+ load={handleLoad}
87
+ submit={handleSubmit}
88
+ >
89
+ {(ctx) => {
90
+ async function onImportClick() {
91
+ const sourceId = copySourceRoleId();
92
+ if (sourceId == null) return;
93
+ const data = await loadPermissionsByRoleId(sourceId);
94
+ ctx.setData(reconcile(data));
95
+ }
96
+
97
+ return (
98
+ <>
99
+ <CrudDetail.Tools>
100
+ <SharedDataSelect
101
+ data={sharedData.role}
102
+ value={copySourceRoleId()}
103
+ onValueChange={(v) => setCopySourceRoleId(v as number | undefined)}
104
+ >
105
+ {(item: RoleSharedItem) => <>{item.name}</>}
106
+ </SharedDataSelect>
107
+ <Button onClick={onImportClick} disabled={copySourceRoleId() == null}>
108
+ 가져오기
109
+ </Button>
110
+ </CrudDetail.Tools>
111
+
112
+ <PermissionTable
113
+ items={appStructure.usablePerms().flatMap((p) => p.children ?? []) as AppPerm<string>[]}
114
+ value={ctx.data}
115
+ onValueChange={(v) => ctx.setData(reconcile(v))}
116
+ disabled={!perms().edit}
117
+ />
118
+ </>
119
+ );
120
+ }}
121
+ </CrudDetail>
122
+ );
123
+ }
@@ -0,0 +1,52 @@
1
+ import { createSignal, Show } from "solid-js";
2
+ import { Button, Icon, SharedDataSelectList, useDialog, useSharedData } from "@simplysm/solid";
3
+ import type { AppSharedData, RoleSharedItem } from "../../../../providers/configureSharedData";
4
+ import { RolePermissionDetail } from "./RolePermissionDetail";
5
+ import { RoleSheet } from "./RoleSheet";
6
+ import { IconExternalLink } from "@tabler/icons-solidjs";
7
+
8
+ export function RolePermissionView() {
9
+ const dialog = useDialog();
10
+ const sharedData = useSharedData<AppSharedData>();
11
+ const [selectedRole, setSelectedRole] = createSignal<RoleSharedItem>();
12
+
13
+ return (
14
+ <div class="flex h-full flex-row">
15
+ <SharedDataSelectList
16
+ class={"border-r border-base-200 p-1.5 py-3"}
17
+ data={sharedData.role}
18
+ value={selectedRole()}
19
+ onValueChange={setSelectedRole}
20
+ header={
21
+ <div class={"flex flex-row p-1"}>
22
+ <div class={"flex-1 font-bold text-base-400"}>권한그룹</div>
23
+ <Button
24
+ variant={"ghost"}
25
+ theme={"primary"}
26
+ size={"xs"}
27
+ onClick={() => dialog.show(() => <RoleSheet />, { header: "권한그룹", closeOnBackdrop: true })}
28
+ >
29
+ <Icon icon={IconExternalLink} />
30
+ </Button>
31
+ </div>
32
+ }
33
+ required
34
+ >
35
+ <SharedDataSelectList.ItemTemplate<RoleSharedItem>>
36
+ {(item) => <>{item.name}</>}
37
+ </SharedDataSelectList.ItemTemplate>
38
+ </SharedDataSelectList>
39
+
40
+ <Show
41
+ when={selectedRole()}
42
+ fallback={
43
+ <div class="flex flex-1 items-center justify-center text-4xl leading-relaxed text-base-300">
44
+ 권한그룹을 선택하세요.
45
+ </div>
46
+ }
47
+ >
48
+ <RolePermissionDetail roleId={selectedRole()!.id} />
49
+ </Show>
50
+ </div>
51
+ );
52
+ }
@@ -0,0 +1,125 @@
1
+ import {
2
+ Checkbox,
3
+ CrudSheet,
4
+ type ModalEditConfig,
5
+ type SortingDef,
6
+ TextInput,
7
+ useDialog,
8
+ } from "@simplysm/solid";
9
+ import { FormGroup } from "@simplysm/solid";
10
+ import { expr } from "@{{projectName}}/db-main";
11
+ import { type ExprUnit } from "@simplysm/orm-common";
12
+ import { objGetChainValue } from "@simplysm/core-common";
13
+ import { useAppService } from "../../../../providers/AppServiceProvider";
14
+ import { useAppStructure } from "../../../../providers/AppStructureProvider";
15
+ import { RoleDetail } from "./RoleDetail";
16
+
17
+ type SheetItem = {
18
+ id?: number;
19
+ name?: string;
20
+ isDeleted: boolean;
21
+ };
22
+
23
+ type Filter = {
24
+ searchText?: string;
25
+ isIncludeDeleted: boolean;
26
+ };
27
+
28
+ const ITEMS_PER_PAGE = 50;
29
+
30
+ export function RoleSheet() {
31
+ const appService = useAppService();
32
+ const appStructure = useAppStructure();
33
+ const dialog = useDialog();
34
+
35
+ const rolePerms = appStructure.perms.home.base["role-permission"];
36
+
37
+ const modalEdit: ModalEditConfig<SheetItem> = {
38
+ editItem: (item) =>
39
+ dialog.show(() => <RoleDetail itemId={item?.id} />, {
40
+ header: item ? "권한그룹 수정" : "권한그룹 등록",
41
+ }),
42
+ };
43
+
44
+ async function search(filter: Filter, page: number | undefined, sorts: SortingDef[]) {
45
+ return appService.orm.connect(async (db) => {
46
+ let qr = db.role();
47
+
48
+ const searchText = filter.searchText?.trim();
49
+ if (searchText != null && searchText.length > 0) {
50
+ qr = qr.search((c) => [c.name], searchText);
51
+ }
52
+
53
+ if (!filter.isIncludeDeleted) {
54
+ qr = qr.where((c) => [expr.eq(c.isDeleted, false)]);
55
+ }
56
+
57
+ const pageCount = page != null ? Math.ceil((await qr.count()) / ITEMS_PER_PAGE) : undefined;
58
+
59
+ let qr2 = qr.select((c) => ({
60
+ id: c.id,
61
+ name: c.name,
62
+ isDeleted: c.isDeleted,
63
+ }));
64
+
65
+ for (const sort of sorts) {
66
+ qr2 = qr2.orderBy(
67
+ (c) => objGetChainValue(c, sort.key) as ExprUnit<any>,
68
+ sort.desc ? "DESC" : "ASC",
69
+ );
70
+ }
71
+ if (!sorts.some((s) => s.key === "id")) {
72
+ qr2 = qr2.orderBy((c) => c.id, "DESC");
73
+ }
74
+
75
+ if (page != null) {
76
+ qr2 = qr2.limit((page - 1) * ITEMS_PER_PAGE, ITEMS_PER_PAGE);
77
+ }
78
+
79
+ const items = (await qr2.result()) as SheetItem[];
80
+ return { items, pageCount };
81
+ });
82
+ }
83
+
84
+ return (
85
+ <CrudSheet<SheetItem, Filter>
86
+ search={search}
87
+ getItemKey={(item) => item.id}
88
+ itemDeleted={(item) => item.isDeleted}
89
+ isItemSelectable={(item) => item.id != null}
90
+ persistKey="role-sheet-page"
91
+ editable={rolePerms.edit}
92
+ filterInitial=\{{ isIncludeDeleted: false } as Filter}
93
+ modalEdit={modalEdit}
94
+ >
95
+ <CrudSheet.Filter<Filter>>
96
+ {(filter, setFilter) => (
97
+ <>
98
+ <FormGroup.Item label="검색어">
99
+ <TextInput
100
+ value={filter.searchText}
101
+ onValueChange={(v) => setFilter("searchText", v)}
102
+ />
103
+ </FormGroup.Item>
104
+ <FormGroup.Item>
105
+ <Checkbox
106
+ value={filter.isIncludeDeleted}
107
+ onValueChange={(v) => setFilter("isIncludeDeleted", v)}
108
+ >
109
+ 삭제항목 포함
110
+ </Checkbox>
111
+ </FormGroup.Item>
112
+ </>
113
+ )}
114
+ </CrudSheet.Filter>
115
+
116
+ <CrudSheet.Column<SheetItem> key="id" header="#" editTrigger>
117
+ {({ item }) => <div class="px-2 py-1 text-right">{item.id}</div>}
118
+ </CrudSheet.Column>
119
+
120
+ <CrudSheet.Column<SheetItem> key="name" header="이름">
121
+ {({ item }) => <div class="px-2 py-1">{item.name}</div>}
122
+ </CrudSheet.Column>
123
+ </CrudSheet>
124
+ );
125
+ }
@@ -0,0 +1,13 @@
1
+ import { useAuth } from "../../../providers/AuthProvider";
2
+
3
+ export function MainView() {
4
+ const auth = useAuth();
5
+
6
+ return (
7
+ <div class="flex h-full items-center justify-center">
8
+ <h1 class="text-2xl font-bold text-base-700 dark:text-base-200">
9
+ {{projectName}} ({auth.authInfo()?.employeeName})
10
+ </h1>
11
+ </div>
12
+ );
13
+ }