@pautena/react-design-system 0.1.2 → 0.2.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 (191) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/index.js +4 -259
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/generators/model-router/screens/add-screen.d.ts +1 -1
  5. package/dist/cjs/types/generators/model-router/screens/list-screen.d.ts +1 -1
  6. package/dist/cjs/types/generators/model-router/screens/screens.types.d.ts +20 -0
  7. package/dist/cjs/types/generators/model-router/screens/update-screen.d.ts +1 -1
  8. package/dist/cjs/types/index.d.ts +1 -0
  9. package/dist/esm/index.js +4 -259
  10. package/dist/esm/index.js.map +1 -1
  11. package/dist/esm/types/generators/model-router/screens/add-screen.d.ts +1 -1
  12. package/dist/esm/types/generators/model-router/screens/list-screen.d.ts +1 -1
  13. package/dist/esm/types/generators/model-router/screens/screens.types.d.ts +20 -0
  14. package/dist/esm/types/generators/model-router/screens/update-screen.d.ts +1 -1
  15. package/dist/esm/types/index.d.ts +1 -0
  16. package/dist/index.d.ts +52 -3
  17. package/package.json +13 -2
  18. package/src/components/app-bar/app-bar.stories.tsx +54 -0
  19. package/src/components/app-bar/app-bar.test.tsx +142 -0
  20. package/src/components/app-bar/app-bar.tsx +150 -0
  21. package/src/components/app-bar/app-bar.types.ts +17 -0
  22. package/src/components/app-bar/index.ts +3 -0
  23. package/src/components/app-bar/mini-app-bar/index.ts +1 -0
  24. package/src/components/app-bar/mini-app-bar/mini-app-bar.tsx +31 -0
  25. package/src/components/bullet/bullet.stories.tsx +43 -0
  26. package/src/components/bullet/bullet.test.tsx +24 -0
  27. package/src/components/bullet/bullet.tsx +30 -0
  28. package/src/components/bullet/index.ts +1 -0
  29. package/src/components/center-container/center-container.stories.tsx +50 -0
  30. package/src/components/center-container/center-container.test.tsx +16 -0
  31. package/src/components/center-container/center-container.tsx +32 -0
  32. package/src/components/center-container/index.ts +1 -0
  33. package/src/components/content/content.stories.tsx +23 -0
  34. package/src/components/content/content.test.tsx +26 -0
  35. package/src/components/content/content.tsx +11 -0
  36. package/src/components/content/content.types.ts +5 -0
  37. package/src/components/content/index.ts +2 -0
  38. package/src/components/drawer/__snapshots__/drawer.test.tsx.snap +20 -0
  39. package/src/components/drawer/drawer.context.ts +20 -0
  40. package/src/components/drawer/drawer.mixins.ts +24 -0
  41. package/src/components/drawer/drawer.mock.tsx +100 -0
  42. package/src/components/drawer/drawer.provider.tsx +23 -0
  43. package/src/components/drawer/drawer.test.tsx +97 -0
  44. package/src/components/drawer/drawer.tsx +30 -0
  45. package/src/components/drawer/drawer.types.ts +53 -0
  46. package/src/components/drawer/index.ts +5 -0
  47. package/src/components/drawer/mini-drawer/index.ts +1 -0
  48. package/src/components/drawer/mini-drawer/mini-drawer.stories.tsx +34 -0
  49. package/src/components/drawer/mini-drawer/mini-drawer.tsx +67 -0
  50. package/src/components/drawer-content/drawer-content.stories.tsx +29 -0
  51. package/src/components/drawer-content/drawer-content.test.tsx +34 -0
  52. package/src/components/drawer-content/drawer-content.tsx +18 -0
  53. package/src/components/drawer-content/index.ts +1 -0
  54. package/src/components/drawer-item/drawer-item.stories.tsx +62 -0
  55. package/src/components/drawer-item/drawer-item.test.tsx +119 -0
  56. package/src/components/drawer-item/drawer-item.tsx +71 -0
  57. package/src/components/drawer-item/index.ts +1 -0
  58. package/src/components/drawer-section/drawer-section.mock.tsx +39 -0
  59. package/src/components/drawer-section/drawer-section.stories.tsx +28 -0
  60. package/src/components/drawer-section/drawer-section.test.tsx +44 -0
  61. package/src/components/drawer-section/drawer-section.tsx +40 -0
  62. package/src/components/drawer-section/index.ts +1 -0
  63. package/src/components/header/header.dummy.ts +55 -0
  64. package/src/components/header/header.stories.tsx +116 -0
  65. package/src/components/header/header.test.tsx +159 -0
  66. package/src/components/header/header.tsx +121 -0
  67. package/src/components/header/header.types.ts +61 -0
  68. package/src/components/header/index.ts +2 -0
  69. package/src/components/index.ts +18 -0
  70. package/src/components/label/index.ts +1 -0
  71. package/src/components/label/label.stories.tsx +49 -0
  72. package/src/components/label/label.test.tsx +30 -0
  73. package/src/components/label/label.tsx +60 -0
  74. package/src/components/link/index.ts +1 -0
  75. package/src/components/link/link.tsx +17 -0
  76. package/src/components/loading-area/index.ts +1 -0
  77. package/src/components/loading-area/loading-area.stories.tsx +17 -0
  78. package/src/components/loading-area/loading-area.test.tsx +11 -0
  79. package/src/components/loading-area/loading-area.tsx +13 -0
  80. package/src/components/placeholder/index.ts +1 -0
  81. package/src/components/placeholder/placeholder.mock.ts +15 -0
  82. package/src/components/placeholder/placeholder.stories.tsx +44 -0
  83. package/src/components/placeholder/placeholder.test.tsx +76 -0
  84. package/src/components/placeholder/placeholder.tsx +75 -0
  85. package/src/components/query-container/index.ts +1 -0
  86. package/src/components/query-container/query-container.stories.tsx +68 -0
  87. package/src/components/query-container/query-container.test.tsx +95 -0
  88. package/src/components/query-container/query-container.tsx +71 -0
  89. package/src/components/sign-in/index.ts +1 -0
  90. package/src/components/sign-in/sign-in.stories.tsx +36 -0
  91. package/src/components/sign-in/sign-in.test.tsx +95 -0
  92. package/src/components/sign-in/sign-in.tsx +97 -0
  93. package/src/components/tab/index.ts +2 -0
  94. package/src/components/tab/tab-card/index.ts +1 -0
  95. package/src/components/tab/tab-card/tab-card.dummy.tsx +30 -0
  96. package/src/components/tab/tab-card/tab-card.stories.tsx +22 -0
  97. package/src/components/tab/tab-card/tab-card.test.tsx +53 -0
  98. package/src/components/tab/tab-card/tab-card.tsx +27 -0
  99. package/src/components/tab/tab-panel/index.ts +1 -0
  100. package/src/components/tab/tab-panel/tab-panel.test.tsx +26 -0
  101. package/src/components/tab/tab-panel/tab-panel.tsx +27 -0
  102. package/src/components/table/enhanced-remote-table/enhanced-remote-table.mock.tsx +27 -0
  103. package/src/components/table/enhanced-remote-table/enhanced-remote-table.stories.tsx +24 -0
  104. package/src/components/table/enhanced-remote-table/enhanced-remote-table.test.tsx +77 -0
  105. package/src/components/table/enhanced-remote-table/enhanced-remote-table.tsx +74 -0
  106. package/src/components/table/enhanced-remote-table/index.ts +1 -0
  107. package/src/components/table/enhanced-table/enhanced-table-head.tsx +58 -0
  108. package/src/components/table/enhanced-table/enhanced-table.mock.tsx +93 -0
  109. package/src/components/table/enhanced-table/enhanced-table.stories.tsx +21 -0
  110. package/src/components/table/enhanced-table/enhanced-table.test.tsx +107 -0
  111. package/src/components/table/enhanced-table/enhanced-table.tsx +136 -0
  112. package/src/components/table/enhanced-table/index.ts +2 -0
  113. package/src/components/table/index.ts +2 -0
  114. package/src/components/table-list/index.ts +1 -0
  115. package/src/components/table-list/table-list.stories.tsx +75 -0
  116. package/src/components/table-list/table-list.test.tsx +291 -0
  117. package/src/components/table-list/table-list.tsx +127 -0
  118. package/src/components/value-displays/group-value-card/group-value-card.mock.tsx +35 -0
  119. package/src/components/value-displays/group-value-card/group-value-card.stories.tsx +26 -0
  120. package/src/components/value-displays/group-value-card/group-value-card.test.tsx +58 -0
  121. package/src/components/value-displays/group-value-card/group-value-card.tsx +63 -0
  122. package/src/components/value-displays/group-value-card/index.ts +1 -0
  123. package/src/components/value-displays/index.ts +4 -0
  124. package/src/components/value-displays/value-boolean/index.ts +1 -0
  125. package/src/components/value-displays/value-boolean/value-boolean.stories.tsx +25 -0
  126. package/src/components/value-displays/value-boolean/value-boolean.test.tsx +27 -0
  127. package/src/components/value-displays/value-boolean/value-boolean.tsx +33 -0
  128. package/src/components/value-displays/value-card/index.ts +1 -0
  129. package/src/components/value-displays/value-card/value-card.stories.tsx +22 -0
  130. package/src/components/value-displays/value-card/value-card.test.tsx +18 -0
  131. package/src/components/value-displays/value-card/value-card.tsx +12 -0
  132. package/src/components/value-displays/value-text/index.ts +1 -0
  133. package/src/components/value-displays/value-text/value-test.test.tsx +21 -0
  134. package/src/components/value-displays/value-text/value-text.stories.tsx +26 -0
  135. package/src/components/value-displays/value-text/value-text.tsx +32 -0
  136. package/src/generators/generators.mock.ts +238 -0
  137. package/src/generators/generators.model.ts +46 -0
  138. package/src/generators/index.ts +4 -0
  139. package/src/generators/model-form/index.ts +1 -0
  140. package/src/generators/model-form/model-form.stories.tsx +30 -0
  141. package/src/generators/model-form/model-form.test.tsx +100 -0
  142. package/src/generators/model-form/model-form.tsx +97 -0
  143. package/src/generators/model-router/index.ts +1 -0
  144. package/src/generators/model-router/model-router.test.tsx +831 -0
  145. package/src/generators/model-router/model-router.tsx +30 -0
  146. package/src/generators/model-router/model-router.types.ts +14 -0
  147. package/src/generators/model-router/screens/add-screen.tsx +70 -0
  148. package/src/generators/model-router/screens/details-screen.tsx +62 -0
  149. package/src/generators/model-router/screens/index.ts +4 -0
  150. package/src/generators/model-router/screens/list-screen.tsx +125 -0
  151. package/src/generators/model-router/screens/screens.types.ts +38 -0
  152. package/src/generators/model-router/screens/update-screen.tsx +97 -0
  153. package/src/generators/model-router/stories/details-screen.stories.tsx +38 -0
  154. package/src/generators/model-router/stories/list-screen.stories.tsx +96 -0
  155. package/src/generators/model-router/stories/model-router.stories.tsx +176 -0
  156. package/src/generators/model-router/stories/templates.tsx +39 -0
  157. package/src/generators/object-details/index.ts +1 -0
  158. package/src/generators/object-details/object-details.stories.tsx +20 -0
  159. package/src/generators/object-details/object-details.test.tsx +21 -0
  160. package/src/generators/object-details/object-details.tsx +76 -0
  161. package/src/index.ts +5 -0
  162. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.stories.tsx +28 -0
  163. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.test.tsx +30 -0
  164. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.tsx +37 -0
  165. package/src/layouts/app-bar-with-drawer-layout/index.ts +1 -0
  166. package/src/layouts/header-layout/header-layout.stories.tsx +204 -0
  167. package/src/layouts/header-layout/header-layout.test.tsx +37 -0
  168. package/src/layouts/header-layout/header-layout.tsx +23 -0
  169. package/src/layouts/header-layout/index.ts +1 -0
  170. package/src/layouts/index.ts +2 -0
  171. package/src/providers/index.ts +2 -0
  172. package/src/providers/notification-center/index.ts +2 -0
  173. package/src/providers/notification-center/notification-center.context.ts +37 -0
  174. package/src/providers/notification-center/notification-center.provider.tsx +51 -0
  175. package/src/providers/notification-center/notification-center.stories.tsx +52 -0
  176. package/src/providers/notification-center/notification-center.test.tsx +112 -0
  177. package/src/providers/tab-provider/index.ts +2 -0
  178. package/src/providers/tab-provider/tab-provider.context.ts +8 -0
  179. package/src/providers/tab-provider/tab-provider.provider.tsx +13 -0
  180. package/src/storybook.tsx +90 -0
  181. package/src/tests/assertions.ts +76 -0
  182. package/src/tests/components.tsx +60 -0
  183. package/src/tests/content-placeholder.stories.tsx +16 -0
  184. package/src/tests/index.ts +3 -0
  185. package/src/tests/skeleton-card.stories.tsx +18 -0
  186. package/src/tests/testing-library.tsx +65 -0
  187. package/src/utils/arrays.test.ts +9 -0
  188. package/src/utils/arrays.ts +7 -0
  189. package/src/utils/index.ts +2 -0
  190. package/src/utils/theme.ts +11 -0
  191. package/.prettierrc.js +0 -5
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { Routes, Route } from "react-router-dom";
3
+ import { BasicModelInstance } from "../generators.model";
4
+ import {
5
+ AddScreen,
6
+ AddScreenProps,
7
+ DetailsScreen,
8
+ DetailsScreenProps,
9
+ ListScreen,
10
+ ListScreenProps,
11
+ UpdateScreen,
12
+ UpdateScreenProps,
13
+ } from "./screens";
14
+
15
+ export type ModelRouterProps<T extends BasicModelInstance> = DetailsScreenProps<T> &
16
+ ListScreenProps<T> &
17
+ AddScreenProps<T> &
18
+ UpdateScreenProps<T>;
19
+
20
+ export const ModelRouter = <T extends BasicModelInstance>(props: ModelRouterProps<T>) => {
21
+ const { updateFeature, addFeature, detailsFeature } = props;
22
+ return (
23
+ <Routes>
24
+ <Route path="" element={<ListScreen {...props} />} />
25
+ {detailsFeature && <Route path=":id" element={<DetailsScreen {...props} />} />}
26
+ {addFeature && <Route path="add" element={<AddScreen {...props} />} />}
27
+ {updateFeature && <Route path=":id/update" element={<UpdateScreen {...props} />} />}
28
+ </Routes>
29
+ );
30
+ };
@@ -0,0 +1,14 @@
1
+ export interface RequestState {
2
+ idle?: boolean;
3
+ loading?: boolean;
4
+ error?: string;
5
+ success?: boolean;
6
+ }
7
+
8
+ export const IdleRequest: RequestState = {
9
+ idle: true,
10
+ };
11
+
12
+ export const LoadingRequest: RequestState = {
13
+ loading: true,
14
+ };
@@ -0,0 +1,70 @@
1
+ import React, { useEffect } from "react";
2
+ import { useNavigate } from "react-router-dom";
3
+ import { Header, Content } from "~/components";
4
+ import { BasicModelInstance, ModelForm } from "~/generators";
5
+ import { HeaderLayout } from "../../../layouts";
6
+ import { useNotificationCenter } from "../../../providers";
7
+ import { RequestState } from "../model-router.types";
8
+ import { BaseScreenProps } from "./screens.types";
9
+
10
+ export interface AddScreenProps<T extends BasicModelInstance> extends BaseScreenProps {
11
+ /**
12
+ * Callback executed when the user wants to
13
+ * add a new item
14
+ */
15
+ onSubmitNewItem: (obj: T) => void;
16
+
17
+ /**
18
+ * Current status of the request to retrieve
19
+ * add a new item
20
+ */
21
+ newItemRequest: RequestState;
22
+ }
23
+
24
+ export const AddScreen = <T extends BasicModelInstance>({
25
+ model,
26
+ modelName,
27
+ basePath = "",
28
+ onSubmitNewItem,
29
+ newItemRequest,
30
+ }: AddScreenProps<T>) => {
31
+ const navigate = useNavigate();
32
+ const { show } = useNotificationCenter();
33
+
34
+ useEffect(() => {
35
+ if (newItemRequest.success) {
36
+ show({ message: "Item added successfully", severity: "success" });
37
+ navigate(`${basePath}/`);
38
+ }
39
+ }, [newItemRequest.success]);
40
+
41
+ useEffect(() => {
42
+ if (newItemRequest.error) {
43
+ show({ title: "We had an error", message: newItemRequest.error, severity: "error" });
44
+ }
45
+ }, [newItemRequest.error]);
46
+
47
+ return (
48
+ <HeaderLayout loading={newItemRequest.loading}>
49
+ <Header
50
+ title={`Add ${modelName}`}
51
+ preset="default"
52
+ breadcrumbs={[
53
+ {
54
+ id: "list",
55
+ text: modelName,
56
+ link: "/",
57
+ },
58
+ {
59
+ id: "add",
60
+ text: `Add new ${modelName}`,
61
+ link: "/add",
62
+ },
63
+ ]}
64
+ />
65
+ <Content>
66
+ <ModelForm model={model} saveButtonText="Save" onSubmit={onSubmitNewItem} />
67
+ </Content>
68
+ </HeaderLayout>
69
+ );
70
+ };
@@ -0,0 +1,62 @@
1
+ import React, { useEffect } from "react";
2
+ import { useParams } from "react-router-dom";
3
+ import { RequestState } from "../model-router.types";
4
+ import { Content, Header } from "~/components";
5
+ import { HeaderLayout } from "~/layouts";
6
+ import { BaseScreenProps } from "./screens.types";
7
+ import { BasicModelInstance, ObjectDetails } from "~/generators";
8
+
9
+ export interface DetailsScreenProps<T extends BasicModelInstance> extends BaseScreenProps {
10
+ /**
11
+ * Callback executed each time we want
12
+ * the details information of an item
13
+ */
14
+ onRequestItem: (id: string) => void;
15
+
16
+ /**
17
+ * Current status of the request to retrieve
18
+ * an item
19
+ */
20
+ itemRequest: RequestState;
21
+
22
+ /**
23
+ * Item to be displayed
24
+ */
25
+ detailsItem?: T;
26
+ }
27
+
28
+ export const DetailsScreen = <T extends BasicModelInstance>({
29
+ model,
30
+ modelName,
31
+ onRequestItem,
32
+ itemRequest,
33
+ detailsItem,
34
+ }: DetailsScreenProps<T>) => {
35
+ const { id = "" } = useParams();
36
+
37
+ useEffect(() => {
38
+ onRequestItem(id);
39
+ }, [id]);
40
+
41
+ return (
42
+ <HeaderLayout loading={itemRequest.loading}>
43
+ <Header
44
+ title={id}
45
+ preset="default"
46
+ breadcrumbs={[
47
+ {
48
+ id: "list",
49
+ text: modelName,
50
+ link: "/",
51
+ },
52
+ {
53
+ id: "detail",
54
+ text: id,
55
+ link: `/${id}`,
56
+ },
57
+ ]}
58
+ />
59
+ <Content>{detailsItem && <ObjectDetails model={model} instance={detailsItem} />}</Content>
60
+ </HeaderLayout>
61
+ );
62
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./update-screen";
2
+ export * from "./list-screen";
3
+ export * from "./add-screen";
4
+ export * from "./details-screen";
@@ -0,0 +1,125 @@
1
+ import React, { useEffect } from "react";
2
+ import { useNavigate } from "react-router-dom";
3
+ import { Content, Header, HeaderAction, TableList, TableRowOption } from "~/components";
4
+ import { BasicModelInstance } from "~/generators";
5
+ import { HeaderLayout } from "../../../layouts";
6
+ import { RequestState } from "../model-router.types";
7
+ import { BaseScreenProps } from "./screens.types";
8
+
9
+ export interface ListScreenProps<T extends BasicModelInstance> extends BaseScreenProps {
10
+ /**
11
+ * Callback executed each time the list screen
12
+ * requests for a data update
13
+ */
14
+ onRequestList: () => void;
15
+
16
+ /**
17
+ * List of items to be displayed in the list screen
18
+ */
19
+ listData: T[];
20
+
21
+ /**
22
+ * Callback executed when the user clicks an option
23
+ * to delete an item
24
+ */
25
+ onClickDeleteItem: (item: T) => void;
26
+
27
+ /**
28
+ * Current status of the request to retrieve
29
+ * the list items
30
+ */
31
+ listRequest: RequestState;
32
+
33
+ /**
34
+ * Current status of the request to delete
35
+ * an item
36
+ */
37
+ deleteRequest: RequestState;
38
+ }
39
+
40
+ export const ListScreen = <T extends BasicModelInstance>({
41
+ model,
42
+ modelName,
43
+ listData,
44
+ listRequest,
45
+ deleteRequest,
46
+ basePath = "",
47
+ deleteFeature = true,
48
+ updateFeature = true,
49
+ addFeature = true,
50
+ detailsFeature = true,
51
+ onRequestList,
52
+ onClickDeleteItem,
53
+ }: ListScreenProps<T>) => {
54
+ const navigate = useNavigate();
55
+
56
+ useEffect(() => {
57
+ onRequestList();
58
+ }, []);
59
+
60
+ const handleClickListItem = detailsFeature
61
+ ? (item: T) => {
62
+ navigate(`${basePath}/${item.id}`);
63
+ }
64
+ : undefined;
65
+
66
+ const handleClickListOption = (optionId: "edit" | "remove", item: T) => {
67
+ if (optionId === "edit") {
68
+ navigate(`${basePath}/${item.id}/update`);
69
+ } else {
70
+ onClickDeleteItem(item);
71
+ }
72
+ };
73
+
74
+ const options: TableRowOption<T>[] = [];
75
+
76
+ updateFeature &&
77
+ options.push({
78
+ id: "edit",
79
+ label: "Edit",
80
+ onClick: (item: T) => handleClickListOption("edit", item),
81
+ });
82
+
83
+ deleteFeature &&
84
+ options.push({
85
+ id: "remove",
86
+ label: "Remove",
87
+ onClick: (item: T) => handleClickListOption("remove", item),
88
+ });
89
+
90
+ const actions: HeaderAction[] = [];
91
+
92
+ addFeature &&
93
+ actions.push({
94
+ id: "add",
95
+ text: "Add",
96
+ href: `${basePath}/add`,
97
+ });
98
+
99
+ return (
100
+ <HeaderLayout loading={listRequest.loading || deleteRequest.loading}>
101
+ <Header
102
+ title={modelName}
103
+ preset="default"
104
+ actions={actions.length > 0 ? actions : undefined}
105
+ />
106
+ <Content>
107
+ <TableList
108
+ columns={model.fields
109
+ .filter(({ listable }) => listable)
110
+ .map(({ id, name, type }) => ({
111
+ disablePadding: false,
112
+ id,
113
+ label: name,
114
+ numeric: type === "number",
115
+ sort: false,
116
+ }))}
117
+ data={listData}
118
+ defaultSort={model.fields[0].id}
119
+ onClick={handleClickListItem}
120
+ options={options.length > 0 ? options : undefined}
121
+ />
122
+ </Content>
123
+ </HeaderLayout>
124
+ );
125
+ };
@@ -0,0 +1,38 @@
1
+ import { Model } from "../../generators.model";
2
+
3
+ export interface BaseScreenProps {
4
+ /**
5
+ * UI-friendly string that represents the model
6
+ */
7
+ modelName: string;
8
+
9
+ /**
10
+ * Structure that represents the fields of the model
11
+ */
12
+ model: Model;
13
+
14
+ /**
15
+ * Path to attach before each internal ModelRouter path
16
+ */
17
+ basePath?: string;
18
+
19
+ /**
20
+ * If true delete features are enabled
21
+ */
22
+ deleteFeature?: boolean;
23
+
24
+ /**
25
+ * If true update features are enabled
26
+ */
27
+ updateFeature?: boolean;
28
+
29
+ /**
30
+ * If true add features are enabled
31
+ */
32
+ addFeature?: boolean;
33
+
34
+ /**
35
+ * If true details features are enabled
36
+ */
37
+ detailsFeature?: boolean;
38
+ }
@@ -0,0 +1,97 @@
1
+ import React, { useEffect } from "react";
2
+ import { useNavigate, useParams } from "react-router-dom";
3
+ import { Content, Header } from "~/components";
4
+ import { BasicModelInstance, ModelForm } from "~/generators";
5
+ import { HeaderLayout } from "../../../layouts";
6
+ import { useNotificationCenter } from "../../../providers";
7
+ import { RequestState } from "../model-router.types";
8
+ import { BaseScreenProps } from "./screens.types";
9
+
10
+ export interface UpdateScreenProps<T extends BasicModelInstance> extends BaseScreenProps {
11
+ /**
12
+ * Callback executed when the user wants to update
13
+ * an item
14
+ */
15
+ onSubmitUpdateItem: (obj: T) => void;
16
+ /**
17
+ * Current status of the request to update an item
18
+ */
19
+ submitUpdateItemRequest: RequestState;
20
+
21
+ /**
22
+ * Current status of the request to retrieve
23
+ * the item to be updated
24
+ */
25
+ updateItemRequest: RequestState;
26
+
27
+ /**
28
+ * Callback executed to retrive the item that
29
+ * has to going tobe updated
30
+ */
31
+ onRequestUpdateItem: (id: string) => void;
32
+
33
+ /**
34
+ * Item that is going to be updated
35
+ */
36
+ updateItem?: T;
37
+ }
38
+
39
+ export const UpdateScreen = <T extends BasicModelInstance>({
40
+ model,
41
+ modelName,
42
+ basePath = "",
43
+ submitUpdateItemRequest,
44
+ updateItemRequest,
45
+ updateItem,
46
+ onSubmitUpdateItem,
47
+ onRequestUpdateItem,
48
+ }: UpdateScreenProps<T>) => {
49
+ const { id = "" } = useParams();
50
+ const navigate = useNavigate();
51
+ const { show } = useNotificationCenter();
52
+ const loading = updateItemRequest.loading || submitUpdateItemRequest.loading;
53
+
54
+ useEffect(() => {
55
+ onRequestUpdateItem(id);
56
+ }, [id]);
57
+
58
+ useEffect(() => {
59
+ if (submitUpdateItemRequest.success) {
60
+ show({
61
+ title: "Item updated",
62
+ message: `The item ${id} has been updated successfully`,
63
+ severity: "success",
64
+ });
65
+ navigate(`${basePath}/`);
66
+ }
67
+ }, [submitUpdateItemRequest.success]);
68
+
69
+ return (
70
+ <HeaderLayout loading={loading}>
71
+ <Header
72
+ title={`Edit ${id}`}
73
+ preset="default"
74
+ breadcrumbs={[
75
+ {
76
+ id: "list",
77
+ text: modelName,
78
+ link: "/",
79
+ },
80
+ {
81
+ id: "update",
82
+ text: `Edit ${id}`,
83
+ link: `/${id}/update`,
84
+ },
85
+ ]}
86
+ />
87
+ <Content>
88
+ <ModelForm
89
+ model={model}
90
+ initialValues={updateItem}
91
+ saveButtonText="Save"
92
+ onSubmit={onSubmitUpdateItem}
93
+ />
94
+ </Content>
95
+ </HeaderLayout>
96
+ );
97
+ };
@@ -0,0 +1,38 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { withNotificationCenter, createTemplate, withActionRouter } from "../../../storybook";
3
+ import { item1 } from "./templates";
4
+ import { DetailsScreen } from "../screens";
5
+ import { mockModel } from "../../generators.mock";
6
+ import { IdleRequest, LoadingRequest } from "../model-router.types";
7
+
8
+ export default {
9
+ title: "Generators/ModelRouter/DetailsScreen",
10
+ component: DetailsScreen,
11
+ decorators: [
12
+ withActionRouter({
13
+ location: `/${item1.id}`,
14
+ path: "/:id",
15
+ }),
16
+ withNotificationCenter,
17
+ ],
18
+ parameters: {
19
+ layout: "fullscreen",
20
+ },
21
+ } as ComponentMeta<typeof DetailsScreen>;
22
+
23
+ const Template = createTemplate(DetailsScreen);
24
+
25
+ export const Loading = Template.bind({});
26
+ Loading.args = {
27
+ modelName: "Items",
28
+ model: mockModel,
29
+ itemRequest: LoadingRequest,
30
+ };
31
+
32
+ export const Details = Template.bind({});
33
+ Details.args = {
34
+ modelName: "Items",
35
+ model: mockModel,
36
+ itemRequest: IdleRequest,
37
+ detailsItem: item1,
38
+ };
@@ -0,0 +1,96 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { withActionRouter, withNotificationCenter } from "../../../storybook";
3
+ import { IdleRequest, LoadingRequest } from "../model-router.types";
4
+ import { data } from "./templates";
5
+ import { createTemplate } from "../../../storybook";
6
+ import { ListScreen } from "../screens";
7
+ import { mockModel } from "../../generators.mock";
8
+
9
+ export default {
10
+ title: "Generators/ModelRouter/ListScreen",
11
+ component: ListScreen,
12
+ decorators: [withActionRouter(), withNotificationCenter],
13
+ parameters: {
14
+ layout: "fullscreen",
15
+ },
16
+ } as ComponentMeta<typeof ListScreen>;
17
+
18
+ const Template = createTemplate(ListScreen);
19
+
20
+ export const ListLoading = Template.bind({});
21
+ ListLoading.args = {
22
+ modelName: "Items",
23
+ model: mockModel,
24
+ listData: data,
25
+ listRequest: LoadingRequest,
26
+ deleteRequest: IdleRequest,
27
+ };
28
+
29
+ export const DeleteLoading = Template.bind({});
30
+ DeleteLoading.args = {
31
+ modelName: "Items",
32
+ model: mockModel,
33
+ listData: data,
34
+ listRequest: IdleRequest,
35
+ deleteRequest: LoadingRequest,
36
+ };
37
+
38
+ export const List = Template.bind({});
39
+ List.args = {
40
+ modelName: "Items",
41
+ model: mockModel,
42
+ listData: data,
43
+ listRequest: IdleRequest,
44
+ deleteRequest: IdleRequest,
45
+ };
46
+
47
+ export const WithoutDeleteFeature = Template.bind({});
48
+ WithoutDeleteFeature.args = {
49
+ modelName: "Items",
50
+ model: mockModel,
51
+ listData: data,
52
+ listRequest: IdleRequest,
53
+ deleteRequest: IdleRequest,
54
+ deleteFeature: false,
55
+ };
56
+
57
+ export const WithoutUpdateFeature = Template.bind({});
58
+ WithoutUpdateFeature.args = {
59
+ modelName: "Items",
60
+ model: mockModel,
61
+ listData: data,
62
+ listRequest: IdleRequest,
63
+ deleteRequest: IdleRequest,
64
+ updateFeature: false,
65
+ };
66
+
67
+ export const WithoutDeleteAndUpdateFeature = Template.bind({});
68
+ WithoutDeleteAndUpdateFeature.args = {
69
+ modelName: "Items",
70
+ model: mockModel,
71
+ listData: data,
72
+ listRequest: IdleRequest,
73
+ deleteRequest: IdleRequest,
74
+ deleteFeature: false,
75
+ updateFeature: false,
76
+ };
77
+
78
+ export const WithoutAddFeature = Template.bind({});
79
+ WithoutAddFeature.args = {
80
+ modelName: "Items",
81
+ model: mockModel,
82
+ listData: data,
83
+ listRequest: IdleRequest,
84
+ deleteRequest: IdleRequest,
85
+ addFeature: false,
86
+ };
87
+
88
+ export const WithoutDetailsFeature = Template.bind({});
89
+ WithoutDetailsFeature.args = {
90
+ modelName: "Items",
91
+ model: mockModel,
92
+ listData: data,
93
+ listRequest: IdleRequest,
94
+ deleteRequest: IdleRequest,
95
+ detailsFeature: false,
96
+ };