Skip to content

Commit a44e8fd

Browse files
Merge pull request #83 from linked-planet/dev
Dev
2 parents 9ad0942 + 643ff12 commit a44e8fd

File tree

16 files changed

+507
-368
lines changed

16 files changed

+507
-368
lines changed

library/src/components/Button.tsx

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import type React from "react"
2-
import { type CSSProperties, forwardRef, type HTMLProps, useMemo } from "react"
2+
import {
3+
type CSSProperties,
4+
forwardRef,
5+
type HTMLProps,
6+
useMemo,
7+
useRef,
8+
} from "react"
39
import { twJoin, twMerge } from "tailwind-merge"
410
import { LoadingSpinner } from "./LoadingSpinner"
511

@@ -204,25 +210,32 @@ export const LoadingButton = ({
204210
loadingSpinnerClassName,
205211
...props
206212
}: ButtonProps & { loading: boolean; loadingSpinnerClassName?: string }) => {
213+
const ref = useRef<HTMLDivElement>(null)
214+
215+
const height = ref.current?.clientHeight ?? 0
216+
207217
return (
208218
<Button
209219
iconAfter={!loading && iconAfter}
210220
iconBefore={!loading && iconBefore}
211221
{...props}
212222
>
213223
<div className={loading ? "opacity-0" : undefined}>{children}</div>
214-
{loading && (
215-
<div className="absolute inset-0 flex items-center justify-center">
216-
<LoadingSpinner
217-
className={twMerge(
218-
loadingSpinnerClassNames[
219-
props.appearance ?? "default"
220-
],
221-
loadingSpinnerClassName,
222-
)}
223-
/>
224-
</div>
225-
)}
224+
<div
225+
className={`absolute inset-0 flex items-center justify-center ${loading ? "" : "opacity-0"}`}
226+
ref={ref}
227+
>
228+
<LoadingSpinner
229+
className={twMerge(
230+
loadingSpinnerClassNames[props.appearance ?? "default"],
231+
loadingSpinnerClassName,
232+
)}
233+
style={{
234+
height: `${height * 0.8}px`,
235+
width: `${height * 0.8}px`,
236+
}}
237+
/>
238+
</div>
226239
</Button>
227240
)
228241
}

library/src/components/inputs/Select.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ function useClassNamesConfig<ValueType, IsMulti extends boolean = boolean>(
164164
provided.isDisabled
165165
? "bg-disabled text-disabled-text"
166166
: undefined,
167+
provided.data.isFixed ? "pr-1" : undefined,
167168
),
168169
"text-ellipsis whitespace-nowrap",
169170
classNamesConfig?.multiValue?.(provided),

library/src/components/timetable/TimeTable.tsx

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import {
3636
} from "./TimeTableSelectionStore"
3737
import { useGroupRows } from "./useGoupRows"
3838
import { twMerge } from "tailwind-merge"
39-
import { getStartAndEndSlot } from "./timeTableUtils"
39+
import { getStartAndEndSlot, getTimeSlotMinutes } from "./timeTableUtils"
4040
import { flushSync } from "react-dom"
4141

4242
export interface TimeSlotBooking {
@@ -205,6 +205,8 @@ const nowbarUpdateIntervall = 1000 * 60 // 1 minute
205205
* Each column in the table is actually 2 columns. 1 fixed size one, and 1 dynamic sized on. Like that I can simulate min-width on the columns, which else is not allowed.
206206
*
207207
* The index exports a memoized version of the LPTimeTable, which is used by the parent component.
208+
*
209+
* @emits allGroupsRendered (exported, string: timetable-allgroupsrendered) - when all groups are rendered
208210
*/
209211
export default function LPTimeTable<
210212
G extends TimeTableGroup,
@@ -270,7 +272,7 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
270272
// biome-ignore lint/correctness/useExhaustiveDependencies: just remove the message is props change
271273
useEffect(() => {
272274
setMessage?.(undefined) // clear the message on time frame change
273-
}, [viewType, startDate, endDate, setMessage, timeStepsMinutes])
275+
}, [startDate, endDate, setMessage, timeStepsMinutes])
274276

275277
const tableRef = useRef<HTMLTableElement>(null)
276278
const tableHeaderRef = useRef<HTMLTableSectionElement>(null)
@@ -316,7 +318,7 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
316318
itemsWithSameStartAndEnd,
317319
slotsArray,
318320
timeFrameDay,
319-
timeSlotMinutes,
321+
viewType: currViewType,
320322
} = useGroupRows(entries)
321323

