design-system-next 2.8.3 → 2.9.1
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/design-system-next.js +8916 -8687
- package/dist/design-system-next.js.gz +0 -0
- package/dist/main.css +1 -1
- package/dist/main.css.gz +0 -0
- package/dist/package.json.d.ts +1 -1
- package/package.json +1 -1
- package/src/components/banner/banner.ts +20 -0
- package/src/components/banner/banner.vue +28 -0
- package/src/components/banner/use-banner.ts +96 -0
- package/src/components/calendar/calendar.ts +4 -31
- package/src/components/calendar/calendar.vue +186 -223
- package/src/components/calendar/use-calendar.ts +72 -38
- package/src/components/calendar-cell/use-calendar-cell.ts +0 -1
- package/src/components/list/use-list.ts +10 -6
- package/src/components/select/select-ladderized/use-select-ladderized.ts +164 -164
- package/src/components/select/use-select.ts +7 -3
- package/src/components/stepper/step/step.ts +8 -0
- package/src/components/stepper/step/step.vue +3 -1
- package/src/components/stepper/step/use-step.ts +22 -10
- package/src/components/stepper/stepper.ts +9 -0
- package/src/components/stepper/stepper.vue +1 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { computed, type Ref } from "vue";
|
|
2
|
+
import type { BannerPropTypes } from "./banner";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
|
|
5
|
+
interface BannerClasses {
|
|
6
|
+
base: string;
|
|
7
|
+
content: string;
|
|
8
|
+
icon: string;
|
|
9
|
+
message: string;
|
|
10
|
+
close: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useBanner = (props: BannerPropTypes, showModel: Ref<boolean>) => {
|
|
14
|
+
const closeBanner = () => showModel.value = false;
|
|
15
|
+
|
|
16
|
+
const bannerClasses = computed<BannerClasses>(() => {
|
|
17
|
+
const base = classNames(
|
|
18
|
+
'spr-w-full spr-flex spr-flex-row spr-items-top spr-p-size-spacing-3xs spr-rounded-border-radius-md',
|
|
19
|
+
{
|
|
20
|
+
'spr-background-color-success-weak': props.type === 'success',
|
|
21
|
+
'spr-background-color-danger-weak': props.type === 'error',
|
|
22
|
+
'spr-background-color-information-weak': props.type === 'info',
|
|
23
|
+
'spr-background-color-pending-weak': props.type === 'pending',
|
|
24
|
+
'spr-background-color-caution-weak': props.type === 'caution',
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const content = classNames(
|
|
29
|
+
'spr-flex-auto'
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const icon = classNames(
|
|
33
|
+
'spr-mt-[2px]',
|
|
34
|
+
{
|
|
35
|
+
'spr-text-color-brand-base': props.type === 'success',
|
|
36
|
+
'spr-text-color-danger-base': props.type === 'error',
|
|
37
|
+
'spr-text-color-information-base': props.type === 'info',
|
|
38
|
+
'spr-text-color-pending-base': props.type === 'pending',
|
|
39
|
+
'spr-text-color-caution-base': props.type === 'caution',
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const message = classNames(
|
|
44
|
+
'spr-body-sm-regular',
|
|
45
|
+
{
|
|
46
|
+
'spr-text-color-brand-base': props.type === 'success',
|
|
47
|
+
'spr-text-color-danger-pressed': props.type === 'error',
|
|
48
|
+
'spr-text-color-information-pressed': props.type === 'info',
|
|
49
|
+
'spr-text-color-pending-pressed': props.type === 'pending',
|
|
50
|
+
'spr-text-color-caution-pressed': props.type === 'caution',
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const close = classNames(
|
|
55
|
+
'spr-flex-none spr-cursor-pointer',
|
|
56
|
+
{
|
|
57
|
+
'spr-text-color-brand-base': props.type === 'success',
|
|
58
|
+
'spr-text-color-danger-base': props.type === 'error',
|
|
59
|
+
'spr-text-color-information-base': props.type === 'info',
|
|
60
|
+
'spr-text-color-pending-base': props.type === 'pending',
|
|
61
|
+
'spr-text-color-caution-base': props.type === 'caution',
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
base,
|
|
67
|
+
content,
|
|
68
|
+
icon,
|
|
69
|
+
message,
|
|
70
|
+
close,
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const bannerIcon = computed(() => {
|
|
75
|
+
switch (props.type) {
|
|
76
|
+
case 'success':
|
|
77
|
+
return 'ph:check-circle-fill';
|
|
78
|
+
case 'error':
|
|
79
|
+
return 'ph:warning-circle-fill';
|
|
80
|
+
case 'info':
|
|
81
|
+
return 'ph:info-fill';
|
|
82
|
+
case 'pending':
|
|
83
|
+
return 'ph:info-fill';
|
|
84
|
+
case 'caution':
|
|
85
|
+
return 'ph:warning-fill';
|
|
86
|
+
default:
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
closeBanner,
|
|
93
|
+
bannerClasses,
|
|
94
|
+
bannerIcon,
|
|
95
|
+
};
|
|
96
|
+
};
|
|
@@ -22,12 +22,6 @@ interface Employee {
|
|
|
22
22
|
hoursTarget?: number;
|
|
23
23
|
schedule: EmployeeSchedule[];
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
interface FilterOption {
|
|
27
|
-
text: string;
|
|
28
|
-
value: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
25
|
export interface SelectedShift {
|
|
32
26
|
employeeId: string;
|
|
33
27
|
date: string;
|
|
@@ -43,18 +37,6 @@ export const calendarPropTypes = {
|
|
|
43
37
|
type: Date,
|
|
44
38
|
default: () => new Date(),
|
|
45
39
|
},
|
|
46
|
-
companyOptions: {
|
|
47
|
-
type: Array as PropType<FilterOption[]>,
|
|
48
|
-
default: () => [{ text: 'All Companies', value: 'all' }],
|
|
49
|
-
},
|
|
50
|
-
departmentOptions: {
|
|
51
|
-
type: Array as PropType<FilterOption[]>,
|
|
52
|
-
default: () => [{ text: 'All Departments', value: 'all' }],
|
|
53
|
-
},
|
|
54
|
-
branchOptions: {
|
|
55
|
-
type: Array as PropType<FilterOption[]>,
|
|
56
|
-
default: () => [{ text: 'All Branches', value: 'all' }],
|
|
57
|
-
},
|
|
58
40
|
|
|
59
41
|
search: {
|
|
60
42
|
type: String,
|
|
@@ -69,19 +51,6 @@ export const calendarPropTypes = {
|
|
|
69
51
|
shift: null,
|
|
70
52
|
}),
|
|
71
53
|
},
|
|
72
|
-
|
|
73
|
-
selectedCompany: {
|
|
74
|
-
type: String,
|
|
75
|
-
default: '',
|
|
76
|
-
},
|
|
77
|
-
selectedDepartment: {
|
|
78
|
-
type: String,
|
|
79
|
-
default: '',
|
|
80
|
-
},
|
|
81
|
-
selectedBranch: {
|
|
82
|
-
type: String,
|
|
83
|
-
default: '',
|
|
84
|
-
},
|
|
85
54
|
loading: {
|
|
86
55
|
type: Boolean,
|
|
87
56
|
default: false,
|
|
@@ -98,6 +67,10 @@ export const calendarPropTypes = {
|
|
|
98
67
|
type: String,
|
|
99
68
|
default: 'Add Employee',
|
|
100
69
|
},
|
|
70
|
+
hideAddButton: {
|
|
71
|
+
type: Boolean,
|
|
72
|
+
default: false,
|
|
73
|
+
},
|
|
101
74
|
};
|
|
102
75
|
|
|
103
76
|
export const calendarEmitTypes = {};
|
|
@@ -1,231 +1,200 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<SprCard :has-content-padding="false">
|
|
3
|
-
<template #header>
|
|
4
|
-
<div :class="[getCalendarClasses.borderClasses, getCalendarClasses.headerWrapper]">
|
|
5
|
-
<div class="spr-flex spr-items-center spr-gap-size-spacing-3xs">
|
|
6
|
-
<div class="spr-flex">
|
|
7
|
-
<spr-button variant="tertiary" has-icon @click="prevWeek">
|
|
8
|
-
<Icon icon="ph:caret-left-fill" class="spr-text-color-success-base" />
|
|
9
|
-
</spr-button>
|
|
10
|
-
<spr-button variant="tertiary" has-icon @click="nextWeek">
|
|
11
|
-
<Icon icon="ph:caret-right-fill" class="spr-text-color-success-base" />
|
|
12
|
-
</spr-button>
|
|
13
|
-
</div>
|
|
14
|
-
<h2 class="spr-heading-xs">{{ weekRangeDisplay }}</h2>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<spr-button variant="secondary" size="small" @click="goToToday"> Today </spr-button>
|
|
18
|
-
</div>
|
|
19
|
-
</template>
|
|
20
|
-
|
|
2
|
+
<SprCard :has-content-padding="false" class="spr-flex spr-h-full spr-flex-col spr-overflow-hidden">
|
|
21
3
|
<template #content>
|
|
22
4
|
<div :class="getCalendarClasses.contentWrapper">
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
v-model="companyDropDown"
|
|
35
|
-
:menu-list="companyOptions"
|
|
36
|
-
@update:model-value="(e) => handleFilter('company', e[0])"
|
|
37
|
-
>
|
|
38
|
-
<!-- @update:model-value="(e) => (selectedCompany = e[0])" -->
|
|
39
|
-
<spr-input v-model="selectedCompany" placeholder="Company">
|
|
40
|
-
<template #icon>
|
|
41
|
-
<Icon icon="ph:caret-down" />
|
|
42
|
-
</template>
|
|
43
|
-
</spr-input>
|
|
44
|
-
</spr-dropdown>
|
|
45
|
-
|
|
46
|
-
<spr-dropdown
|
|
47
|
-
id="department-dropdown"
|
|
48
|
-
v-model="departmentDropDown"
|
|
49
|
-
:menu-list="departmentOptions"
|
|
50
|
-
@update:model-value="(e) => handleFilter('department', e[0])"
|
|
51
|
-
>
|
|
52
|
-
<spr-input v-model="selectedDepartment" placeholder="Department">
|
|
53
|
-
<template #icon>
|
|
54
|
-
<Icon icon="ph:caret-down" />
|
|
55
|
-
</template>
|
|
56
|
-
</spr-input>
|
|
57
|
-
</spr-dropdown>
|
|
58
|
-
|
|
59
|
-
<spr-dropdown
|
|
60
|
-
id="branch-dropdown"
|
|
61
|
-
v-model="branchDropDown"
|
|
62
|
-
:menu-list="branchOptions"
|
|
63
|
-
@update:model-value="(e) => handleFilter('branch', e[0])"
|
|
64
|
-
>
|
|
65
|
-
<spr-input v-model="selectedBranch" placeholder="Branch">
|
|
66
|
-
<template #icon>
|
|
67
|
-
<Icon icon="ph:caret-down" />
|
|
68
|
-
</template>
|
|
69
|
-
</spr-input>
|
|
70
|
-
</spr-dropdown>
|
|
5
|
+
<div :class="[getCalendarClasses.headerWrapper]">
|
|
6
|
+
<div class="spr-flex spr-items-center spr-justify-center spr-gap-size-spacing-3xs">
|
|
7
|
+
<div class="spr-flex">
|
|
8
|
+
<spr-button variant="tertiary" has-icon @click="prevWeek">
|
|
9
|
+
<Icon icon="ph:caret-left-fill" class="spr-text-color-success-base" />
|
|
10
|
+
</spr-button>
|
|
11
|
+
<spr-button variant="tertiary" has-icon @click="nextWeek">
|
|
12
|
+
<Icon icon="ph:caret-right-fill" class="spr-text-color-success-base" />
|
|
13
|
+
</spr-button>
|
|
14
|
+
</div>
|
|
15
|
+
<div class="spr-heading-xs">{{ weekRangeDisplay }}</div>
|
|
71
16
|
</div>
|
|
72
|
-
</slot>
|
|
73
17
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
:class="[getCalendarClasses.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
]"
|
|
95
|
-
>
|
|
96
|
-
{{ formatDate(date, 'DD') }}
|
|
18
|
+
<spr-button variant="secondary" size="large" @click="goToToday"> Today </spr-button>
|
|
19
|
+
</div>
|
|
20
|
+
<!-- Filters -->
|
|
21
|
+
<slot name="filter" />
|
|
22
|
+
|
|
23
|
+
<div ref="tableBodyRef" class="spr-table-wrapper spr-h-[calc(100vh-12rem)] spr-w-full spr-overflow-auto">
|
|
24
|
+
<div class="spr-pb-size-spacing-lg">
|
|
25
|
+
<table aria-describedby="calendar" :class="[getCalendarClasses.calendarTable, 'spr-relative']">
|
|
26
|
+
<!-- Calendar Header -->
|
|
27
|
+
<thead class="spr-bg-white spr-sticky spr-top-0 spr-z-20">
|
|
28
|
+
<tr>
|
|
29
|
+
<th :class="[getCalendarClasses.tableHeaderEmployeeName, 'spr-sticky spr-left-0']">
|
|
30
|
+
<div :class="getCalendarClasses.headerContent">
|
|
31
|
+
<div>Employee Name</div>
|
|
32
|
+
<div
|
|
33
|
+
:class="['spr-flex spr-cursor-pointer spr-flex-row spr-items-center spr-p-size-spacing-6xs']"
|
|
34
|
+
@click="handleSorting"
|
|
35
|
+
>
|
|
36
|
+
<Icon :icon="getSortIcon" height="16" width="16" :class="[{ 'spr-text-kangkong-700': sort }]" />
|
|
37
|
+
</div>
|
|
97
38
|
</div>
|
|
98
|
-
|
|
99
|
-
|
|
39
|
+
</th>
|
|
40
|
+
<th
|
|
41
|
+
v-for="(date, index) in weekDates"
|
|
42
|
+
:key="index"
|
|
43
|
+
:class="[getCalendarClasses.borderClasses, getCalendarClasses.tableHeader]"
|
|
44
|
+
>
|
|
45
|
+
<div :class="getCalendarClasses.headerContent">
|
|
46
|
+
<div
|
|
47
|
+
:class="[
|
|
48
|
+
getCalendarClasses.headerDate,
|
|
49
|
+
{
|
|
50
|
+
'spr-background-color-brand-base spr-text-color-inverted-strong': isToday(date),
|
|
51
|
+
},
|
|
52
|
+
]"
|
|
53
|
+
>
|
|
54
|
+
{{ formatDate(date, 'DD') }}
|
|
55
|
+
</div>
|
|
56
|
+
<div class="spr-body-sm-regular">
|
|
57
|
+
{{ formatDate(date, 'ddd').toUpperCase() }}
|
|
58
|
+
</div>
|
|
100
59
|
</div>
|
|
101
|
-
</
|
|
102
|
-
</
|
|
103
|
-
</
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
60
|
+
</th>
|
|
61
|
+
</tr>
|
|
62
|
+
</thead>
|
|
63
|
+
<tbody v-if="employees.length > 0 && !loading" class="spr-overflow-y-auto">
|
|
64
|
+
<tr v-for="employee in employees" :key="employee.id">
|
|
65
|
+
<td
|
|
66
|
+
:class="[
|
|
67
|
+
getCalendarClasses.borderClasses,
|
|
68
|
+
'spr-bg-white spr-sticky spr-left-0 spr-z-10 spr-content-start spr-border-y spr-border-b-0 spr-border-l-0 spr-border-r spr-p-size-spacing-xs',
|
|
69
|
+
]"
|
|
70
|
+
>
|
|
71
|
+
<div class="spr-flex spr-flex-col spr-gap-size-spacing-3xs spr-overflow-hidden">
|
|
72
|
+
<spr-avatar
|
|
73
|
+
:src="employee.avatar"
|
|
74
|
+
:initial="employee.name"
|
|
75
|
+
size="md"
|
|
76
|
+
:variant="employee.avatar ? 'image' : 'initial'"
|
|
77
|
+
color="tertiary"
|
|
78
|
+
/>
|
|
79
|
+
<div class="spr-label-xs-regular">{{ employee.name }}</div>
|
|
80
|
+
<div class="spr-text-color-supporting spr-label-xs-regular spr-uppercase">
|
|
81
|
+
{{ employee.position }}
|
|
82
|
+
</div>
|
|
124
83
|
</div>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
</
|
|
134
|
-
</
|
|
135
|
-
</
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
@mouseleave="handleHover(false, index, employee.id)"
|
|
146
|
-
>
|
|
147
|
-
<section
|
|
148
|
-
v-if="
|
|
149
|
-
employee.schedule[formatDate(date, dateFormat)] &&
|
|
150
|
-
employee.schedule[formatDate(date, dateFormat)].length > 0
|
|
151
|
-
"
|
|
152
|
-
class="spr-flex spr-flex-col spr-justify-start spr-gap-size-spacing-3xs"
|
|
84
|
+
<div class="spr-mt-size-spacing-xs">
|
|
85
|
+
<spr-lozenge
|
|
86
|
+
:label="`${employee.hoursWorked || 0}/${employee.hoursTarget || 48} HRS`"
|
|
87
|
+
tone="neutral"
|
|
88
|
+
>
|
|
89
|
+
<template #icon>
|
|
90
|
+
<Icon icon="ph:clock" />
|
|
91
|
+
</template>
|
|
92
|
+
</spr-lozenge>
|
|
93
|
+
</div>
|
|
94
|
+
</td>
|
|
95
|
+
<td
|
|
96
|
+
v-for="(date, index) in weekDates"
|
|
97
|
+
:key="index"
|
|
98
|
+
:class="[
|
|
99
|
+
getCalendarClasses.borderClasses,
|
|
100
|
+
'spr-min-w-[180px] spr-content-start spr-space-y-size-spacing-3xs spr-border-x spr-border-b-0 spr-border-t spr-p-size-spacing-sm last:spr-mb-size-spacing-lg last:spr-border-r-0',
|
|
101
|
+
]"
|
|
102
|
+
@mouseover="handleHover(true, index, employee.id)"
|
|
103
|
+
@mouseleave="handleHover(false, index, employee.id)"
|
|
153
104
|
>
|
|
154
|
-
<
|
|
155
|
-
v-
|
|
156
|
-
|
|
105
|
+
<section
|
|
106
|
+
v-if="
|
|
107
|
+
employee.schedule[formatDate(date, dateFormat)] &&
|
|
108
|
+
employee.schedule[formatDate(date, dateFormat)].length > 0
|
|
109
|
+
"
|
|
110
|
+
class="spr-flex spr-flex-col spr-justify-start spr-gap-size-spacing-3xs"
|
|
157
111
|
>
|
|
158
112
|
<div
|
|
159
|
-
v-
|
|
160
|
-
|
|
161
|
-
onShiftClick({
|
|
162
|
-
employeeId: employee.id,
|
|
163
|
-
date: formatDate(date, dateFormat),
|
|
164
|
-
shift: 'restday',
|
|
165
|
-
})
|
|
166
|
-
"
|
|
113
|
+
v-for="(schedule, scheduleIndex) in employee.schedule[formatDate(date, dateFormat)]"
|
|
114
|
+
:key="scheduleIndex"
|
|
167
115
|
>
|
|
168
|
-
<
|
|
116
|
+
<div
|
|
117
|
+
v-if="schedule.type === 'restday'"
|
|
118
|
+
@click="
|
|
119
|
+
onCellClick({
|
|
120
|
+
employeeId: employee.id,
|
|
121
|
+
date: formatDate(date, dateFormat),
|
|
122
|
+
shift: 'restday',
|
|
123
|
+
})
|
|
124
|
+
"
|
|
125
|
+
>
|
|
126
|
+
<spr-calendar-cell type="restday" />
|
|
127
|
+
</div>
|
|
128
|
+
<div
|
|
129
|
+
v-else
|
|
130
|
+
@click="
|
|
131
|
+
onCellClick({
|
|
132
|
+
employeeId: employee.id,
|
|
133
|
+
date: formatDate(date, dateFormat),
|
|
134
|
+
shift: schedule,
|
|
135
|
+
})
|
|
136
|
+
"
|
|
137
|
+
>
|
|
138
|
+
<spr-calendar-cell
|
|
139
|
+
:view-only="false"
|
|
140
|
+
:title="`${schedule.startTime} - ${schedule.endTime}`"
|
|
141
|
+
:description="schedule.location"
|
|
142
|
+
:sub-description="schedule.type"
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
169
145
|
</div>
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
146
|
+
</section>
|
|
147
|
+
|
|
148
|
+
<section v-if="showAddShift(index, employee.id)">
|
|
149
|
+
<spr-calendar-cell
|
|
150
|
+
status="pending"
|
|
151
|
+
type="exempt"
|
|
152
|
+
:view-only="false"
|
|
153
|
+
@on-click="
|
|
154
|
+
onCellClick({ employeeId: employee.id, date: formatDate(date, dateFormat), shift: null })
|
|
178
155
|
"
|
|
179
156
|
>
|
|
180
|
-
<
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
157
|
+
<template #prefix>
|
|
158
|
+
<Icon icon="ph:plus" />
|
|
159
|
+
</template>
|
|
160
|
+
<div class="spr-label-xs-medium">Add New Shift</div>
|
|
161
|
+
</spr-calendar-cell>
|
|
162
|
+
</section>
|
|
163
|
+
</td>
|
|
164
|
+
</tr>
|
|
165
|
+
</tbody>
|
|
166
|
+
<tbody v-else>
|
|
167
|
+
<tr v-if="!loading" class="spr-h-full">
|
|
168
|
+
<td :colspan="weekDates.length + 1" class="spr-flex spr-h-full spr-items-center spr-justify-center">
|
|
169
|
+
<slot name="empty-state">
|
|
170
|
+
<SprEmptyState
|
|
171
|
+
size="large"
|
|
172
|
+
:description="emptyStateTitle"
|
|
173
|
+
:sub-description="emptyStateDescription"
|
|
174
|
+
>
|
|
175
|
+
<template v-if="emptyStateButtonText" #button>
|
|
176
|
+
<spr-button tone="success"
|
|
177
|
+
><Icon icon="ph:plus" @click="$emit('onClickEmptyButton')" />{{
|
|
178
|
+
emptyStateButtonText
|
|
179
|
+
}}</spr-button
|
|
180
|
+
>
|
|
181
|
+
</template>
|
|
182
|
+
</SprEmptyState>
|
|
183
|
+
</slot>
|
|
184
|
+
</td>
|
|
185
|
+
</tr>
|
|
186
|
+
<tr v-else>
|
|
187
|
+
<td :colspan="weekDates.length + 1" class="spr-h-[360px] spr-overflow-hidden">
|
|
188
|
+
<slot name="loading">
|
|
189
|
+
<div class="spr-flex spr-items-center spr-justify-center">
|
|
190
|
+
<Icon size="48" icon="svg-spinners:ring-resize" class="spr-text-color-success-base" />
|
|
186
191
|
</div>
|
|
187
|
-
</
|
|
188
|
-
</
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
type="exempt"
|
|
194
|
-
:view-only="false"
|
|
195
|
-
@on-click="
|
|
196
|
-
onShiftClick({ employeeId: employee.id, date: formatDate(date, dateFormat), shift: null })
|
|
197
|
-
"
|
|
198
|
-
>
|
|
199
|
-
<template #prefix>
|
|
200
|
-
<Icon icon="ph:plus" />
|
|
201
|
-
</template>
|
|
202
|
-
<div class="spr-label-xs-medium">Add New Shift</div>
|
|
203
|
-
</spr-calendar-cell>
|
|
204
|
-
</section>
|
|
205
|
-
</td>
|
|
206
|
-
</tr>
|
|
207
|
-
</tbody>
|
|
208
|
-
<tbody v-else>
|
|
209
|
-
<tr v-if="!loading" class="spr-h-full">
|
|
210
|
-
<td :colspan="weekDates.length + 1" class="spr-flex spr-h-full spr-items-center spr-justify-center">
|
|
211
|
-
<slot name="empty-state">
|
|
212
|
-
<SprEmptyState size="large" :description="emptyStateTitle" :sub-description="emptyStateDescription">
|
|
213
|
-
<template v-if="emptyStateButtonText" #button>
|
|
214
|
-
<spr-button tone="success"><Icon icon="ph:plus" />{{ emptyStateButtonText }}</spr-button>
|
|
215
|
-
</template>
|
|
216
|
-
</SprEmptyState>
|
|
217
|
-
</slot>
|
|
218
|
-
</td>
|
|
219
|
-
</tr>
|
|
220
|
-
<tr v-else>
|
|
221
|
-
<td :colspan="weekDates.length + 1" class="spr-overflow-hidden">
|
|
222
|
-
<slot name="loading">
|
|
223
|
-
<div class="spr-flex spr-items-center spr-justify-center">Loading...</div>
|
|
224
|
-
</slot>
|
|
225
|
-
</td>
|
|
226
|
-
</tr>
|
|
227
|
-
</tbody>
|
|
228
|
-
</table>
|
|
192
|
+
</slot>
|
|
193
|
+
</td>
|
|
194
|
+
</tr>
|
|
195
|
+
</tbody>
|
|
196
|
+
</table>
|
|
197
|
+
</div>
|
|
229
198
|
</div>
|
|
230
199
|
</div>
|
|
231
200
|
</template>
|
|
@@ -235,10 +204,8 @@
|
|
|
235
204
|
<script setup lang="ts">
|
|
236
205
|
import { Icon } from '@iconify/vue';
|
|
237
206
|
import SprButton from '@/components/button/button.vue';
|
|
238
|
-
import SprInput from '@/components/input/input.vue';
|
|
239
207
|
import SprAvatar from '@/components/avatar/avatar.vue';
|
|
240
208
|
import SprCard from '@/components/card/card.vue';
|
|
241
|
-
import SprDropdown from '@/components/dropdown/dropdown.vue';
|
|
242
209
|
import SprLozenge from '@/components/lozenge/lozenge.vue';
|
|
243
210
|
import SprCalendarCell from '@/components/calendar-cell/calendar-cell.vue';
|
|
244
211
|
import SprEmptyState from '@/components/empty-state/empty-state.vue';
|
|
@@ -250,26 +217,22 @@ const emit = defineEmits(calendarEmitTypes);
|
|
|
250
217
|
|
|
251
218
|
const {
|
|
252
219
|
// State
|
|
253
|
-
searchTerm,
|
|
254
|
-
selectedCompany,
|
|
255
|
-
selectedDepartment,
|
|
256
|
-
selectedBranch,
|
|
257
220
|
weekDates,
|
|
258
221
|
weekRangeDisplay,
|
|
259
222
|
getCalendarClasses,
|
|
260
|
-
companyDropDown,
|
|
261
|
-
departmentDropDown,
|
|
262
|
-
branchDropDown,
|
|
263
223
|
dateFormat,
|
|
224
|
+
getSortIcon,
|
|
225
|
+
sort,
|
|
226
|
+
tableBodyRef,
|
|
264
227
|
// Function
|
|
265
228
|
formatDate,
|
|
266
229
|
isToday,
|
|
267
230
|
prevWeek,
|
|
268
231
|
nextWeek,
|
|
269
232
|
goToToday,
|
|
270
|
-
|
|
233
|
+
onCellClick,
|
|
271
234
|
handleHover,
|
|
272
235
|
showAddShift,
|
|
273
|
-
|
|
236
|
+
handleSorting,
|
|
274
237
|
} = useCalendar(props, emit);
|
|
275
238
|
</script>
|