@pautena/react-design-system 0.0.1 → 0.1.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 (170) hide show
  1. package/.prettierignore +2 -1
  2. package/babel.config.js +10 -0
  3. package/dist/cjs/index.js +28 -28
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/app-bar/app-bar.types.d.ts +2 -1
  6. package/dist/cjs/types/components/content/content.d.ts +2 -0
  7. package/dist/cjs/types/components/content/content.types.d.ts +4 -0
  8. package/dist/cjs/types/components/content/index.d.ts +2 -0
  9. package/dist/cjs/types/components/header/header.d.ts +2 -61
  10. package/dist/cjs/types/components/header/header.types.d.ts +55 -0
  11. package/dist/cjs/types/components/header/index.d.ts +1 -0
  12. package/dist/cjs/types/components/index.d.ts +1 -0
  13. package/dist/cjs/types/components/tab/index.d.ts +0 -1
  14. package/dist/cjs/types/components/tab/tab-card/tab-card.d.ts +1 -2
  15. package/dist/cjs/types/components/table-list/table-list.d.ts +4 -7
  16. package/dist/cjs/types/generators/generators.mock.d.ts +22 -1
  17. package/dist/cjs/types/generators/generators.model.d.ts +5 -1
  18. package/dist/cjs/types/generators/model-form/model-form.d.ts +5 -5
  19. package/dist/cjs/types/generators/model-router/model-router.d.ts +4 -35
  20. package/dist/cjs/types/generators/model-router/model-router.types.d.ts +8 -0
  21. package/dist/cjs/types/generators/model-router/screens/add-screen.d.ts +16 -2
  22. package/dist/cjs/types/generators/model-router/screens/details-screen.d.ts +20 -2
  23. package/dist/cjs/types/generators/model-router/screens/list-screen.d.ts +30 -2
  24. package/dist/cjs/types/generators/model-router/screens/screens.types.d.ts +11 -0
  25. package/dist/cjs/types/generators/model-router/screens/update-screen.d.ts +29 -2
  26. package/dist/cjs/types/generators/model-router/stories/templates.d.ts +23 -0
  27. package/dist/cjs/types/generators/object-details/object-details.d.ts +4 -4
  28. package/dist/cjs/types/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.d.ts +5 -8
  29. package/dist/cjs/types/layouts/header-layout/header-layout.d.ts +4 -5
  30. package/dist/cjs/types/layouts/index.d.ts +1 -6
  31. package/dist/cjs/types/providers/index.d.ts +1 -0
  32. package/dist/cjs/types/providers/notification-center/index.d.ts +1 -0
  33. package/dist/cjs/types/providers/tab-provider/index.d.ts +2 -0
  34. package/dist/cjs/types/providers/tab-provider/tab-provider.context.d.ts +4 -0
  35. package/dist/cjs/types/providers/tab-provider/tab-provider.provider.d.ts +6 -0
  36. package/dist/cjs/types/utils/theme.d.ts +7 -4
  37. package/dist/esm/index.js +28 -28
  38. package/dist/esm/index.js.map +1 -1
  39. package/dist/esm/types/components/app-bar/app-bar.types.d.ts +2 -1
  40. package/dist/esm/types/components/content/content.d.ts +2 -0
  41. package/dist/esm/types/components/content/content.types.d.ts +4 -0
  42. package/dist/esm/types/components/content/index.d.ts +2 -0
  43. package/dist/esm/types/components/header/header.d.ts +2 -61
  44. package/dist/esm/types/components/header/header.types.d.ts +55 -0
  45. package/dist/esm/types/components/header/index.d.ts +1 -0
  46. package/dist/esm/types/components/index.d.ts +1 -0
  47. package/dist/esm/types/components/tab/index.d.ts +0 -1
  48. package/dist/esm/types/components/tab/tab-card/tab-card.d.ts +1 -2
  49. package/dist/esm/types/components/table-list/table-list.d.ts +4 -7
  50. package/dist/esm/types/generators/generators.mock.d.ts +22 -1
  51. package/dist/esm/types/generators/generators.model.d.ts +5 -1
  52. package/dist/esm/types/generators/model-form/model-form.d.ts +5 -5
  53. package/dist/esm/types/generators/model-router/model-router.d.ts +4 -35
  54. package/dist/esm/types/generators/model-router/model-router.types.d.ts +8 -0
  55. package/dist/esm/types/generators/model-router/screens/add-screen.d.ts +16 -2
  56. package/dist/esm/types/generators/model-router/screens/details-screen.d.ts +20 -2
  57. package/dist/esm/types/generators/model-router/screens/list-screen.d.ts +30 -2
  58. package/dist/esm/types/generators/model-router/screens/screens.types.d.ts +11 -0
  59. package/dist/esm/types/generators/model-router/screens/update-screen.d.ts +29 -2
  60. package/dist/esm/types/generators/model-router/stories/templates.d.ts +23 -0
  61. package/dist/esm/types/generators/object-details/object-details.d.ts +4 -4
  62. package/dist/esm/types/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.d.ts +5 -8
  63. package/dist/esm/types/layouts/header-layout/header-layout.d.ts +4 -5
  64. package/dist/esm/types/layouts/index.d.ts +1 -6
  65. package/dist/esm/types/providers/index.d.ts +1 -0
  66. package/dist/esm/types/providers/notification-center/index.d.ts +1 -0
  67. package/dist/esm/types/providers/tab-provider/index.d.ts +2 -0
  68. package/dist/esm/types/providers/tab-provider/tab-provider.context.d.ts +4 -0
  69. package/dist/esm/types/providers/tab-provider/tab-provider.provider.d.ts +6 -0
  70. package/dist/esm/types/utils/theme.d.ts +7 -4
  71. package/dist/index.d.ts +146 -122
  72. package/jest.config.js +3 -0
  73. package/package.json +3 -1
  74. package/rollup.config.js +12 -0
  75. package/src/components/app-bar/app-bar.types.ts +2 -1
  76. package/src/components/content/content.stories.tsx +23 -0
  77. package/src/components/content/content.test.tsx +26 -0
  78. package/src/components/content/content.tsx +11 -0
  79. package/src/components/content/content.types.ts +5 -0
  80. package/src/components/content/index.ts +2 -0
  81. package/src/components/drawer-item/drawer-item.tsx +2 -0
  82. package/src/components/header/header.test.tsx +18 -16
  83. package/src/components/header/header.tsx +5 -69
  84. package/src/components/header/header.types.ts +61 -0
  85. package/src/components/header/index.ts +1 -0
  86. package/src/components/index.ts +1 -0
  87. package/src/components/tab/index.ts +0 -1
  88. package/src/components/tab/tab-card/tab-card.dummy.tsx +14 -11
  89. package/src/components/tab/tab-card/tab-card.test.tsx +2 -2
  90. package/src/components/tab/tab-card/tab-card.tsx +11 -14
  91. package/src/components/tab/tab-panel/tab-panel.test.tsx +4 -4
  92. package/src/components/tab/tab-panel/tab-panel.tsx +2 -2
  93. package/src/components/table/enhanced-table/enhanced-table.tsx +2 -2
  94. package/src/components/table-list/table-list.test.tsx +3 -2
  95. package/src/components/table-list/table-list.tsx +4 -8
  96. package/src/components/value-displays/group-value-card/group-value-card.tsx +2 -4
  97. package/src/generators/generators.mock.ts +25 -2
  98. package/src/generators/generators.model.ts +6 -1
  99. package/src/generators/model-form/model-form.test.tsx +5 -3
  100. package/src/generators/model-form/model-form.tsx +15 -15
  101. package/src/generators/model-router/model-router.test.tsx +72 -39
  102. package/src/generators/model-router/model-router.tsx +16 -41
  103. package/src/generators/model-router/model-router.types.ts +14 -0
  104. package/src/generators/model-router/screens/add-screen.tsx +53 -36
  105. package/src/generators/model-router/screens/details-screen.tsx +52 -43
  106. package/src/generators/model-router/screens/list-screen.tsx +89 -60
  107. package/src/generators/model-router/screens/screens.types.ts +13 -0
  108. package/src/generators/model-router/screens/update-screen.tsx +76 -42
  109. package/src/generators/model-router/stories/details-screen.stories.tsx +38 -0
  110. package/src/generators/model-router/stories/list-screen.stories.tsx +45 -0
  111. package/src/generators/model-router/stories/model-router.stories.tsx +164 -0
  112. package/src/generators/model-router/stories/templates.tsx +39 -0
  113. package/src/generators/object-details/object-details.tsx +18 -12
  114. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.stories.tsx +7 -8
  115. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.test.tsx +30 -0
  116. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.tsx +10 -7
  117. package/src/layouts/header-layout/header-layout.stories.tsx +158 -22
  118. package/src/layouts/header-layout/header-layout.test.tsx +37 -0
  119. package/src/layouts/header-layout/header-layout.tsx +12 -13
  120. package/src/layouts/index.ts +1 -6
  121. package/src/providers/index.ts +1 -0
  122. package/src/providers/notification-center/index.ts +1 -0
  123. package/src/providers/tab-provider/index.ts +2 -0
  124. package/src/providers/tab-provider/tab-provider.context.ts +8 -0
  125. package/src/providers/tab-provider/tab-provider.provider.tsx +13 -0
  126. package/src/storybook.tsx +41 -7
  127. package/src/tests/assertions.ts +4 -0
  128. package/src/tests/components.tsx +1 -1
  129. package/src/utils/theme.ts +7 -2
  130. package/tsconfig.json +8 -10
  131. package/tsconfig.rollup.json +2 -0
  132. package/dist/cjs/types/components/tab/tab.context.d.ts +0 -4
  133. package/dist/cjs/types/layouts/data-table-layout/data-table-layout.d.ts +0 -12
  134. package/dist/cjs/types/layouts/data-table-layout/index.d.ts +0 -1
  135. package/dist/cjs/types/layouts/details-layout/details-layout.d.ts +0 -12
  136. package/dist/cjs/types/layouts/details-layout/index.d.ts +0 -1
  137. package/dist/cjs/types/layouts/form-layout/form-layout.d.ts +0 -8
  138. package/dist/cjs/types/layouts/form-layout/index.d.ts +0 -1
  139. package/dist/cjs/types/layouts/list-layout/index.d.ts +0 -1
  140. package/dist/cjs/types/layouts/list-layout/list-layout.d.ts +0 -8
  141. package/dist/cjs/types/layouts/tab-layout/index.d.ts +0 -1
  142. package/dist/cjs/types/layouts/tab-layout/tab-layout.d.ts +0 -7
  143. package/dist/esm/types/components/tab/tab.context.d.ts +0 -4
  144. package/dist/esm/types/layouts/data-table-layout/data-table-layout.d.ts +0 -12
  145. package/dist/esm/types/layouts/data-table-layout/index.d.ts +0 -1
  146. package/dist/esm/types/layouts/details-layout/details-layout.d.ts +0 -12
  147. package/dist/esm/types/layouts/details-layout/index.d.ts +0 -1
  148. package/dist/esm/types/layouts/form-layout/form-layout.d.ts +0 -8
  149. package/dist/esm/types/layouts/form-layout/index.d.ts +0 -1
  150. package/dist/esm/types/layouts/list-layout/index.d.ts +0 -1
  151. package/dist/esm/types/layouts/list-layout/list-layout.d.ts +0 -8
  152. package/dist/esm/types/layouts/tab-layout/index.d.ts +0 -1
  153. package/dist/esm/types/layouts/tab-layout/tab-layout.d.ts +0 -7
  154. package/src/components/tab/tab.context.ts +0 -5
  155. package/src/generators/model-router/model-router.stories.tsx +0 -160
  156. package/src/layouts/data-table-layout/data-table-layout.stories.tsx +0 -94
  157. package/src/layouts/data-table-layout/data-table-layout.tsx +0 -30
  158. package/src/layouts/data-table-layout/index.ts +0 -1
  159. package/src/layouts/details-layout/details-layout.stories.tsx +0 -81
  160. package/src/layouts/details-layout/details-layout.tsx +0 -33
  161. package/src/layouts/details-layout/index.ts +0 -1
  162. package/src/layouts/form-layout/form-layout.stories.tsx +0 -65
  163. package/src/layouts/form-layout/form-layout.tsx +0 -18
  164. package/src/layouts/form-layout/index.ts +0 -1
  165. package/src/layouts/list-layout/index.ts +0 -1
  166. package/src/layouts/list-layout/list-layout.stories.tsx +0 -102
  167. package/src/layouts/list-layout/list-layout.tsx +0 -36
  168. package/src/layouts/tab-layout/index.ts +0 -1
  169. package/src/layouts/tab-layout/tab-layout.stories.tsx +0 -88
  170. package/src/layouts/tab-layout/tab-layout.tsx +0 -11
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { DummyModelRouter } from "./model-router.stories";
2
+ import { DummyModelRouter } from "./stories/model-router.stories";
3
3
  import {
4
4
  expectModelFieldInputExist,
5
5
  expectProgressIndicator,
@@ -9,11 +9,12 @@ import {
9
9
  TestRouter,
10
10
  expectModelFieldValue,
11
11
  expectModelFieldInputValue,
12
- } from "../../tests";
12
+ } from "~/tests";
13
13
  import userEvent from "@testing-library/user-event";
