Skip to content

Commit cec746f

Browse files
committed
chore(workplace): add status dots to day and week view schedule cards
1 parent 2b04e6c commit cec746f

2 files changed

Lines changed: 109 additions & 24 deletions

File tree

apps/workplace/src/app/schedule/schedule-day-view.component.ts

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ interface PositionedBooking {
5454
{{ date() | date: 'EEEE, MMMM d, yyyy' }}
5555
</h2>
5656
<div
57-
class="rounded-md border border-base-300 bg-base-100 px-2 py-1 text-sm text-base-content"
57+
class="border-base-300 bg-base-100 text-base-content rounded-md border px-2 py-1 text-sm"
5858
>
5959
{{ bookings()?.length || 0 }} booking{{
6060
bookings()?.length !== 1 ? 's' : ''
@@ -66,7 +66,7 @@ interface PositionedBooking {
6666
<div class="w-12 flex-shrink-0 pr-2">
6767
@for (slot of timeSlots(); track slot.hour) {
6868
<div
69-
class="flex h-16 items-start justify-end text-xs text-base-content opacity-60"
69+
class="text-base-content flex h-16 items-start justify-end text-xs opacity-60"
7070
>
7171
<div class="relative -translate-y-1/2">
7272
{{ slot.label }}
@@ -77,17 +77,17 @@ interface PositionedBooking {
7777
7878
<!-- Calendar grid -->
7979
<div
80-
class="relative flex-1 overflow-hidden rounded-xl border-x border-b border-base-300 bg-base-100"
80+
class="border-base-300 bg-base-100 relative flex-1 overflow-hidden rounded-xl border-x border-b"
8181
>
8282
<!-- Grid lines -->
8383
<div class="absolute inset-0">
8484
@for (slot of timeSlots(); track slot.hour) {
8585
<div class="relative h-16">
8686
<div
87-
class="absolute inset-x-0 top-0 border-t border-base-300"
87+
class="border-base-300 absolute inset-x-0 top-0 border-t"
8888
></div>
8989
<div
90-
class="absolute inset-x-0 top-8 border-t border-dashed border-base-300"
90+
class="border-base-300 absolute inset-x-0 top-8 border-t border-dashed"
9191
></div>
9292
</div>
9393
}
@@ -101,10 +101,10 @@ interface PositionedBooking {
101101
[style.top.%]="currentTimePosition()"
102102
>
103103
<div
104-
class="-ml-1 h-2 w-2 rounded-full bg-error"
104+
class="bg-error -ml-1 h-2 w-2 rounded-full"
105105
></div>
106106
<div
107-
class="flex-1 border-t-2 border-error"
107+
class="border-error flex-1 border-t-2"
108108
></div>
109109
</div>
110110
}
@@ -139,8 +139,11 @@ interface PositionedBooking {
139139
'
140140
' +
141141
($any(item.booking).user_name ||
142-
($any(item.booking).host | user | async)
143-
?.name ||
142+
(
143+
$any(item.booking).host
144+
| user
145+
| async
146+
)?.name ||
144147
$any(item.booking).host) +
145148
'
146149
' +
@@ -152,16 +155,35 @@ interface PositionedBooking {
152155
"
153156
>
154157
<div
155-
class="flex items-center space-x-1 truncate text-sm font-medium"
158+
class="flex items-start justify-between gap-2 text-sm font-medium"
156159
>
157-
<div>{{ item.booking.title }}</div>
160+
<div class="min-w-0 truncate">
161+
{{ item.booking.title }}
162+
@if (
163+
item.height <= 5 &&
164+
location(item.booking)
165+
) {
166+
<span
167+
class="text-xs opacity-60"
168+
>
169+
·
170+
{{ location(item.booking) }}
171+
</span>
172+
}
173+
</div>
158174
@if (
159-
item.height <= 5 &&
160-
location(item.booking)
175+
bookingStatus(item.booking);
176+
as status
161177
) {
162-
<div class="text-xs opacity-60">
163-
· {{ location(item.booking) }}
164-
</div>
178+
<div
179+
class="h-2.5 w-2.5 flex-shrink-0 rounded-full"
180+
[style.background-color]="
181+
statusColor(status)
182+
"
183+
[matTooltip]="
184+
statusLabel(status)
185+
"
186+
></div>
165187
}
166188
</div>
167189
@if (item.height > 3) {
@@ -187,7 +209,10 @@ interface PositionedBooking {
187209
{{ location(item.booking) }}
188210
</div>
189211
}
190-
@if (item.height > 7 && $any(item.booking).host) {
212+
@if (
213+
item.height > 7 &&
214+
$any(item.booking).host
215+
) {
191216
<div
192217
class="mt-1 truncate text-xs opacity-60"
193218
>
@@ -214,14 +239,16 @@ interface PositionedBooking {
214239
>
215240
Booked by
216241
{{
217-
$any(item.booking).booked_by_name ||
242+
$any(item.booking)
243+
.booked_by_name ||
218244
(
219245
$any(item.booking)
220246
.booked_by_email
221247
| user
222248
| async
223249
)?.name ||
224-
$any(item.booking).booked_by_email
250+
$any(item.booking)
251+
.booked_by_email
225252
}}
226253
</div>
227254
}
@@ -458,6 +485,27 @@ export class ScheduleDayViewComponent extends AsyncHandler implements OnInit {
458485
return booking.extension_data?.shared_event ? 'group-event' : 'event';
459486
}
460487

488+
public bookingStatus(
489+
booking: Booking | CalendarEvent,
490+
): 'approved' | 'tentative' | 'declined' | null {
491+
const status = booking.status;
492+
return status === 'approved' ||
493+
status === 'tentative' ||
494+
status === 'declined'
495+
? status
496+
: null;
497+
}
498+
499+
public statusLabel(status: 'approved' | 'tentative' | 'declined') {
500+
return status.charAt(0).toUpperCase() + status.slice(1);
501+
}
502+
503+
public statusColor(status: 'approved' | 'tentative' | 'declined') {
504+
if (status === 'approved') return 'var(--success)';
505+
if (status === 'tentative') return 'var(--warn)';
506+
return 'var(--error)';
507+
}
508+
461509
public location(booking: Booking | CalendarEvent): string {
462510
let location = '';
463511
let level_name = '';

apps/workplace/src/app/schedule/schedule-week-view.component.ts

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ interface Weekday {
8080
@for (day of weekdays(); track day.id) {
8181
<div
8282
body
83-
class="flex min-h-[calc(100vh-15rem)] flex-col space-y-2 rounded-xl border border-base-300 bg-base-100 p-2"
83+
class="border-base-300 bg-base-100 flex min-h-[calc(100vh-15rem)] flex-col space-y-2 rounded-xl border p-2"
8484
[class.opacity-30]="day.is_past"
8585
>
8686
@for (
@@ -89,7 +89,7 @@ interface Weekday {
8989
) {
9090
<button
9191
matRipple
92-
class="w-full rounded-lg border bg-base-100 p-2 text-left text-black"
92+
class="bg-base-100 w-full rounded-lg border p-2 text-left text-black"
9393
[style.border-color]="colors[type(bkn)][1]"
9494
[style.background-color]="
9595
colors[type(bkn)][0]
@@ -104,7 +104,8 @@ interface Weekday {
104104
'
105105
' +
106106
($any(bkn).user_name ||
107-
($any(bkn).host | user | async)?.name ||
107+
($any(bkn).host | user | async)
108+
?.name ||
108109
$any(bkn).host) +
109110
'
110111
' +
@@ -113,8 +114,23 @@ interface Weekday {
113114
(bkn.date_end | date: 'shortTime')
114115
"
115116
>
116-
<div class="truncate text-sm">
117-
{{ bkn.title }}
117+
<div
118+
class="flex items-start justify-between gap-2"
119+
>
120+
<div class="min-w-0 truncate text-sm">
121+
{{ bkn.title }}
122+
</div>
123+
@if (bookingStatus(bkn); as status) {
124+
<div
125+
class="h-2.5 w-2.5 flex-shrink-0 rounded-full"
126+
[style.background-color]="
127+
statusColor(status)
128+
"
129+
[matTooltip]="
130+
statusLabel(status)
131+
"
132+
></div>
133+
}
118134
</div>
119135
@if (location(bkn)) {
120136
<div
@@ -233,6 +249,27 @@ export class ScheduleWeekViewComponent {
233249
return booking.extension_data?.shared_event ? 'group-event' : 'event';
234250
}
235251

252+
public bookingStatus(
253+
booking: Booking | CalendarEvent,
254+
): 'approved' | 'tentative' | 'declined' | null {
255+
const status = booking.status;
256+
return status === 'approved' ||
257+
status === 'tentative' ||
258+
status === 'declined'
259+
? status
260+
: null;
261+
}
262+
263+
public statusLabel(status: 'approved' | 'tentative' | 'declined') {
264+
return status.charAt(0).toUpperCase() + status.slice(1);
265+
}
266+
267+
public statusColor(status: 'approved' | 'tentative' | 'declined') {
268+
if (status === 'approved') return 'var(--success)';
269+
if (status === 'tentative') return 'var(--warn)';
270+
return 'var(--error)';
271+
}
272+
236273
public location(booking: Booking | CalendarEvent): string {
237274
let location = '';
238275
let level_name = '';

0 commit comments

Comments
 (0)