@altinn/altinn-components 0.4.1 → 0.5.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 (178) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/biome.jsonc +1 -1
  3. package/lib/components/Attachment/AttachmentLink.stories.ts +1 -1
  4. package/lib/components/Attachment/AttachmentList.stories.ts +1 -1
  5. package/lib/components/Button/Button.tsx +13 -10
  6. package/lib/components/Button/ButtonBase.tsx +1 -1
  7. package/lib/components/Button/ButtonIcon.tsx +16 -0
  8. package/lib/components/Button/ButtonLabel.tsx +16 -0
  9. package/lib/components/Button/Buttons.stories.tsx +64 -0
  10. package/lib/components/Button/ComboButton.tsx +9 -7
  11. package/lib/components/Button/IconButton.stories.tsx +47 -0
  12. package/lib/components/Button/IconButton.tsx +15 -5
  13. package/lib/components/Button/button.module.css +5 -46
  14. package/lib/components/Button/buttonBase.module.css +55 -23
  15. package/lib/components/Button/buttonIcon.module.css +17 -0
  16. package/lib/components/Button/buttonLabel.module.css +17 -0
  17. package/lib/components/Button/comboButton.module.css +15 -65
  18. package/lib/components/Button/iconButton.module.css +21 -4
  19. package/lib/components/Button/index.ts +2 -0
  20. package/lib/components/ContextMenu/ContextMenu.stories.ts +49 -0
  21. package/lib/components/ContextMenu/ContextMenu.tsx +12 -20
  22. package/lib/components/ContextMenu/ContextMenuBase.tsx +33 -0
  23. package/lib/components/Dialog/Dialog.tsx +2 -0
  24. package/lib/components/Dialog/DialogGroup.tsx +24 -0
  25. package/lib/components/Dialog/DialogList.stories.ts +14 -10
  26. package/lib/components/Dialog/DialogList.tsx +26 -11
  27. package/lib/components/Dialog/DialogListItem.tsx +12 -2
  28. package/lib/components/Dialog/DialogListItemBase.tsx +4 -2
  29. package/lib/components/Dialog/DialogNav.stories.ts +5 -5
  30. package/lib/components/Dialog/DialogNav.tsx +2 -6
  31. package/lib/components/Dialog/DialogSelect.tsx +1 -1
  32. package/lib/components/Dialog/dialogGroup.module.css +35 -0
  33. package/lib/components/Dropdown/Backdrop.tsx +4 -3
  34. package/lib/components/Dropdown/DrawerBase.tsx +5 -2
  35. package/lib/components/Dropdown/DrawerBody.tsx +12 -0
  36. package/lib/components/Dropdown/DrawerButton.tsx +17 -0
  37. package/lib/components/Dropdown/DrawerFooter.tsx +12 -0
  38. package/lib/components/Dropdown/DrawerHeader.tsx +19 -0
  39. package/lib/components/Dropdown/DrawerOrDropdown.tsx +29 -0
  40. package/lib/components/Dropdown/DropdownBase.tsx +5 -2
  41. package/lib/components/Dropdown/backdrop.module.css +3 -0
  42. package/lib/components/Dropdown/drawerBase.module.css +9 -0
  43. package/lib/components/Dropdown/drawerBody.module.css +5 -0
  44. package/lib/components/Dropdown/drawerButton.module.css +6 -0
  45. package/lib/components/Dropdown/drawerFooter.module.css +13 -0
  46. package/lib/components/Dropdown/drawerHeader.module.css +17 -0
  47. package/lib/components/Dropdown/drawerOrDropdown.module.css +19 -0
  48. package/lib/components/Dropdown/dropdownBase.module.css +15 -3
  49. package/lib/components/Dropdown/index.ts +7 -1
  50. package/lib/components/Footer/footerMenu.module.css +5 -0
  51. package/lib/components/GlobalMenu/GlobalMenu.stories.tsx +9 -9
  52. package/lib/components/GlobalMenu/GlobalMenu.tsx +5 -5
  53. package/lib/components/Header/{Header.stories.ts → Header.stories.tsx} +79 -20
  54. package/lib/components/Header/Header.tsx +24 -37
  55. package/lib/components/Header/HeaderBase.tsx +7 -3
  56. package/lib/components/Header/header.module.css +10 -42
  57. package/lib/components/Header/headerBase.module.css +43 -0
  58. package/lib/components/Header/headerButton.module.css +1 -0
  59. package/lib/components/Layout/Layout.stories.tsx +77 -38
  60. package/lib/components/Layout/Layout.tsx +5 -3
  61. package/lib/components/Layout/LayoutBase.tsx +3 -2
  62. package/lib/components/Layout/layoutBase.module.css +11 -0
  63. package/lib/components/Layout/layoutBody.module.css +1 -0
  64. package/lib/components/LayoutAction/ActionHeader.tsx +1 -1
  65. package/lib/components/LayoutAction/ActionMenu.tsx +2 -4
  66. package/lib/components/LayoutAction/actionMenu.module.css +3 -0
  67. package/lib/components/List/List.stories.tsx +43 -0
  68. package/lib/components/List/List.tsx +6 -6
  69. package/lib/components/List/ListBase.tsx +6 -6
  70. package/lib/components/List/ListItem.tsx +4 -1
  71. package/lib/components/List/ListItemBase.tsx +20 -4
  72. package/lib/components/List/listBase.module.css +3 -3
  73. package/lib/components/List/listItemBase.module.css +4 -0
  74. package/lib/components/Menu/Menu.stories.ts +46 -46
  75. package/lib/components/Menu/Menu.tsx +3 -102
  76. package/lib/components/Menu/MenuBase.tsx +47 -3
  77. package/lib/components/Menu/MenuItem.tsx +6 -4
  78. package/lib/components/Menu/MenuItemBase.tsx +7 -0
  79. package/lib/components/Menu/MenuItems.stories.ts +438 -0
  80. package/lib/components/Menu/MenuItems.tsx +96 -0
  81. package/lib/components/Menu/MenuOption.tsx +4 -1
  82. package/lib/components/Menu/{MenuGroup.tsx → __MenuGroup.tsx} +1 -1
  83. package/lib/components/Menu/index.ts +1 -1
  84. package/lib/components/Menu/menu.module.css +2 -3
  85. package/lib/components/Menu/menuBase.module.css +25 -0
  86. package/lib/components/Menu/menuItemBase.module.css +5 -4
  87. package/lib/components/Meta/MetaItemBase.tsx +1 -1
  88. package/lib/components/Meta/MetaItemLabel.tsx +1 -1
  89. package/lib/components/Meta/MetaItemMedia.tsx +1 -1
  90. package/lib/components/Page/PageBase.tsx +14 -0
  91. package/lib/components/Page/PageHeader.tsx +21 -0
  92. package/lib/components/Page/PageHeaderMedia.tsx +25 -0
  93. package/lib/components/Page/SectionBase.tsx +52 -0
  94. package/lib/components/Page/SectionFooter.tsx +15 -0
  95. package/lib/components/Page/SectionHeader.tsx +16 -0
  96. package/lib/components/Page/index.ts +5 -0
  97. package/lib/components/Page/pageHeader.module.css +5 -0
  98. package/lib/components/Page/sectionBase.module.css +82 -0
  99. package/lib/components/Page/sectionFooter.module.css +8 -0
  100. package/lib/components/Page/sectionHeader.module.css +9 -0
  101. package/lib/components/RootProvider/RootProvider.tsx +43 -7
  102. package/lib/components/Searchbar/Autocomplete.stories.tsx +77 -0
  103. package/lib/components/Searchbar/Autocomplete.tsx +44 -0
  104. package/lib/components/Searchbar/AutocompleteBase.tsx +16 -0
  105. package/lib/components/Searchbar/AutocompleteGroup.tsx +17 -0
  106. package/lib/components/Searchbar/AutocompleteItem.tsx +23 -0
  107. package/lib/components/Searchbar/SearchField.tsx +78 -0
  108. package/lib/components/Searchbar/Searchbar.stories.tsx +151 -0
  109. package/lib/components/Searchbar/Searchbar.tsx +18 -0
  110. package/lib/components/Searchbar/SearchbarBase.tsx +23 -0
  111. package/lib/components/Searchbar/autocompleteBase.module.css +17 -0
  112. package/lib/components/Searchbar/autocompleteGroup.module.css +3 -0
  113. package/lib/components/Searchbar/autocompleteItem.module.css +19 -0
  114. package/lib/components/Searchbar/index.ts +1 -0
  115. package/lib/components/Searchbar/searchField.module.css +54 -0
  116. package/lib/components/Searchbar/searchbarBase.module.css +20 -0
  117. package/lib/components/Toolbar/Toolbar.stories.tsx +10 -10
  118. package/lib/components/Toolbar/Toolbar.tsx +28 -10
  119. package/lib/components/Toolbar/ToolbarAdd.tsx +6 -5
  120. package/lib/components/Toolbar/ToolbarBase.tsx +5 -20
  121. package/lib/components/Toolbar/ToolbarButton.tsx +1 -1
  122. package/lib/components/Toolbar/ToolbarFilter.tsx +11 -6
  123. package/lib/components/Toolbar/ToolbarMenu.tsx +8 -7
  124. package/lib/components/Toolbar/ToolbarOptions.stories.ts +5 -5
  125. package/lib/components/Toolbar/ToolbarOptions.tsx +34 -21
  126. package/lib/components/Toolbar/toolbarAdd.module.css +7 -0
  127. package/lib/components/Toolbar/toolbarBase.module.css +19 -0
  128. package/lib/components/Toolbar/toolbarButton.module.css +1 -1
  129. package/lib/components/Toolbar/toolbarFilter.module.css +25 -0
  130. package/lib/components/Toolbar/toolbarMenu.module.css +7 -0
  131. package/lib/components/Typography/Heading.tsx +23 -0
  132. package/lib/components/Typography/Typography.tsx +8 -5
  133. package/lib/components/Typography/heading.module.css +21 -0
  134. package/lib/components/Typography/index.ts +1 -0
  135. package/lib/components/Typography/typography.module.css +8 -0
  136. package/lib/components/index.ts +2 -0
  137. package/lib/hooks/index.ts +3 -0
  138. package/lib/{components/Menu → hooks}/useEscapeKey.ts +2 -2
  139. package/lib/hooks/useMenu.tsx +80 -0
  140. package/lib/index.ts +1 -0
  141. package/lib/stories/Color/MenuItem.stories.tsx +43 -0
  142. package/lib/stories/Color/Swatches.stories.tsx +19 -0
  143. package/lib/stories/Color/Swatches.tsx +42 -0
  144. package/lib/stories/Color/colors.json +62 -0
  145. package/lib/stories/Color/swatches.module.css +14 -0
  146. package/lib/stories/Inbox/BookmarksPage.tsx +52 -0
  147. package/lib/stories/Inbox/DialogPage.tsx +15 -0
  148. package/lib/stories/Inbox/Inbox.stories.tsx +55 -0
  149. package/lib/stories/Inbox/Inbox.tsx +12 -0
  150. package/lib/stories/Inbox/InboxLayout.tsx +50 -0
  151. package/lib/stories/Inbox/InboxPage.tsx +50 -0
  152. package/lib/stories/Inbox/InboxProvider.tsx +136 -0
  153. package/lib/stories/Inbox/InboxSection.tsx +39 -0
  154. package/lib/stories/Inbox/InboxToolbar.tsx +94 -0
  155. package/lib/stories/Inbox/ProfilePage.tsx +35 -0
  156. package/lib/stories/Inbox/SettingsPage.tsx +19 -0
  157. package/lib/stories/Inbox/accounts/accounts.ts +24 -0
  158. package/lib/stories/Inbox/accounts/index.ts +1 -0
  159. package/lib/stories/Inbox/actionMenu.ts +24 -0
  160. package/lib/stories/Inbox/dialogs/brreg-completed.json +35 -0
  161. package/lib/stories/Inbox/dialogs/brreg-draft.json +45 -0
  162. package/lib/stories/Inbox/dialogs/index.ts +10 -0
  163. package/lib/stories/Inbox/dialogs/skatt-2023.json +33 -0
  164. package/lib/stories/Inbox/groupBy.ts +19 -0
  165. package/lib/stories/Inbox/inboxSection.module.css +19 -0
  166. package/lib/stories/Inbox/index.ts +15 -0
  167. package/lib/stories/Inbox/layout/footer.ts +27 -0
  168. package/lib/stories/Inbox/layout/header.ts +11 -0
  169. package/lib/stories/Inbox/layout/index.ts +3 -0
  170. package/lib/stories/Inbox/layout/menu.ts +64 -0
  171. package/package.json +1 -1
  172. package/tsconfig.json +7 -2
  173. package/lib/components/Header/HeaderSearch.stories.ts +0 -20
  174. package/lib/components/Header/HeaderSearch.tsx +0 -44
  175. package/lib/components/Header/headerSearch.module.css +0 -30
  176. package/lib/components/Toolbar/toolbar.module.css +0 -43
  177. /package/lib/components/ContextMenu/{contextMenu.module.css → contextMenuBase.module.css} +0 -0
  178. /package/lib/{components/Menu → hooks}/useClickOutside.ts +0 -0