322324
if (!slotsArray || slotsArray.length === 0) {
@@ -401,18 +403,10 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
401403
tableHeaderRef,
402404
tableBodyRef,
403405
timeFrameDay,
404-
timeSlotMinutes,
405-
viewType,
406+
currViewType,
406407
setMessage,
407408
)
408-
}, [
409-
slotsArray,
410-
nowOverwrite,
411-
timeFrameDay,
412-
timeSlotMinutes,
413-
viewType,
414-
setMessage,
415-
])
409+
}, [slotsArray, nowOverwrite, timeFrameDay, currViewType, setMessage])
416410

417411
// initial run, and start interval to move the now bar
418412
useEffect(() => {
@@ -439,11 +433,10 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
439433
tableHeaderRef,
440434
tableBodyRef,
441435
timeFrameDay,
442-
timeSlotMinutes,
443-
viewType,
436+
currViewType,
444437
setMessage,
445438
)
446-
}, [setMessage, slotsArray, timeFrameDay, timeSlotMinutes, viewType])
439+
}, [setMessage, slotsArray, timeFrameDay, currViewType])
447440

448441
useResizeObserver({
449442
ref: tableBodyRef,
@@ -507,12 +500,11 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
507500
>
508501
<LPTimeTableHeader<G, I>
509502
slotsArray={slotsArray}
510-
timeSlotMinutes={timeSlotMinutes}
511503
columnWidth={columnWidth}
512504
groupHeaderColumnWidth={groupHeaderColumnWidth}
513505
startDate={startDate}
514506
endDate={endDate}
515-
viewType={viewType}
507+
viewType={currViewType}
516508
timeFrameDay={timeFrameDay}
517509
showTimeSlotHeader={
518510
showTimeSlotHeader === undefined ||
@@ -539,9 +531,8 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
539531
}
540532
headerRef={tableHeaderRef}
541533
slotsArray={slotsArray}
542-
timeSlotMinutes={timeSlotMinutes}
543534
timeFrameDay={timeFrameDay}
544-
viewType={viewType}
535+
viewType={currViewType}
545536
/>
546537
</tbody>
547538
</table>
@@ -568,7 +559,6 @@ function moveNowBar(
568559
tableHeaderRef: MutableRefObject<HTMLTableSectionElement | null>,
569560
tableBodyRef: MutableRefObject<HTMLTableSectionElement | null>,
570561
timeFrameDay: TimeFrameDay,
571-
timeSlotMinutes: number,
572562
viewType: TimeTableViewType,
573563
setMessage?: (message: TimeTableMessage) => void,
574564
) {
@@ -623,7 +613,6 @@ function moveNowBar(
623613
nowItem,
624614
slotsArray,
625615
timeFrameDay,
626-
timeSlotMinutes,
627616
viewType,
628617
)
629618
if (startAndEndSlot.status !== "in") {
@@ -684,19 +673,13 @@ function moveNowBar(
684673
nowBarRef.current = nowBar
685674
}
686675

687-
let currentTimeSlot = slotsArray[startSlot]
688-
if (viewType !== "hours") {
689-
currentTimeSlot = currentTimeSlot
690-
.add(timeFrameDay.startHour, "hour")
691-
.add(timeFrameDay.startMinute, "minute")
692-
}
693-
694-
const diffNowDays = now.diff(currentTimeSlot, "days")
695-
let diffNow = now.diff(currentTimeSlot, "minutes")
696-
if (diffNowDays > 0) {
697-
const dDay = 24 * 60 - timeFrameDay.oneDayMinutes
698-
diffNow = diffNow - dDay * diffNowDays
699-
}
676+
const currentTimeSlot = slotsArray[startSlot]
677+
const timeSlotMinutes = getTimeSlotMinutes(
678+
currentTimeSlot,
679+
timeFrameDay,
680+
viewType,
681+
)
682+
const diffNow = now.diff(currentTimeSlot, "minutes")
700683

701684
const diffPerc = diffNow / timeSlotMinutes
702685
nowBar.style.left = `${diffPerc * 100}%`
@@ -727,6 +710,7 @@ function moveNowBar(
727710
console.error("unable to find header date row")
728711
return
729712
}
713+
730714
const headerDateCells = headerDateRow.children
731715
for (const headerDateCell of headerDateCells) {
732716
headerDateCell.classList.remove("text-text-subtle")

library/src/components/timetable/TimeTableConfigStore.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ export type TimeTableConfig<G extends TimeTableGroup> = {
88
basicProperties: {
99
timeFrameDay: TimeFrameDay
1010
slotsArray: readonly Dayjs[]
11-
timeSlotMinutes: number // length of 1 slot in minutes (for example if the day starts at 8, and ends at 16, and the time slot is a week, that this means (16-8)*60*7 minutes)
11+
viewType: TimeTableViewType
1212
}
13-
viewType: TimeTableViewType
1413
disableWeekendInteractions: boolean
1514
hideOutOfRangeMarkers: boolean
1615
timeSlotSelectionDisabled: boolean
@@ -73,7 +72,6 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
7372

7473
timeTableConfigStore[ident] = proxy<TimeTableConfig<G>>({
7574
basicProperties,
76-
viewType,
7775

7876
propTimeSlotMinutes,
7977

@@ -107,7 +105,7 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
107105
timeTableConfigStore[ident].endDate !== endDateString ||
108106
timeTableConfigStore[ident].propTimeSlotMinutes !==
109107
propTimeSlotMinutes ||
110-
timeTableConfigStore[ident].viewType !== viewType
108+
timeTableConfigStore[ident].basicProperties.viewType !== viewType
111109
) {
112110
const basicProperties = calculateTimeSlotPropertiesForView(
113111
startDate,
@@ -134,7 +132,7 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
134132
timeTableConfigStore[ident].propTimeSlotMinutes !==
135133
propTimeSlotMinutes,
136134
"view type updated",
137-
timeTableConfigStore[ident].viewType !== viewType,
135+
timeTableConfigStore[ident].basicProperties.viewType !== viewType,
138136
)
139137

140138
clearTimeSlotSelection(ident, true)
@@ -156,12 +154,10 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
156154
}*/
157155

158156
timeTableConfigStore[ident].basicProperties = basicProperties
159-
timeTableConfigStore[ident].viewType = viewType
160157
timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes
161158
timeTableConfigStore[ident].startDate = startDateString
162159
timeTableConfigStore[ident].endDate = endDateString
163160
timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes
164-
timeTableConfigStore[ident].viewType = viewType
165161
}
166162

167163
if (isCellDisabled !== timeTableConfigStore[ident].isCellDisabled) {
@@ -246,14 +242,6 @@ export function useTTCTimeSlotSelectionDisabled(ident: string) {
246242
return timeSlotSelectionDisabled
247243
}
248244

249-
/**
250-
* returns the view type and a setter for it
251-
*/
252-
export function useTTCViewType(ident: string) {
253-
const viewType = useSnapshot(timeTableConfigStore[ident]).viewType
254-
return viewType
255-
}
256-
257245
//#endregion
258246

259247
//#region utilities

library/src/components/timetable/TimeTableHeader.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import type {
2323
} from "./TimeTable"
2424
import type { TimeFrameDay } from "./TimeTableConfigStore"
2525
import useResizeObserver, { type ObservedSize } from "use-resize-observer"
26+
import { getTimeSlotMinutes } from "./timeTableUtils"
2627

2728
const headerTimeSlotFormat: { [viewType in TimeTableViewType]: string } = {
2829
hours: "HH:mm",
@@ -88,7 +89,6 @@ type TimeTableHeaderProps<
8889
I extends TimeSlotBooking,
8990
> = {
9091
slotsArray: readonly Dayjs[]
91-
timeSlotMinutes: number
9292
groupHeaderColumnWidth: number | string
9393
columnWidth: number | string
9494
startDate: Dayjs
@@ -120,7 +120,6 @@ export const LPTimeTableHeader = function TimeTableHeader<
120120
I extends TimeSlotBooking,
121121
>({
122122
slotsArray,
123-
timeSlotMinutes,
124123
groupHeaderColumnWidth,
125124
columnWidth,
126125
startDate,
@@ -311,6 +310,11 @@ export const LPTimeTableHeader = function TimeTableHeader<
311310
const isLastOfDay =
312311
i === slotsArray.length - 1 ||
313312
!slotsArray[i + 1].isSame(slot, "day")
313+
const timeSlotMinutes = getTimeSlotMinutes(
314+
slotsArray[i],
315+
timeFrameDay,
316+
viewType,
317+
)
314318
return (
315319
<CustomHeaderRowCell
316320
customHeaderRow={customHeaderRow}

0 commit comments

Comments
 (0)