14
14
  import { getRandomItem } from "../../utils";
15
15
  import { Model } from "../generators.model";
16
- import { createModelInstance } from "../generators.mock";
16
+ import { createModelInstance, MockInstance, mockModel } from "../generators.mock";
17
+ import { NotificationCenterProvider } from "../../providers";
17
18
 
18
19
  const REQUEST_TIMEOUT = 20;
19
20
 
@@ -39,7 +40,7 @@ describe("ModelRouter", () => {
39
40
  name: `Edit ${id}`,
40
41
  level: 1,
41
42
  }),
42
- expectListItems: async ({ data, model }: { data: any[]; model: Model }) => {
43
+ expectListItems: async ({ data, model }: { data: MockInstance[]; model: Model }) => {
43
44
  for (let i = 0; i < model.fields.length; ++i) {
44
45
  const { id, listable } = model.fields[i];
45
46
 
@@ -48,10 +49,10 @@ describe("ModelRouter", () => {
48
49
  }
49
50
  }
50
51
  },
51
- expectMenuOption: async ({ id }: { id: number }) => {
52
+ expectMenuOption: async ({ id }: { id: string }) => {
52
53
  await screen.findByTestId(`options-${id}`);
53
54
  },
54
- expectSubmitInstanceCall: (mockFn: jest.Mock, instance: any) => {
55
+ expectSubmitInstanceCall: (mockFn: jest.Mock, instance: MockInstance) => {
55
56
  expect(mockFn).toHaveBeenCalledTimes(1);
56
57
  expect(mockFn).toHaveBeenCalledWith({
57
58
  id: instance.id,
@@ -81,14 +82,14 @@ describe("ModelRouter", () => {
81
82
  navigateToAddScreen: async () => {
82
83
  await userEvent.click(screen.getByRole("button", { name: /add/i }));
83
84
  },
84
- navigateToUpdateScreen: async ({ id }: { id: number }) => {
85
+ navigateToUpdateScreen: async ({ id }: { id: string }) => {
85
86
  await actions.openItemOptions({ id });
86
87
  await userEvent.click(screen.getByRole("menuitem", { name: /edit/i }));
87
88
  },
88
89
  navigateToDetailScreen: async ({ name }: { name: string }) => {
89
90
  await userEvent.click(await screen.findByRole("cell", { name }));
90
91
  },
91
- openItemOptions: async ({ id }: { id: number }) => {
92
+ openItemOptions: async ({ id }: { id: string }) => {
92
93
  await userEvent.click(await screen.findByTestId(`options-${id}`));
93
94
  },
94
95
  fullfillModelForm: async ({
@@ -100,7 +101,7 @@ describe("ModelRouter", () => {
100
101
  submit?: boolean;
101
102
  clear?: boolean;
102
103
  }) => {
103
- const instance = createModelInstance(model);
104
+ const instance = createModelInstance<MockInstance>(model);
104
105
 
105
106
  const idElement = screen.getByRole("textbox", { name: "Id" });
106
107
  const firstNameElement = screen.getByRole("textbox", { name: /first name/i });
@@ -167,26 +168,32 @@ describe("ModelRouter", () => {
167
168
  router = "memory",
168
169
  screen = "initial",
169
170
  }: { router?: TestRouter; screen?: "initial" | "add" | "details" | "update" } = {}) => {
170
- const requestList = jest.fn();
171
- const onSubmitAdd = jest.fn();
171
+ const onRequestList = jest.fn();
172
+ const onRequestItem = jest.fn();
173
+ const onSubmitNewItem = jest.fn();
174
+ const onRequestUpdateItem = jest.fn();
172
175
  const onSubmitUpdate = jest.fn();
173
176
  const onRequestDelete = jest.fn();
174
177
  const args = DummyModelRouter.args;
175
178
  const instance = render(
176
- <DummyModelRouter
177
- {...args}
178
- requestTimeout={REQUEST_TIMEOUT}
179
- requestListAction={requestList}
180
- onSubmitAddAction={onSubmitAdd}
181
- onSubmitUpdateAction={onSubmitUpdate}
182
- onRequestDeleteAction={onRequestDelete}
183
- />,
179
+ <NotificationCenterProvider>
180
+ <DummyModelRouter
181
+ {...args}
182
+ requestTimeout={REQUEST_TIMEOUT}
183
+ onRequestListAction={onRequestList}
184
+ onRequestItem={onRequestItem}
185
+ onSubmitNewItemAction={onSubmitNewItem}
186
+ onRequestUpdateItemAction={onRequestUpdateItem}
187
+ onSubmitUpdateAction={onSubmitUpdate}
188
+ onRequestDeleteAction={onRequestDelete}
189
+ />
190
+ </NotificationCenterProvider>,
184
191
  {
185
192
  router,
186
193
  },
187
194
  );
188
195
 
189
- const randomItem = getRandomItem<any>(args.initialData);
196
+ const randomItem = getRandomItem(args.initialData);
190
197
 
191
198
  if (screen === "add") {
192
199
  await actions.navigateToAddScreen();
@@ -199,10 +206,12 @@ describe("ModelRouter", () => {
199
206
  return {
200
207
  ...instance,
201
208
  data: args.initialData,
202
- model: args.model,
209
+ model: mockModel,
203
210
  randomItem,
204
- requestList,
205
- onSubmitAdd,
211
+ onRequestList,
212
+ onRequestItem,
213
+ onSubmitNewItem,
214
+ onRequestUpdateItem,
206
215
  onSubmitUpdate,
207
216
  onRequestDelete,
208
217
  };
@@ -225,7 +234,7 @@ describe("ModelRouter", () => {
225
234
 
226
235
  it("would render the update screen if we navigate there", async () => {
227
236
  const { data } = await renderComponent();
228
- const { item } = getRandomItem<any>(data);
237
+ const { item } = getRandomItem<MockInstance>(data);
229
238
  const { id } = item;
230
239
 
231
240
  await actions.navigateToUpdateScreen({ id });
@@ -237,7 +246,7 @@ describe("ModelRouter", () => {
237
246
  const { data } = await renderComponent();
238
247
  const {
239
248
  item: { id, firstName },
240
- } = getRandomItem<any>(data);
249
+ } = getRandomItem<MockInstance>(data);
241
250
 
242
251
  await actions.navigateToDetailScreen({ name: firstName });
243
252
 
@@ -264,7 +273,7 @@ describe("ModelRouter", () => {
264
273
  const { history, data } = await renderComponent({ router: "router" });
265
274
  const {
266
275
  item: { id },
267
- } = getRandomItem<any>(data);
276
+ } = getRandomItem<MockInstance>(data);
268
277
 
269
278
  await actions.navigateToUpdateScreen({ id });
270
279
 
@@ -275,7 +284,7 @@ describe("ModelRouter", () => {
275
284
  const { history, data } = await renderComponent({ router: "router" });
276
285
  const {
277
286
  item: { id, firstName },
278
- } = getRandomItem<any>(data);
287
+ } = getRandomItem<MockInstance>(data);
279
288
 
280
289
  await actions.navigateToDetailScreen({ name: firstName });
281
290
 
@@ -284,10 +293,10 @@ describe("ModelRouter", () => {
284
293
  });
285
294
 
286
295
  describe("list screen", () => {
287
- it("would call requestList when is mounted", async () => {
288
- const { requestList } = await renderComponent();
296
+ it("would call onRequestList when is mounted", async () => {
297
+ const { onRequestList } = await renderComponent();
289
298
 
290
- expect(requestList).toHaveBeenCalledTimes(1);
299
+ expect(onRequestList).toHaveBeenCalledTimes(1);
291
300
  });
292
301
 
293
302
  it("would render a loading indicator until the data is ready", async () => {
@@ -334,7 +343,7 @@ describe("ModelRouter", () => {
334
343
  const { data, history } = await renderComponent({ router: "router" });
335
344
  const {
336
345
  item: { id, firstName },
337
- } = getRandomItem<any>(data);
346
+ } = getRandomItem<MockInstance>(data);
338
347
 
339
348
  await userEvent.click(await screen.findByRole("cell", { name: firstName }));
340
349
 
@@ -346,7 +355,7 @@ describe("ModelRouter", () => {
346
355
  const { data } = await renderComponent();
347
356
 
348
357
  for (let i = 0; i < data.length; ++i) {
349
- const id = (data[i] as any).id;
358
+ const id = data[i].id;
350
359
  await assertions.expectMenuOption({ id });
351
360
  }
352
361
  });
@@ -355,7 +364,7 @@ describe("ModelRouter", () => {
355
364
  const { data } = await renderComponent({ router: "router" });
356
365
  const {
357
366
  item: { id },
358
- } = getRandomItem<any>(data);
367
+ } = getRandomItem<MockInstance>(data);
359
368
 
360
369
  await actions.openItemOptions({ id });
361
370
 
@@ -366,7 +375,7 @@ describe("ModelRouter", () => {
366
375
  const { data } = await renderComponent({ router: "router" });
367
376
  const {
368
377
  item: { id },
369
- } = getRandomItem<any>(data);
378
+ } = getRandomItem<MockInstance>(data);
370
379
 
371
380
  await actions.openItemOptions({ id });
372
381
 
@@ -417,11 +426,11 @@ describe("ModelRouter", () => {
417
426
  });
418
427
 
419
428
  it("would make a request when the form is submitted", async () => {
420
- const { onSubmitAdd, model } = await renderComponent({ screen: "add" });
429
+ const { onSubmitNewItem, model } = await renderComponent({ screen: "add" });
421
430
 
422
431
  const newInstance = await actions.fullfillModelForm({ model, submit: true });
423
432
 
424
- assertions.expectSubmitInstanceCall(onSubmitAdd, newInstance);
433
+ assertions.expectSubmitInstanceCall(onSubmitNewItem, newInstance);
425
434
  });
426
435
 
427
436
  it("would show a loading indicator when the request is in progress", async () => {
@@ -480,6 +489,18 @@ describe("ModelRouter", () => {
480
489
  await assertions.expectListScreen();
481
490
  });
482
491
 
492
+ it("would call onRequestItem when is mounted", async () => {
493
+ const {
494
+ onRequestItem,
495
+ randomItem: {
496
+ item: { id },
497
+ },
498
+ } = await renderComponent({ screen: "details" });
499
+
500
+ expect(onRequestItem).toHaveBeenCalledTimes(1);
501
+ expect(onRequestItem).toHaveBeenCalledWith(id);
502
+ });
503
+
483
504
  it("would show a loading indicator when the request is in progress", async () => {
484
505
  await renderComponent({ screen: "details" });
485
506
 
@@ -542,6 +563,18 @@ describe("ModelRouter", () => {
542
563
  await assertions.expectListScreen();
543
564
  });
544
565
 
566
+ it("would make a request to retrive the instance to update", async () => {
567
+ const {
568
+ onRequestUpdateItem,
569
+ randomItem: {
570
+ item: { id },
571
+ },
572
+ } = await renderComponent({ screen: "update" });
573
+
574
+ expect(onRequestUpdateItem).toHaveBeenCalledTimes(1);
575
+ expect(onRequestUpdateItem).toHaveBeenCalledWith(id);
576
+ });
577
+
545
578
  it("would show a loading indicator while the instance is requested", async () => {
546
579
  await renderComponent({ screen: "update" });
547
580
 
@@ -591,7 +624,7 @@ describe("ModelRouter", () => {
591
624
  it("would make a request when we try to delete an option", async () => {
592
625
  const { data, onRequestDelete } = await renderComponent();
593
626
 
594
- const { item } = getRandomItem<any>(data);
627
+ const { item } = getRandomItem<MockInstance>(data);
595
628
  const { id, firstName } = item;
596
629
 
597
630
  await screen.findByRole("cell", { name: firstName });
@@ -607,7 +640,7 @@ describe("ModelRouter", () => {
607
640
  it("would show a loading indicator while the request is in progress", async () => {
608
641
  const { data } = await renderComponent();
609
642
 
610
- const { item } = getRandomItem<any>(data);
643
+ const { item } = getRandomItem<MockInstance>(data);
611
644
  const { id, firstName } = item;
612
645
 
613
646
  await screen.findByRole("cell", { name: firstName });
@@ -619,7 +652,7 @@ describe("ModelRouter", () => {
619
652
 
620
653
  it("would remove the item from the list when the request finish", async () => {
621
654
  const { data } = await renderComponent();
622
- const { item } = getRandomItem<any>(data);
655
+ const { item } = getRandomItem<MockInstance>(data);
623
656
  const { id, firstName } = item;
624
657
 
625
658
  await screen.findByRole("cell", { name: firstName });
@@ -1,48 +1,23 @@
1
1
  import React from "react";
2
2
  import { Routes, Route } from "react-router-dom";
3
- import { Model } from "../generators.model";
4
- import { AddScreen, DetailsScreen, ListScreen, UpdateScreen } from "./screens";
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";
5
14
 
6
- export interface RequestState {
7
- idle?: boolean;
8
- loading?: boolean;
9
- error?: string;
10
- success?: boolean;
11
- }
15
+ export type ModelRouterProps<T extends BasicModelInstance> = DetailsScreenProps<T> &
16
+ ListScreenProps<T> &
17
+ AddScreenProps<T> &
18
+ UpdateScreenProps<T>;
12
19
 
13
- export interface ModelRouterProps {
14
- modelName: string;
15
- model: Model;
16
- //list screen
17
- requestList?: () => void;
18
- list: {
19
- data: any[];
20
- onClickRemoveItem: (item: any) => void;
21
- listRequest: RequestState;
22
- requestDelete: RequestState;
23
- };
24
- //add screen
25
- add: {
26
- onSubmit: (obj: object) => void;
27
- request: RequestState;
28
- };
29
- //detail screen
30
- detail: {
31
- onScreenMount?: (id: string) => void;
32
- request: RequestState;
33
- instance?: any;
34
- };
35
- //update screen
36
- update: {
37
- onSubmit: (obj: object) => void;
38
- request: RequestState;
39
- requestInstance: RequestState;
40
- onRequestInstance: (id: string) => void;
41
- instance?: any;
42
- };
43
- }
44
-
45
- export const ModelRouter = (props: ModelRouterProps) => {
20
+ export const ModelRouter = <T extends BasicModelInstance>(props: ModelRouterProps<T>) => {
46
21
  return (
47
22
  <Routes>
48
23
  <Route path="" element={<ListScreen {...props} />} />
@@ -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
+ };
@@ -1,52 +1,69 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { useNavigate } from "react-router-dom";
3
- import { ModelRouterProps } from "../..";
4
- import { FormLayout, FormLayoutProps } from "../../../layouts";
5
- import { useNotificationCenter } from "../../../providers/notification-center/notification-center.context";
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";
6
9
 
7
- const getAddPropsFromModel = ({ model, modelName, add }: ModelRouterProps): FormLayoutProps => {
8
- return {
9
- loading: add.request.loading,
10
- headerProps: {
11
- title: `Add ${modelName}`,
12
- preset: "default",
13
- breadcrumbs: [
14
- {
15
- id: "list",
16
- text: modelName,
17
- link: "/",
18
- },
19
- {
20
- id: "add",
21
- text: `Add new ${modelName}`,
22
- link: "/add",
23
- },
24
- ],
25
- },
26
- modelFormProps: {
27
- model,
28
- saveButtonText: "Save",
29
- onSubmit: add.onSubmit,
30
- },
31
- };
32
- };
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
+ }
33
23
 
34
- export const AddScreen = (props: ModelRouterProps) => {
24
+ export const AddScreen = <T extends BasicModelInstance>({
25
+ model,
26
+ modelName,
27
+ onSubmitNewItem,
28
+ newItemRequest,
29
+ }: AddScreenProps<T>) => {
35
30
  const navigate = useNavigate();
36
31
  const { show } = useNotificationCenter();
37
32
 
38
33
  useEffect(() => {
39
- if (props.add.request.success) {
34
+ if (newItemRequest.success) {
40
35
  show({ message: "Item added successfully", severity: "success" });
41
36
  navigate("/");
42
37
  }
43
- }, [props.add.request.success]);
38
+ }, [newItemRequest.success]);
44
39
 
45
40
  useEffect(() => {
46
- if (props.add.request.error) {
47
- show({ title: "We had an error", message: props.add.request.error, severity: "error" });
41
+ if (newItemRequest.error) {
42
+ show({ title: "We had an error", message: newItemRequest.error, severity: "error" });
48
43
  }
49
- }, [props.add.request.error]);
44
+ }, [newItemRequest.error]);
50
45
 
51
- return <FormLayout {...getAddPropsFromModel(props)} />;
46
+ return (
47
+ <HeaderLayout loading={newItemRequest.loading}>
48
+ <Header
49
+ title={`Add ${modelName}`}
50
+ preset="default"
51
+ breadcrumbs={[
52
+ {
53
+ id: "list",
54
+ text: modelName,
55
+ link: "/",
56
+ },
57
+ {
58
+ id: "add",
59
+ text: `Add new ${modelName}`,
60
+ link: "/add",
61
+ },
62
+ ]}
63
+ />
64
+ <Content>
65
+ <ModelForm model={model} saveButtonText="Save" onSubmit={onSubmitNewItem} />
66
+ </Content>
67
+ </HeaderLayout>
68
+ );
52
69
  };
@@ -1,53 +1,62 @@
1
1
  import React, { useEffect } from "react";
2
2
  import { useParams } from "react-router-dom";
3
- import { ModelRouterProps } from "..";
4
- import { PlaceholderIconArgs } from "../../../components";
5
- import { DetailsLayout, DetailsLayoutProps } from "../../../layouts";
6
- import SentimentVeryDissatisfiedIcon from "@mui/icons-material/SentimentVeryDissatisfied";
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";
7
8
 
8
- const getDetailsPropsFromModel = (
9
- { modelName, model, detail }: ModelRouterProps,
10
- id: string,
11
- ): DetailsLayoutProps => {
12
- return {
13
- loading: detail.request.loading,
14
- headerProps: {
15
- title: id,
16
- preset: "default",
17
- breadcrumbs: [
18
- {
19
- id: "list",
20
- text: modelName,
21
- link: "/",
22
- },
23
- {
24
- id: "detail",
25
- text: id,
26
- link: `/${id}`,
27
- },
28
- ],
29
- },
30
- objectDetailsProps: {
31
- model,
32
- instance: detail.instance,
33
- },
34
- notFoundPlaceholderProps: {
35
- title: "Not found",
36
- subtitle: "There is no item with that id",
37
- icon: ({ size, color }: PlaceholderIconArgs) => (
38
- <SentimentVeryDissatisfiedIcon color={color} sx={{ fontSize: size }} />
39
- ),
40
- },
41
- };
42
- };
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
+ }
43
27
 
44
- export const DetailsScreen = (props: ModelRouterProps) => {
45
- const onScreenMount = props.detail.onScreenMount;
28
+ export const DetailsScreen = <T extends BasicModelInstance>({
29
+ model,
30
+ modelName,
31
+ onRequestItem,
32
+ itemRequest,
33
+ detailsItem,
34
+ }: DetailsScreenProps<T>) => {
46
35
  const { id = "" } = useParams();
47
36
 
48
37
  useEffect(() => {
49
- onScreenMount && onScreenMount(id);
38
+ onRequestItem(id);
50
39
  }, [id]);
51
40
 
52
- return <DetailsLayout {...getDetailsPropsFromModel(props, id)} />;
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
+ );
53
62
  };