@@ -0,0 +1,12 @@
1
+ import { InboxLayout, InboxProvider, InboxSection } from './';
2
+ import type { InboxDefaultValue } from './';
3
+
4
+ export const Inbox = ({ accounts, accountId, inboxId, dialogId, dialogs, selectedIds }: InboxDefaultValue) => {
5
+ return (
6
+ <InboxProvider defaultValue={{ accounts, accountId, inboxId, dialogId, dialogs, selectedIds }}>
7
+ <InboxLayout>
8
+ <InboxSection />
9
+ </InboxLayout>
10
+ </InboxProvider>
11
+ );
12
+ };
@@ -0,0 +1,50 @@
1
+ import type { ReactNode } from 'react';
2
+ import { ActionFooter, ActionHeader, ActionMenu, Layout } from '../../components';
3
+ import { actionMenu, footer, header, menu } from './';
4
+ import { useInbox } from './';
5
+
6
+ export interface InboxLayoutProps {
7
+ children: ReactNode;
8
+ }
9
+
10
+ export const InboxLayout = ({ children }: InboxLayoutProps) => {
11
+ const { theme, itemsCount, selectedCount, inboxId, accounts, dialogId, onInboxId, onUnselectAll } = useInbox();
12
+
13
+ const selectedTitle = `${selectedCount} av ${itemsCount} valgt`;
14
+ const bulkMode = selectedCount > 0;
15
+
16
+ return (
17
+ <Layout
18
+ theme={selectedCount ? 'neutral' : theme}
19
+ footer={footer}
20
+ header={{
21
+ ...header,
22
+ menu: {
23
+ accounts,
24
+ },
25
+ search: !dialogId && {
26
+ ...header.search,
27
+ },
28
+ }}
29
+ sidebar={{
30
+ hidden: bulkMode,
31
+ menu: {
32
+ ...menu,
33
+ items: menu?.items.map((item) => {
34
+ return {
35
+ ...item,
36
+ selected: inboxId === item.id,
37
+ onClick: () => onInboxId(item.id),
38
+ };
39
+ }),
40
+ },
41
+ }}
42
+ >
43
+ <ActionHeader title={selectedTitle} hidden={!bulkMode} onDismiss={onUnselectAll} />
44
+ {children}
45
+ <ActionFooter hidden={!bulkMode}>
46
+ <ActionMenu theme="global-dark" items={actionMenu} />
47
+ </ActionFooter>
48
+ </Layout>
49
+ );
50
+ };
@@ -0,0 +1,50 @@
1
+ 'use client';
2
+ import { DialogList, PageBase } from '../../components';
3
+ import { useInbox } from './';
4
+ import { InboxToolbar } from './InboxToolbar';
5
+
6
+ export function InboxPage() {
7
+ const { inboxId, onDialogId, items = [], onSelectId, selectedCount } = useInbox();
8
+ const selected = items?.filter((item) => item.selected);
9
+
10
+ const inboxItems = items
11
+ ?.filter((item) => {
12
+ const inboxStatus = item?.status.value;
13
+
14
+ if (inboxId === 'drafts' && inboxStatus !== 'draft') {
15
+ return false;
16
+ }
17
+ if (inboxId === 'sent' && inboxStatus !== 'sent') {
18
+ return false;
19
+ }
20
+ if (inboxId === 'inbox' && (item.status.value === 'sent' || item.status.value === 'draft')) {
21
+ return false;
22
+ }
23
+
24
+ return true;
25
+ })
26
+ .map((item) => {
27
+ return {
28
+ ...item,
29
+ groupId: 'g1',
30
+ onClick: selectedCount > 0 ? () => onSelectId(item.id) : () => onDialogId(item.id),
31
+ select: {
32
+ checked: item?.selected,
33
+ onChange: () => onSelectId(item.id),
34
+ },
35
+ };
36
+ });
37
+
38
+ const inboxGroups = {
39
+ g1: {
40
+ title: 'Gruppe',
41
+ },
42
+ };
43
+
44
+ return (
45
+ <PageBase spacing="md" margin="lg">
46
+ {!selected.length > 0 && <InboxToolbar items={inboxItems} />}
47
+ <DialogList items={inboxItems} groups={inboxGroups} />
48
+ </PageBase>
49
+ );
50
+ }
@@ -0,0 +1,136 @@
1
+ import { type ReactNode, createContext, useContext, useState } from 'react';
2
+ import type { DialogProps } from '../../components';
3
+
4
+ interface AccountProps {
5
+ id?: string;
6
+ type?: string;
7
+ name?: string;
8
+ selected?: boolean;
9
+ }
10
+
11
+ export interface InboxDefaultValue {
12
+ accountId?: string | null;
13
+ accounts: AccountProps[];
14
+ inboxId?: string | null;
15
+ dialogId?: string | null;
16
+ dialogs?: DialogProps[];
17
+ selectedIds?: string[];
18
+ }
19
+
20
+ interface InboxProviderProps {
21
+ children: ReactNode;
22
+ defaultValue?: InboxDefaultValue;
23
+ }
24
+
25
+ interface InboxContextProvider {
26
+ theme?: string;
27
+ account?: AccountProps;
28
+ accountId?: string | null;
29
+ accounts?: AccountProps[];
30
+ inboxId?: string | null;
31
+ dialogId?: string | null;
32
+ onAccountId?: (id: string) => void;
33
+ onInboxId?: (id: string) => void;
34
+ onDialogId?: (id: string) => void;
35
+ items?: (DialogProps & { selected: boolean })[];
36
+ itemsCount: number;
37
+ onSelectId?: (id: string) => void;
38
+ onUnselectAll?: () => void;
39
+ selectedCount: number;
40
+ }
41
+
42
+ const InboxContext = createContext<InboxContextProvider>({
43
+ theme: '',
44
+ account: {},
45
+ accountId: null,
46
+ accounts: [],
47
+ inboxId: null,
48
+ dialogId: null,
49
+ items: [],
50
+ itemsCount: 0,
51
+ selectedCount: 0,
52
+ });
53
+
54
+ export const InboxProvider = ({ defaultValue, children }: InboxProviderProps) => {
55
+ const [accountId, setAccountId] = useState(defaultValue?.accountId ?? null);
56
+ const [accounts, setAccounts] = useState(defaultValue?.accounts ?? []);
57
+ const [inboxId, setInboxId] = useState(defaultValue?.inboxId ?? null);
58
+ const [dialogId, setDialogId] = useState(defaultValue?.dialogId ?? null);
59
+ const [selectedIds, setSelectedIds] = useState(defaultValue?.selectedIds || []);
60
+
61
+ const onAccountId = (id: string) => {
62
+ setAccountId(id);
63
+ setAccounts((prevState) => {
64
+ return prevState.map((item) => {
65
+ return {
66
+ ...item,
67
+ selected: id === item.id,
68
+ };
69
+ });
70
+ });
71
+ };
72
+
73
+ const account = accounts?.find((item) => item.id === accountId);
74
+ const theme = account?.type;
75
+
76
+ const onInboxId = (id: string) => {
77
+ setInboxId(id);
78
+ setDialogId(null);
79
+ };
80
+
81
+ const onDialogId = (id: string) => {
82
+ setDialogId((prevState) => (prevState === id ? null : id));
83
+ };
84
+
85
+ const onSelectId = (id: string) => {
86
+ setSelectedIds((prevState) => {
87
+ if (prevState.includes(id)) {
88
+ return prevState.filter((prevId) => prevId !== id);
89
+ }
90
+ return [...prevState, id];
91
+ });
92
+ };
93
+
94
+ const onUnselectAll = () => {
95
+ setSelectedIds([]);
96
+ };
97
+
98
+ const items = defaultValue?.dialogs?.map((item) => ({
99
+ ...item,
100
+ selected: selectedIds.includes(item.id),
101
+ }));
102
+
103
+ const itemsCount = items?.length || 0;
104
+ const selectedCount = selectedIds.length;
105
+
106
+ return (
107
+ <InboxContext.Provider
108
+ value={{
109
+ theme,
110
+ account,
111
+ accounts,
112
+ accountId,
113
+ onAccountId,
114
+ inboxId,
115
+ onInboxId,
116
+ dialogId,
117
+ onDialogId,
118
+ items,
119
+ itemsCount,
120
+ onSelectId,
121
+ onUnselectAll,
122
+ selectedCount,
123
+ }}
124
+ >
125
+ {children}
126
+ </InboxContext.Provider>
127
+ );
128
+ };
129
+
130
+ export const useInbox = () => {
131
+ return useContext(InboxContext);
132
+ };
133
+
134
+ export const useProfile = () => {
135
+ return useContext(InboxContext);
136
+ };
@@ -0,0 +1,39 @@
1
+ 'use client';
2
+ import { actionMenu, useInbox } from './';
3
+ import { BookmarksPage, DialogPage, InboxPage, ProfilePage, SettingsPage } from './';
4
+
5
+ export function InboxSection() {
6
+ const { inboxId, dialogId, onDialogId, items = [] } = useInbox();
7
+
8
+ if (inboxId === 'bookmarks') {
9
+ return <BookmarksPage />;
10
+ }
11
+
12
+ if (inboxId === 'settings') {
13
+ return <SettingsPage />;
14
+ }
15
+
16
+ if (inboxId === 'profile') {
17
+ return <ProfilePage />;
18
+ }
19
+
20
+ if (dialogId) {
21
+ const dialog = items.find((item) => item.id === dialogId);
22
+ return (
23
+ <DialogPage
24
+ dialog={{
25
+ ...dialog,
26
+ menu: {
27
+ id: 'context-menu',
28
+ items: actionMenu,
29
+ },
30
+ backButton: {
31
+ onClick: () => onDialogId(dialogId),
32
+ },
33
+ }}
34
+ />
35
+ );
36
+ }
37
+
38
+ return <InboxPage />;
39
+ }
@@ -0,0 +1,94 @@
1
+ 'use client';
2
+ import { Toolbar } from '../../components';
3
+ import { useInbox } from './';
4
+
5
+ export function InboxToolbar({ items }) {
6
+ const { accounts = [], accountId, onAccountId } = useInbox();
7
+
8
+ const senderOptions = {};
9
+
10
+ items?.map((item) => {
11
+ const { sender } = item;
12
+
13
+ if (!senderOptions[sender?.name]) {
14
+ senderOptions[sender?.name] = {
15
+ label: sender.name,
16
+ value: sender.name,
17
+ count: 0,
18
+ };
19
+ }
20
+
21
+ senderOptions[sender?.name].count++;
22
+ });
23
+
24
+ const currentAccount = accounts?.find((item) => item.id === accountId);
25
+
26
+ const accountMenu = {
27
+ label: currentAccount?.name,
28
+ value: currentAccount?.id,
29
+ items: accounts.map((item) => {
30
+ return {
31
+ group: item.type,
32
+ title: item?.name,
33
+ avatar: item,
34
+ selected: item.selected,
35
+ onClick: () => onAccountId(item.id),
36
+ };
37
+ }),
38
+ };
39
+
40
+ const filters =
41
+ items &&
42
+ [
43
+ {
44
+ name: 'status',
45
+ label: 'Velg status',
46
+ optionType: 'checkbox',
47
+ options: [
48
+ {
49
+ groupId: '1',
50
+ value: 'draft',
51
+ label: 'Utkast',
52
+ },
53
+ {
54
+ groupId: '1',
55
+ value: 'sent',
56
+ label: 'Sendt',
57
+ },
58
+ {
59
+ groupId: '2',
60
+ value: 'in-progress',
61
+ label: 'Under arbeid',
62
+ },
63
+ {
64
+ groupId: '2',
65
+ value: 'requires-attention',
66
+ label: 'Krever handling',
67
+ },
68
+ {
69
+ groupId: '2',
70
+ value: 'completed',
71
+ label: 'Avsluttet',
72
+ },
73
+ ],
74
+ },
75
+ {
76
+ name: 'sender',
77
+ label: 'Velg avsender',
78
+ optionType: 'checkbox',
79
+ options: Object.values(senderOptions)?.map((item) => {
80
+ return {
81
+ ...item,
82
+ badge: { label: item?.count.toString() || '2' },
83
+ };
84
+ }),
85
+ },
86
+ ].map((item) => {
87
+ return {
88
+ ...item,
89
+ removable: true,
90
+ };
91
+ });
92
+
93
+ return <Toolbar menu={accountMenu} filters={filters} />;
94
+ }
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import {
3
+ Avatar,
4
+ Heading,
5
+ ListBase,
6
+ ListItem,
7
+ MetaItem,
8
+ PageBase,
9
+ PageHeader,
10
+ SectionBase,
11
+ SectionFooter,
12
+ SectionHeader,
13
+ Typography,
14
+ } from '../../components';
15
+ import { useProfile } from './';
16
+
17
+ export function ProfilePage() {
18
+ const { account } = useProfile();
19
+
20
+ return (
21
+ <PageBase>
22
+ <PageHeader
23
+ title={account.name}
24
+ avatar={{ type: account?.type, name: account.name }}
25
+ inset
26
+ padding
27
+ spacing="lg"
28
+ color="white"
29
+ shadow="xs"
30
+ >
31
+ <Typography size="lg">Lorem ipsum dolor sit amet</Typography>
32
+ </PageHeader>
33
+ </PageBase>
34
+ );
35
+ }
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ import {
3
+ Heading,
4
+ ListBase,
5
+ ListItem,
6
+ MetaItem,
7
+ PageBase,
8
+ SectionBase,
9
+ SectionFooter,
10
+ SectionHeader,
11
+ Typography,
12
+ } from '../../components';
13
+ import { useProfile } from './';
14
+
15
+ export function SettingsPage() {
16
+ const { account } = useProfile;
17
+
18
+ return <PageBase inset>{JSON.stringify(account)}</PageBase>;
19
+ }
@@ -0,0 +1,24 @@
1
+ export const accounts = [
2
+ {
3
+ type: 'person',
4
+ name: 'Aurora Mikalsen',
5
+ selected: true,
6
+ },
7
+ {
8
+ type: 'company',
9
+ name: 'Auroras blomster',
10
+ },
11
+ {
12
+ type: 'company',
13
+ name: 'Aurora bier',
14
+ },
15
+ {
16
+ type: 'company',
17
+ name: 'Auroras bier og blomster',
18
+ },
19
+ ].map((item, index) => {
20
+ return {
21
+ ...item,
22
+ id: 'a' + index,
23
+ };
24
+ });
@@ -0,0 +1 @@
1
+ export * from './accounts';
@@ -0,0 +1,24 @@
1
+ import type { MenuItemProps } from '../../components';
2
+
3
+ export const actionMenu: MenuItemProps[] = [
4
+ {
5
+ id: '1',
6
+ icon: 'arrow-redo',
7
+ title: 'Del og gi tilgang',
8
+ },
9
+ {
10
+ id: '2',
11
+ icon: 'eye',
12
+ title: 'Marker som lest',
13
+ },
14
+ {
15
+ id: '3',
16
+ icon: 'archive',
17
+ title: 'Flytt til arkiv',
18
+ },
19
+ {
20
+ id: '4',
21
+ icon: 'trash',
22
+ title: 'Flytt til papirkurv',
23
+ },
24
+ ];
@@ -0,0 +1,35 @@
1
+ {
2
+ "_createdAt": "2024-10-23T09:33:00Z",
3
+ "_id": "95f30463-b886-402d-b765-95d9eccf68c0",
4
+ "_rev": "n6M6ED8lI6VdyYqDQoyiME",
5
+ "_type": "dialog",
6
+ "_updatedAt": "2024-10-28T17:07:12Z",
7
+ "additionalInfo": "For at du skal kunne registrere enkeltpersonforetaket, er du nødt til å drive med næringsaktivitet. Dette er aktivitet som er egnet til å ha et visst omfang og varighet.",
8
+ "body": "## Nøkkelinformasjon\n- **Foretakets navn:** Olas Enkeltmannsforetak\n- **Organisasjonsnummer:** 999 999 999\n- **Dato registrert**: 14. mai 2024\n\n## Hva nå?\nTips og triks til deg som har startet enkeltpersonforetak:\n- Få en regnskapsfører.\n- Slik driver du selskapet ditt.\n- Bla bla bla.",
9
+ "history": [
10
+ {
11
+ "_key": "334c343862da",
12
+ "_type": "historyItem",
13
+ "summary": "Skjema ble opprettet."
14
+ },
15
+ {
16
+ "_key": "f5cc7d1053c9",
17
+ "_type": "historyItem",
18
+ "summary": "Bla bla bla."
19
+ }
20
+ ],
21
+ "recipient": {
22
+ "type": "person",
23
+ "name": "Rein Regnskapsfører",
24
+ "imageUrl": null
25
+ },
26
+ "sender": {
27
+ "type": "company",
28
+ "name": "Brønnøysundregistrene",
29
+ "imageUrl": "https://cdn.sanity.io/images/z3it2oa7/production/3be5df0229c0b58c7ab59db2ade6208cc83954d2-300x300.png?w=96"
30
+ },
31
+ "status": { "label": "Avsluttet", "value": "completed" },
32
+ "summary": "Gratulerer! Ditt enkeltpersonforetak er godkjent og klart til bruk.",
33
+ "title": "Registrering av enkeltmannsforetak",
34
+ "updatedAt": "2024-10-28T17:07:12Z"
35
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "_createdAt": "2024-10-23T07:17:42Z",
3
+ "_id": "7cda3a28-2171-488c-8554-6b061b48e533",
4
+ "_rev": "n6M6ED8lI6VdyYqDQoylrM",
5
+ "_type": "dialog",
6
+ "_updatedAt": "2024-10-28T17:07:32Z",
7
+ "action": [
8
+ { "priority": "primary", "label": "Til skjema" },
9
+ {
10
+ "label": "Forkast utkast"
11
+ }
12
+ ],
13
+ "additionalInfo": "For at du skal kunne registrere enkeltpersonforetaket, er du nødt til å drive med næringsaktivitet. Dette er aktivitet som er egnet til å ha et visst omfang og varighet.",
14
+ "body": "## Oppsummering\n- **Foretakets navn:** Olas Enkeltmannsforetak\n- **Lorem ipsum:** Data",
15
+ "history": [
16
+ {
17
+ "_key": "334c343862da",
18
+ "_type": "historyItem",
19
+ "summary": "Skjema ble opprettet."
20
+ },
21
+ {
22
+ "_key": "f5cc7d1053c9",
23
+ "_type": "historyItem",
24
+ "summary": "Bla bla bla."
25
+ }
26
+ ],
27
+ "recipient": { "type": "person", "name": "Ola Nordmann", "imageUrl": null },
28
+ "sender": {
29
+ "type": "company",
30
+ "name": "Brønnøysundregistrene",
31
+ "imageUrl": "https://cdn.sanity.io/images/z3it2oa7/production/3be5df0229c0b58c7ab59db2ade6208cc83954d2-300x300.png?w=96"
32
+ },
33
+ "status": { "label": "Draft", "value": "draft" },
34
+ "summary": "Et utkast til skjema er lagret.",
35
+ "title": "Registrering av enkeltmannsforetak",
36
+ "updatedAt": "2024-10-28T17:07:32Z",
37
+ "actions": [
38
+ { "_key": "4af713286bf6", "_type": "dialogAction", "label": "Til skjema" },
39
+ {
40
+ "_key": "1ef5bc424eee",
41
+ "_type": "dialogAction",
42
+ "label": "Forkast utkast"
43
+ }
44
+ ]
45
+ }
@@ -0,0 +1,10 @@
1
+ import brregCompleted from './brreg-completed.json';
2
+ import brregDraft from './brreg-draft.json';
3
+ import skatt2023 from './skatt-2023.json';
4
+
5
+ export const dialogs = [brregDraft, brregCompleted, skatt2023].map((item, index) => {
6
+ return {
7
+ ...item,
8
+ id: 'd' + index,
9
+ };
10
+ });
@@ -0,0 +1,33 @@
1
+ {
2
+ "_createdAt": "2024-10-23T21:31:44Z",
3
+ "_id": "83b80be7-9b3a-474e-94bc-d5d24710ec9c",
4
+ "_rev": "5k1KJXrtipgHMEvoTB1MJV",
5
+ "_type": "dialog",
6
+ "_updatedAt": "2024-10-28T17:07:25Z",
7
+ "action": [
8
+ {
9
+ "_key": "2d7c53da7794",
10
+ "_type": "dialogAction",
11
+ "label": "Åpne skattemeldingen"
12
+ }
13
+ ],
14
+ "dueAt": "2024-05-31",
15
+ "recipient": { "type": "person", "name": "Ola Nordmann", "imageUrl": null },
16
+ "sender": {
17
+ "type": "company",
18
+ "name": "Skatteetaten",
19
+ "imageUrl": "https://cdn.sanity.io/images/z3it2oa7/production/e16a4f384d1d5ed959e1d74f0626259711d67509-88x88.png?w=96"
20
+ },
21
+ "status": { "label": "Krever handling", "value": "requires-attention" },
22
+ "summary": "Skattemeldingen for 2023 er tilgjengelig. Du bør sjekke at opplysningene er riktige.",
23
+ "title": "Skatten din 2023",
24
+ "updatedAt": "2024-10-28T17:07:25Z",
25
+ "actions": [
26
+ {
27
+ "_key": "2d7c53da7794",
28
+ "_type": "dialogAction",
29
+ "label": "Åpne skattemeldingen"
30
+ }
31
+ ],
32
+ "history": null
33
+ }
@@ -0,0 +1,19 @@
1
+ interface GroupableItem {
2
+ group: string;
3
+ }
4
+
5
+ export const groupBy = (items: GroupableItem[]) => {
6
+ const groups: Record<string, GroupableItem[]> = items?.reduce(
7
+ (acc: Record<string, GroupableItem[]>, item) => {
8
+ const group = item?.group || '';
9
+ if (!acc[group]) {
10
+ acc[group] = [];
11
+ }
12
+ acc[group].push(item);
13
+ return acc;
14
+ },
15
+ {} as Record<string, GroupableItem[]>,
16
+ );
17
+
18
+ return groups;
19
+ };
@@ -0,0 +1,19 @@
1
+ .section {
2
+ width: 100%;
3
+ display: flex;
4
+ flex-direction: column;
5
+ row-gap: 1rem;
6
+ }
7
+
8
+ .header {
9
+ width: 100%;
10
+ display: flex;
11
+ flex-direction: column;
12
+ }
13
+
14
+ .title {
15
+ font-size: 1.25rem;
16
+ font-weight: 600;
17
+ line-height: 1.25;
18
+ margin: 6px 0;
19
+ }
@@ -0,0 +1,15 @@
1
+ export * from './accounts/';
2
+ export * from './dialogs/';
3
+ export * from './layout/';
4
+
5
+ export * from './actionMenu';
6
+
7
+ export * from './InboxProvider';
8
+ export * from './InboxLayout';
9
+ export * from './InboxSection';
10
+
11
+ export * from './InboxPage';
12
+ export * from './DialogPage';
13
+ export * from './BookmarksPage';
14
+ export * from './ProfilePage';
15
+ export * from './SettingsPage';