@rkosafo/cai.components 0.0.66 → 0.0.67
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.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/keycloak/keycloakService.d.ts +5 -1
- package/dist/keycloak/keycloakService.js +1 -1
- package/dist/layout/mailing/MailPaginator.svelte +36 -0
- package/dist/layout/mailing/MailPaginator.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailSidebar.svelte +39 -0
- package/dist/layout/mailing/MailSidebar.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailToolBar.svelte +174 -0
- package/dist/layout/mailing/MailToolBar.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailingHeader.svelte +5 -0
- package/dist/layout/mailing/MailingHeader.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailingMessageCard.svelte +106 -0
- package/dist/layout/mailing/MailingMessageCard.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailingMessageViewer.svelte +63 -0
- package/dist/layout/mailing/MailingMessageViewer.svelte.d.ts +4 -0
- package/dist/layout/mailing/MailingModule.svelte +415 -0
- package/dist/layout/mailing/MailingModule.svelte.d.ts +4 -0
- package/dist/layout/mailing/index.d.ts +7 -0
- package/dist/layout/mailing/index.js +7 -0
- package/dist/layout/mailing/types.d.ts +126 -0
- package/dist/layout/mailing/types.js +1 -0
- package/dist/themes/themes.d.ts +1 -0
- package/dist/themes/themes.js +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/ui/pageLoader/PageLoader.svelte +6 -2
- package/dist/ui/toast/Toast.svelte +1 -1
- package/dist/ui/toast/Toast.svelte.d.ts +1 -1
- package/dist/ui/tooltip/Tooltip.svelte +51 -0
- package/dist/ui/tooltip/Tooltip.svelte.d.ts +17 -0
- package/dist/ui/tooltip/index.d.ts +2 -0
- package/dist/ui/tooltip/index.js +2 -0
- package/dist/ui/tooltip/theme.d.ts +90 -0
- package/dist/ui/tooltip/theme.js +45 -0
- package/dist/utils/paginate.svelte.d.ts +1 -0
- package/dist/utils/paginate.svelte.js +4 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,9 @@ export * from './ui/box/index.js';
|
|
|
27
27
|
export * from './ui/breadcrumb/index.js';
|
|
28
28
|
export * from './layout/ComponentCanvas/index.js';
|
|
29
29
|
export * from './ui/toast/index.js';
|
|
30
|
+
export * from './ui/tooltip/index.js';
|
|
30
31
|
export * from './layout/Chat/index.js';
|
|
32
|
+
export * from './layout/mailing/index.js';
|
|
31
33
|
export * from './forms/input/index.js';
|
|
32
34
|
export * from './forms/label/index.js';
|
|
33
35
|
export * from './forms/datepicker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -28,7 +28,9 @@ export * from './ui/box/index.js';
|
|
|
28
28
|
export * from './ui/breadcrumb/index.js';
|
|
29
29
|
export * from './layout/ComponentCanvas/index.js';
|
|
30
30
|
export * from './ui/toast/index.js';
|
|
31
|
+
export * from './ui/tooltip/index.js';
|
|
31
32
|
export * from './layout/Chat/index.js';
|
|
33
|
+
export * from './layout/mailing/index.js';
|
|
32
34
|
export * from './forms/input/index.js';
|
|
33
35
|
export * from './forms/label/index.js';
|
|
34
36
|
export * from './forms/datepicker/index.js';
|
|
@@ -9,6 +9,10 @@ export declare function createAuthStore(): {
|
|
|
9
9
|
userIsFound: boolean;
|
|
10
10
|
};
|
|
11
11
|
export type AuthStoreType = ReturnType<typeof createAuthStore>;
|
|
12
|
+
export interface AuthenticatedData {
|
|
13
|
+
keycloakUser: AuthUserInfo;
|
|
14
|
+
queryUser: AuthUserInfo | any;
|
|
15
|
+
}
|
|
12
16
|
export declare class KeycloakService {
|
|
13
17
|
private keycloak;
|
|
14
18
|
private initialized;
|
|
@@ -18,7 +22,7 @@ export declare class KeycloakService {
|
|
|
18
22
|
private onLogout?;
|
|
19
23
|
private onError?;
|
|
20
24
|
constructor(store: AuthStoreType, fetchUserInfo: FetchAuthUserInfoFn, callbacks?: {
|
|
21
|
-
onAuthenticated?: (
|
|
25
|
+
onAuthenticated?: (val: AuthenticatedData) => void;
|
|
22
26
|
onLogout?: () => void;
|
|
23
27
|
onError?: (error: string) => void;
|
|
24
28
|
});
|
|
@@ -97,7 +97,7 @@ export class KeycloakService {
|
|
|
97
97
|
status: extras?.status || ''
|
|
98
98
|
};
|
|
99
99
|
this.store.userInfo = userInfo;
|
|
100
|
-
this.onAuthenticated?.(userInfo);
|
|
100
|
+
this.onAuthenticated?.({ keycloakUser: userInfo, queryUser: meRet.data });
|
|
101
101
|
}
|
|
102
102
|
catch (error) {
|
|
103
103
|
const errorMessage = error instanceof Error ? error.message : 'Failed to set token details';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconifyIcon from '../../ui/icons/IconifyIcon.svelte';
|
|
3
|
+
import type { MailPaginatorProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
hasNextPage = false,
|
|
7
|
+
hasPreviousPage = false,
|
|
8
|
+
currentPage = 0,
|
|
9
|
+
pageSize = 0,
|
|
10
|
+
totalCount = 0,
|
|
11
|
+
onNextClick,
|
|
12
|
+
onPreviousClick
|
|
13
|
+
}: MailPaginatorProps = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="flex items-center space-x-4 px-2">
|
|
17
|
+
<span class="text-sm text-gray-500">{currentPage}-{pageSize} of {totalCount}</span>
|
|
18
|
+
<div class="flex items-center space-x-2">
|
|
19
|
+
<button
|
|
20
|
+
disabled={!hasPreviousPage}
|
|
21
|
+
onclick={onPreviousClick}
|
|
22
|
+
class="rounded-lg bg-gray-200 p-1.5 text-gray-700 hover:bg-gray-300 disabled:bg-gray-200 disabled:text-gray-400"
|
|
23
|
+
title="Older"
|
|
24
|
+
>
|
|
25
|
+
<IconifyIcon icon="material-symbols:arrow-back" class="flex h-5 w-5 justify-center" />
|
|
26
|
+
</button>
|
|
27
|
+
<button
|
|
28
|
+
disabled={!hasNextPage}
|
|
29
|
+
onclick={onNextClick}
|
|
30
|
+
class="rounded-lg bg-gray-200 p-1.5 text-gray-700 transition duration-150 hover:bg-gray-300 disabled:bg-gray-200 disabled:text-gray-400"
|
|
31
|
+
title="Newer"
|
|
32
|
+
>
|
|
33
|
+
<IconifyIcon icon="material-symbols:arrow-forward" class="flex h-5 w-5 justify-center" />
|
|
34
|
+
</button>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconifyIcon from '../../ui/icons/IconifyIcon.svelte';
|
|
3
|
+
import { Tooltip } from '../../ui/tooltip/index.js';
|
|
4
|
+
import type { MailSidebar } from './types.js';
|
|
5
|
+
|
|
6
|
+
let { setActiveMenu, menus = [], onClick }: MailSidebar = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<div class="h-full w-full">
|
|
10
|
+
<ul class="flex h-full w-full flex-col gap-2 pt-4 pb-8">
|
|
11
|
+
{#each menus as menu, i}
|
|
12
|
+
{@const active = setActiveMenu?.(menu)}
|
|
13
|
+
<li class="grid w-full place-content-center">
|
|
14
|
+
<a
|
|
15
|
+
onclick={() => onClick?.(menu)}
|
|
16
|
+
href={menu.path}
|
|
17
|
+
class:text-primary-500={active}
|
|
18
|
+
class:bg-primary-100={active}
|
|
19
|
+
class:bg-opacity-10={active}
|
|
20
|
+
class:hover:bg-primary-100={!active}
|
|
21
|
+
class:hover:bg-opacity-10={!active}
|
|
22
|
+
class:text-gray-500={!active}
|
|
23
|
+
class:hover:text-gray-700={!active}
|
|
24
|
+
class="relative grid cursor-pointer place-content-center rounded px-3 py-3 transition-colors"
|
|
25
|
+
>
|
|
26
|
+
<IconifyIcon icon={menu.icon} style="font-size: 18px;" />
|
|
27
|
+
<div class="absolute -top-1 right-0">
|
|
28
|
+
<span
|
|
29
|
+
class:hidden={!Boolean(menu.count > 0)}
|
|
30
|
+
class="rounded-lg bg-sky-500 px-1.5 py-0.5 text-xs font-bold text-gray-100"
|
|
31
|
+
>{menu.count}</span
|
|
32
|
+
>
|
|
33
|
+
</div>
|
|
34
|
+
</a>
|
|
35
|
+
<Tooltip placement="right">{menu.title}</Tooltip>
|
|
36
|
+
</li>
|
|
37
|
+
{/each}
|
|
38
|
+
</ul>
|
|
39
|
+
</div>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import IconifyIcon from '../../ui/icons/IconifyIcon.svelte';
|
|
3
|
+
import { scale, slide } from 'svelte/transition';
|
|
4
|
+
import type { MailToolBarProps } from './index.js';
|
|
5
|
+
import { Input } from '../../forms/input/index.js';
|
|
6
|
+
import MailPaginator from './MailPaginator.svelte';
|
|
7
|
+
import { Tooltip } from '../../ui/tooltip/index.js';
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
onBackClick,
|
|
11
|
+
onRefreshClick,
|
|
12
|
+
onComposeClick,
|
|
13
|
+
selectedMails = [],
|
|
14
|
+
showComposeButton = true,
|
|
15
|
+
showBackButton = true,
|
|
16
|
+
pageInfo = {
|
|
17
|
+
currentPage: 0,
|
|
18
|
+
pageSize: 0,
|
|
19
|
+
totalCount: 0,
|
|
20
|
+
hasNextPage: false,
|
|
21
|
+
hasPreviousPage: false
|
|
22
|
+
},
|
|
23
|
+
showPagination = true,
|
|
24
|
+
showSearch = true,
|
|
25
|
+
customFilterComponent,
|
|
26
|
+
onsearchChange,
|
|
27
|
+
onNextPageClick,
|
|
28
|
+
onPrevPageClick,
|
|
29
|
+
showArchiveButton = true,
|
|
30
|
+
onArchiveClick,
|
|
31
|
+
showDeleteButton = true,
|
|
32
|
+
onDeleteClick,
|
|
33
|
+
showMarkReadButton = true,
|
|
34
|
+
onToggleMarkReadClick,
|
|
35
|
+
isReadActive = false,
|
|
36
|
+
showFavoriteButton = true,
|
|
37
|
+
onToggleFavoriteClick,
|
|
38
|
+
showMarkAsSpamButton = true,
|
|
39
|
+
onMarkAsSpamClick,
|
|
40
|
+
isFavoriteActive = true
|
|
41
|
+
}: MailToolBarProps = $props();
|
|
42
|
+
|
|
43
|
+
let openFilter = $state(false);
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<div class="flex h-full w-full items-center justify-between">
|
|
47
|
+
<div class="flex items-center">
|
|
48
|
+
<div class="flex items-center">
|
|
49
|
+
<div class:hidden={!showBackButton} class="ml-3 flex items-center">
|
|
50
|
+
<button
|
|
51
|
+
onclick={onBackClick}
|
|
52
|
+
class="grid h-8 w-8 place-content-center rounded-full border border-gray-300 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
53
|
+
>
|
|
54
|
+
<IconifyIcon icon="ic:round-arrow-back-ios-new" class="flex h-5 w-5 justify-center" />
|
|
55
|
+
</button>
|
|
56
|
+
<Tooltip placement="bottom">Back</Tooltip>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="ml-3 flex items-center">
|
|
59
|
+
<button
|
|
60
|
+
onclick={onRefreshClick}
|
|
61
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
62
|
+
>
|
|
63
|
+
<IconifyIcon icon="mdi:refresh" class="flex h-5 w-5 justify-center" />
|
|
64
|
+
</button>
|
|
65
|
+
<Tooltip placement="bottom">Refresh</Tooltip>
|
|
66
|
+
</div>
|
|
67
|
+
<span class:hidden={selectedMails.length === 0} in:scale class="mx-3 h-6 w-[.5px] bg-gray-300"
|
|
68
|
+
></span>
|
|
69
|
+
<div class="flex items-center space-x-2" class:hidden={selectedMails.length === 0} in:scale>
|
|
70
|
+
<button
|
|
71
|
+
onclick={() => onArchiveClick?.()}
|
|
72
|
+
class:hidden={!showArchiveButton}
|
|
73
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
74
|
+
>
|
|
75
|
+
<IconifyIcon icon="mdi:archive-arrow-down-outline" class="flex h-5 w-5 justify-center" />
|
|
76
|
+
</button>
|
|
77
|
+
<Tooltip placement="bottom">Archive</Tooltip>
|
|
78
|
+
|
|
79
|
+
<button
|
|
80
|
+
class:hidden={!showMarkAsSpamButton}
|
|
81
|
+
onclick={() => onMarkAsSpamClick?.()}
|
|
82
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
83
|
+
>
|
|
84
|
+
<IconifyIcon icon="solar:danger-triangle-outline" class="flex h-5 w-5 justify-center" />
|
|
85
|
+
</button>
|
|
86
|
+
<Tooltip placement="bottom">Mark As Spam</Tooltip>
|
|
87
|
+
|
|
88
|
+
<button
|
|
89
|
+
class:hidden={!showDeleteButton}
|
|
90
|
+
onclick={() => onDeleteClick?.()}
|
|
91
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
92
|
+
>
|
|
93
|
+
<IconifyIcon icon="mdi:delete-outline" class="flex h-5 w-5 justify-center" />
|
|
94
|
+
</button>
|
|
95
|
+
<Tooltip placement="bottom">Delete</Tooltip>
|
|
96
|
+
</div>
|
|
97
|
+
<span class:hidden={selectedMails.length === 0} in:scale class="mx-3 h-6 w-[.5px] bg-gray-300"
|
|
98
|
+
></span>
|
|
99
|
+
<div class:hidden={selectedMails.length === 0} in:scale class="flex items-center space-x-2">
|
|
100
|
+
<button
|
|
101
|
+
class:hidden={!showMarkReadButton}
|
|
102
|
+
onclick={() => onToggleMarkReadClick?.(isReadActive ? 'unread' : 'read')}
|
|
103
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
104
|
+
>
|
|
105
|
+
<IconifyIcon
|
|
106
|
+
icon={isReadActive ? 'mdi:email-outline' : 'mdi:email-open-outline'}
|
|
107
|
+
class="flex h-5 w-5 justify-center"
|
|
108
|
+
/>
|
|
109
|
+
</button>
|
|
110
|
+
<Tooltip placement="bottom">{isReadActive ? 'Mark As Unread' : 'Mark As Read'}</Tooltip>
|
|
111
|
+
|
|
112
|
+
<button
|
|
113
|
+
class:hidden={!showFavoriteButton}
|
|
114
|
+
onclick={() => onToggleFavoriteClick?.(isFavoriteActive ? 'unfavorite' : 'favorite')}
|
|
115
|
+
class="rounded-lg border border-gray-300 px-2 py-1 text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
116
|
+
>
|
|
117
|
+
<IconifyIcon
|
|
118
|
+
icon={isFavoriteActive ? 'mdi:star' : 'mdi:star-outline'}
|
|
119
|
+
class="flex h-5 w-5 justify-center"
|
|
120
|
+
/>
|
|
121
|
+
</button>
|
|
122
|
+
<Tooltip placement="bottom">{isFavoriteActive ? 'Unfavorite' : 'Favorite'}</Tooltip>
|
|
123
|
+
</div>
|
|
124
|
+
<span class:hidden={!showSearch} class="mx-3 h-6 w-[.5px] bg-gray-300"></span>
|
|
125
|
+
<div
|
|
126
|
+
class:hidden={!showSearch}
|
|
127
|
+
class="flex items-center justify-center rounded-lg border border-gray-300 px-2 py-1 text-sm text-gray-700 shadow transition duration-100"
|
|
128
|
+
>
|
|
129
|
+
<IconifyIcon icon="iconamoon:search-thin" style="font-size: 16px;" />
|
|
130
|
+
<Input
|
|
131
|
+
type="search"
|
|
132
|
+
class="h-5 w-44 border-none text-xs outline-none placeholder:text-xs focus:ring-0"
|
|
133
|
+
placeholder="Search..."
|
|
134
|
+
oninput={(e) => onsearchChange?.((e.target as HTMLInputElement).value)}
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
<div class:hidden={!customFilterComponent} class="relative pl-2">
|
|
138
|
+
<button
|
|
139
|
+
onclick={() => (openFilter = !openFilter)}
|
|
140
|
+
class="flex items-center justify-center gap-2 rounded-lg border border-gray-300 px-2 py-1 text-sm text-gray-700 shadow transition duration-100 hover:bg-gray-200"
|
|
141
|
+
>
|
|
142
|
+
<IconifyIcon icon="mage:filter" />
|
|
143
|
+
<span>Filters</span>
|
|
144
|
+
</button>
|
|
145
|
+
{#if openFilter}
|
|
146
|
+
<div transition:slide class="absolute z-20 mt-2 w-80 rounded-md bg-white shadow">
|
|
147
|
+
{@render customFilterComponent?.()}
|
|
148
|
+
</div>
|
|
149
|
+
{/if}
|
|
150
|
+
</div>
|
|
151
|
+
<span class:hidden={!showComposeButton} class="mx-3 h-6 w-[.5px] bg-gray-300"></span>
|
|
152
|
+
<div class:hidden={!showComposeButton} class="flex h-8 items-center">
|
|
153
|
+
<button
|
|
154
|
+
onclick={() => onComposeClick?.()}
|
|
155
|
+
class="flex items-center justify-center space-x-2 rounded bg-blue-600 px-6 py-1.5 text-gray-100 transition duration-150 hover:bg-blue-700"
|
|
156
|
+
>
|
|
157
|
+
<IconifyIcon icon="ic:round-add" style="font-size: 16px;" />
|
|
158
|
+
<span class="text-sm">Compose</span>
|
|
159
|
+
</button>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
<div class:hidden={!showPagination}>
|
|
164
|
+
<MailPaginator
|
|
165
|
+
currentPage={pageInfo.currentPage}
|
|
166
|
+
totalCount={pageInfo.totalCount}
|
|
167
|
+
pageSize={pageInfo.pageSize}
|
|
168
|
+
hasNextPage={pageInfo.hasNextPage}
|
|
169
|
+
hasPreviousPage={pageInfo.hasPreviousPage}
|
|
170
|
+
onNextClick={() => onNextPageClick?.()}
|
|
171
|
+
onPreviousClick={() => onPrevPageClick?.()}
|
|
172
|
+
/>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Checkbox } from '../../forms/checkbox/index.js';
|
|
3
|
+
import IconifyIcon from '../../ui/icons/IconifyIcon.svelte';
|
|
4
|
+
import dayjs from 'dayjs';
|
|
5
|
+
import { type MailingMessageCardProps } from './index.js';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
id = 0,
|
|
9
|
+
sender = '',
|
|
10
|
+
subject = '',
|
|
11
|
+
date,
|
|
12
|
+
message = '',
|
|
13
|
+
isStared = false,
|
|
14
|
+
isImportant = false,
|
|
15
|
+
isRead = false,
|
|
16
|
+
isChecked = false,
|
|
17
|
+
onItemChecked,
|
|
18
|
+
toggelImportant,
|
|
19
|
+
toggleFavorited,
|
|
20
|
+
onItemSelected
|
|
21
|
+
}: MailingMessageCardProps = $props();
|
|
22
|
+
|
|
23
|
+
function handleClik(e: any) {
|
|
24
|
+
if (e.target.tagName !== 'INPUT' && e.target.localName !== 'iconify-icon') onItemSelected?.(id);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function formatDate(date: Date | string): string {
|
|
28
|
+
const messageDate = dayjs(date);
|
|
29
|
+
const today = dayjs();
|
|
30
|
+
|
|
31
|
+
if (messageDate.isSame(today, 'day')) {
|
|
32
|
+
return messageDate.format('HH:mm');
|
|
33
|
+
} else if (messageDate.isSame(today.subtract(1, 'day'), 'day')) {
|
|
34
|
+
return 'Yesterday';
|
|
35
|
+
} else if (messageDate.isSame(today, 'year')) {
|
|
36
|
+
return messageDate.format('MMM DD');
|
|
37
|
+
} else {
|
|
38
|
+
return messageDate.format('DD/MM/YYYY');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<div
|
|
44
|
+
class:bg-blue-100={isChecked}
|
|
45
|
+
class:hover:bg-gray-200={!isChecked}
|
|
46
|
+
class:bg-white={!isRead && !isChecked}
|
|
47
|
+
class:shadow={!isRead && !isChecked}
|
|
48
|
+
class:border={!isRead && !isChecked}
|
|
49
|
+
class="flex items-center border-y px-2"
|
|
50
|
+
role="button"
|
|
51
|
+
tabindex="0"
|
|
52
|
+
onkeydown={handleClik}
|
|
53
|
+
onclick={handleClik}
|
|
54
|
+
>
|
|
55
|
+
<Checkbox
|
|
56
|
+
checked={isChecked}
|
|
57
|
+
class="cursor-pointer border-2 border-gray-400 transition-colors hover:ring-4 hover:ring-gray-400 focus:ring-0"
|
|
58
|
+
onchange={(e) => {
|
|
59
|
+
const target = e.target;
|
|
60
|
+
onItemChecked?.({ checked: target.checked, id });
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
<div class="my-1 flex w-full cursor-pointer items-center justify-between p-1">
|
|
64
|
+
<div class="flex items-center">
|
|
65
|
+
<div class="mr-4 flex items-center gap-1 space-x-1">
|
|
66
|
+
<button
|
|
67
|
+
onclick={(e) => {
|
|
68
|
+
toggleFavorited?.(id);
|
|
69
|
+
}}
|
|
70
|
+
aria-label="Not starred"
|
|
71
|
+
>
|
|
72
|
+
<IconifyIcon
|
|
73
|
+
style="font-size: 24px"
|
|
74
|
+
icon={isStared ? 'mdi:star' : 'mdi:star-outline'}
|
|
75
|
+
class="flex justify-center transition-colors {isStared
|
|
76
|
+
? 'text-yellow-500 hover:text-yellow-600'
|
|
77
|
+
: 'text-gray-500 hover:text-gray-900'}"
|
|
78
|
+
/>
|
|
79
|
+
</button>
|
|
80
|
+
<button
|
|
81
|
+
onclick={(e) => {
|
|
82
|
+
toggelImportant?.(id);
|
|
83
|
+
}}
|
|
84
|
+
aria-label="Click to mark this email as important"
|
|
85
|
+
>
|
|
86
|
+
<IconifyIcon
|
|
87
|
+
style="font-size: 18px"
|
|
88
|
+
icon={isImportant ? 'ic:outline-bookmark' : 'solar:bookmark-broken'}
|
|
89
|
+
class="flex justify-center transition-colors {isImportant
|
|
90
|
+
? 'text-yellow-500 hover:text-yellow-600'
|
|
91
|
+
: 'text-gray-500 hover:text-gray-900'}"
|
|
92
|
+
/>
|
|
93
|
+
</button>
|
|
94
|
+
</div>
|
|
95
|
+
<span class="w-56 truncate pr-2" class:font-bold={!isRead}>{sender}</span>
|
|
96
|
+
<span class="w-64 truncate" class:font-bold={!isRead}>{subject}</span>
|
|
97
|
+
<span class="mx-1">-</span>
|
|
98
|
+
<span class="w-96 truncate text-sm text-gray-600">{message}</span>
|
|
99
|
+
</div>
|
|
100
|
+
<div class="flex w-32 items-center justify-end">
|
|
101
|
+
<span class="text-sm" class:font-bold={!isRead} class:text-gray-500={isRead}>
|
|
102
|
+
{formatDate(date)}
|
|
103
|
+
</span>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { PageLoader } from '../../ui/pageLoader/index.js';
|
|
3
|
+
import { slide } from 'svelte/transition';
|
|
4
|
+
import type { MailingHeaderData, MailingMessageViewerProps, MailingReplyType } from './index.js';
|
|
5
|
+
import MailingHeader from './MailingHeader.svelte';
|
|
6
|
+
import { onMount } from 'svelte';
|
|
7
|
+
import toast from 'svelte-french-toast';
|
|
8
|
+
|
|
9
|
+
let { readMessage, recordId, updatePageInfo }: MailingMessageViewerProps = $props();
|
|
10
|
+
|
|
11
|
+
let busy = $state(true);
|
|
12
|
+
let header = $state<MailingHeaderData>({} as MailingHeaderData);
|
|
13
|
+
let inputType = $state<MailingReplyType | undefined>(undefined);
|
|
14
|
+
|
|
15
|
+
onMount(async () => {
|
|
16
|
+
try {
|
|
17
|
+
const ret = await readMessage(recordId);
|
|
18
|
+
if (!ret?.success) {
|
|
19
|
+
toast.error(ret?.message);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
updatePageInfo?.({
|
|
23
|
+
currentPage: 1,
|
|
24
|
+
pageSize: 1,
|
|
25
|
+
totalCount: 1,
|
|
26
|
+
hasNextPage: false,
|
|
27
|
+
hasPreviousPage: false
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log({ ret });
|
|
31
|
+
} catch (error: any) {
|
|
32
|
+
toast.error(error?.message || error);
|
|
33
|
+
} finally {
|
|
34
|
+
busy = false;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<div class="h-full w-full">
|
|
40
|
+
{#if busy}
|
|
41
|
+
<PageLoader size={50} />
|
|
42
|
+
{:else}
|
|
43
|
+
<div class="flex h-full w-full flex-col gap-2" in:slide>
|
|
44
|
+
<div class="h-28 px-4 pt-4">
|
|
45
|
+
<MailingHeader bind:replyType={inputType} data={header} />
|
|
46
|
+
</div>
|
|
47
|
+
<!-- <div class="fex-grow h-full w-full rounded bg-gray-100">
|
|
48
|
+
<div class="flex h-[71vh] w-full flex-col gap-4">
|
|
49
|
+
<div
|
|
50
|
+
class="scrollbar-thumb-blue scrollbar-thumb-rounded scrollbar-track-blue-lighter scrollbar-w-2 scrolling-touch h-full flex-grow overflow-y-auto p-2"
|
|
51
|
+
>
|
|
52
|
+
<ContentSection {content} />
|
|
53
|
+
</div>
|
|
54
|
+
<div class="h-modal p-4 pt-2" class:hidden={!Boolean(inputType)}>
|
|
55
|
+
<div class=" rounded-md bg-white p-4">
|
|
56
|
+
<Reply {inputType} />
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div> -->
|
|
61
|
+
</div>
|
|
62
|
+
{/if}
|
|
63
|
+
</div>
|