Skip to content
Merged

Dev #83

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions library/src/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import type React from "react"
import { type CSSProperties, forwardRef, type HTMLProps, useMemo } from "react"
import {
type CSSProperties,
forwardRef,
type HTMLProps,
useMemo,
useRef,
} from "react"
import { twJoin, twMerge } from "tailwind-merge"
import { LoadingSpinner } from "./LoadingSpinner"

Expand Down Expand Up @@ -204,25 +210,32 @@ export const LoadingButton = ({
loadingSpinnerClassName,
...props
}: ButtonProps & { loading: boolean; loadingSpinnerClassName?: string }) => {
const ref = useRef<HTMLDivElement>(null)

const height = ref.current?.clientHeight ?? 0

return (
<Button
iconAfter={!loading && iconAfter}
iconBefore={!loading && iconBefore}
{...props}
>
<div className={loading ? "opacity-0" : undefined}>{children}</div>
{loading && (
<div className="absolute inset-0 flex items-center justify-center">
<LoadingSpinner
className={twMerge(
loadingSpinnerClassNames[
props.appearance ?? "default"
],
loadingSpinnerClassName,
)}
/>
</div>
)}
<div
className={`absolute inset-0 flex items-center justify-center ${loading ? "" : "opacity-0"}`}
ref={ref}
>
<LoadingSpinner
className={twMerge(
loadingSpinnerClassNames[props.appearance ?? "default"],
loadingSpinnerClassName,
)}
style={{
height: `${height * 0.8}px`,
width: `${height * 0.8}px`,
}}
/>
</div>
</Button>
)
}
Expand Down
1 change: 1 addition & 0 deletions library/src/components/inputs/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ function useClassNamesConfig<ValueType, IsMulti extends boolean = boolean>(
provided.isDisabled
? "bg-disabled text-disabled-text"
: undefined,
provided.data.isFixed ? "pr-1" : undefined,
),
"text-ellipsis whitespace-nowrap",
classNamesConfig?.multiValue?.(provided),
Expand Down
54 changes: 19 additions & 35 deletions library/src/components/timetable/TimeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
} from "./TimeTableSelectionStore"
import { useGroupRows } from "./useGoupRows"
import { twMerge } from "tailwind-merge"
import { getStartAndEndSlot } from "./timeTableUtils"
import { getStartAndEndSlot, getTimeSlotMinutes } from "./timeTableUtils"
import { flushSync } from "react-dom"

export interface TimeSlotBooking {
Expand Down Expand Up @@ -205,6 +205,8 @@ const nowbarUpdateIntervall = 1000 * 60 // 1 minute
* 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.
*
* The index exports a memoized version of the LPTimeTable, which is used by the parent component.
*
* @emits allGroupsRendered (exported, string: timetable-allgroupsrendered) - when all groups are rendered
*/
export default function LPTimeTable<
G extends TimeTableGroup,
Expand Down Expand Up @@ -270,7 +272,7 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
// biome-ignore lint/correctness/useExhaustiveDependencies: just remove the message is props change
useEffect(() => {
setMessage?.(undefined) // clear the message on time frame change
}, [viewType, startDate, endDate, setMessage, timeStepsMinutes])
}, [startDate, endDate, setMessage, timeStepsMinutes])

const tableRef = useRef<HTMLTableElement>(null)
const tableHeaderRef = useRef<HTMLTableSectionElement>(null)
Expand Down Expand Up @@ -316,7 +318,7 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
itemsWithSameStartAndEnd,
slotsArray,
timeFrameDay,
timeSlotMinutes,
viewType: currViewType,
} = useGroupRows(entries)

if (!slotsArray || slotsArray.length === 0) {
Expand Down Expand Up @@ -401,18 +403,10 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
tableHeaderRef,
tableBodyRef,
timeFrameDay,
timeSlotMinutes,
viewType,
currViewType,
setMessage,
)
}, [
slotsArray,
nowOverwrite,
timeFrameDay,
timeSlotMinutes,
viewType,
setMessage,
])
}, [slotsArray, nowOverwrite, timeFrameDay, currViewType, setMessage])

// initial run, and start interval to move the now bar
useEffect(() => {
Expand All @@ -439,11 +433,10 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
tableHeaderRef,
tableBodyRef,
timeFrameDay,
timeSlotMinutes,
viewType,
currViewType,
setMessage,
)
}, [setMessage, slotsArray, timeFrameDay, timeSlotMinutes, viewType])
}, [setMessage, slotsArray, timeFrameDay, currViewType])

useResizeObserver({
ref: tableBodyRef,
Expand Down Expand Up @@ -507,12 +500,11 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
>
<LPTimeTableHeader<G, I>
slotsArray={slotsArray}
timeSlotMinutes={timeSlotMinutes}
columnWidth={columnWidth}
groupHeaderColumnWidth={groupHeaderColumnWidth}
startDate={startDate}
endDate={endDate}
viewType={viewType}
viewType={currViewType}
timeFrameDay={timeFrameDay}
showTimeSlotHeader={
showTimeSlotHeader === undefined ||
Expand All @@ -539,9 +531,8 @@ const LPTimeTableImpl = <G extends TimeTableGroup, I extends TimeSlotBooking>({
}
headerRef={tableHeaderRef}
slotsArray={slotsArray}
timeSlotMinutes={timeSlotMinutes}
timeFrameDay={timeFrameDay}
viewType={viewType}
viewType={currViewType}
/>
</tbody>
</table>
Expand All @@ -568,7 +559,6 @@ function moveNowBar(
tableHeaderRef: MutableRefObject<HTMLTableSectionElement | null>,
tableBodyRef: MutableRefObject<HTMLTableSectionElement | null>,
timeFrameDay: TimeFrameDay,
timeSlotMinutes: number,
viewType: TimeTableViewType,
setMessage?: (message: TimeTableMessage) => void,
) {
Expand Down Expand Up @@ -623,7 +613,6 @@ function moveNowBar(
nowItem,
slotsArray,
timeFrameDay,
timeSlotMinutes,
viewType,
)
if (startAndEndSlot.status !== "in") {
Expand Down Expand Up @@ -684,19 +673,13 @@ function moveNowBar(
nowBarRef.current = nowBar
}

let currentTimeSlot = slotsArray[startSlot]
if (viewType !== "hours") {
currentTimeSlot = currentTimeSlot
.add(timeFrameDay.startHour, "hour")
.add(timeFrameDay.startMinute, "minute")
}

const diffNowDays = now.diff(currentTimeSlot, "days")
let diffNow = now.diff(currentTimeSlot, "minutes")
if (diffNowDays > 0) {
const dDay = 24 * 60 - timeFrameDay.oneDayMinutes
diffNow = diffNow - dDay * diffNowDays
}
const currentTimeSlot = slotsArray[startSlot]
const timeSlotMinutes = getTimeSlotMinutes(
currentTimeSlot,
timeFrameDay,
viewType,
)
const diffNow = now.diff(currentTimeSlot, "minutes")

const diffPerc = diffNow / timeSlotMinutes
nowBar.style.left = `${diffPerc * 100}%`
Expand Down Expand Up @@ -727,6 +710,7 @@ function moveNowBar(
console.error("unable to find header date row")
return
}

const headerDateCells = headerDateRow.children
for (const headerDateCell of headerDateCells) {
headerDateCell.classList.remove("text-text-subtle")
Expand Down
18 changes: 3 additions & 15 deletions library/src/components/timetable/TimeTableConfigStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ export type TimeTableConfig<G extends TimeTableGroup> = {
basicProperties: {
timeFrameDay: TimeFrameDay
slotsArray: readonly Dayjs[]
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)
viewType: TimeTableViewType
}
viewType: TimeTableViewType
disableWeekendInteractions: boolean
hideOutOfRangeMarkers: boolean
timeSlotSelectionDisabled: boolean
Expand Down Expand Up @@ -73,7 +72,6 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(

timeTableConfigStore[ident] = proxy<TimeTableConfig<G>>({
basicProperties,
viewType,

propTimeSlotMinutes,

Expand Down Expand Up @@ -107,7 +105,7 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
timeTableConfigStore[ident].endDate !== endDateString ||
timeTableConfigStore[ident].propTimeSlotMinutes !==
propTimeSlotMinutes ||
timeTableConfigStore[ident].viewType !== viewType
timeTableConfigStore[ident].basicProperties.viewType !== viewType
) {
const basicProperties = calculateTimeSlotPropertiesForView(
startDate,
Expand All @@ -134,7 +132,7 @@ export function initAndUpdateTimeTableConfigStore<G extends TimeTableGroup>(
timeTableConfigStore[ident].propTimeSlotMinutes !==
propTimeSlotMinutes,
"view type updated",
timeTableConfigStore[ident].viewType !== viewType,
timeTableConfigStore[ident].basicProperties.viewType !== viewType,
)

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

timeTableConfigStore[ident].basicProperties = basicProperties
timeTableConfigStore[ident].viewType = viewType
timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes
timeTableConfigStore[ident].startDate = startDateString
timeTableConfigStore[ident].endDate = endDateString
timeTableConfigStore[ident].propTimeSlotMinutes = propTimeSlotMinutes
timeTableConfigStore[ident].viewType = viewType
}

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

/**
* returns the view type and a setter for it
*/
export function useTTCViewType(ident: string) {
const viewType = useSnapshot(timeTableConfigStore[ident]).viewType
return viewType
}

//#endregion

//#region utilities
Expand Down
8 changes: 6 additions & 2 deletions library/src/components/timetable/TimeTableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
} from "./TimeTable"
import type { TimeFrameDay } from "./TimeTableConfigStore"
import useResizeObserver, { type ObservedSize } from "use-resize-observer"
import { getTimeSlotMinutes } from "./timeTableUtils"

const headerTimeSlotFormat: { [viewType in TimeTableViewType]: string } = {
hours: "HH:mm",
Expand Down Expand Up @@ -88,7 +89,6 @@ type TimeTableHeaderProps<
I extends TimeSlotBooking,
> = {
slotsArray: readonly Dayjs[]
timeSlotMinutes: number
groupHeaderColumnWidth: number | string
columnWidth: number | string
startDate: Dayjs
Expand Down Expand Up @@ -120,7 +120,6 @@ export const LPTimeTableHeader = function TimeTableHeader<
I extends TimeSlotBooking,
>({
slotsArray,
timeSlotMinutes,
groupHeaderColumnWidth,
columnWidth,
startDate,
Expand Down Expand Up @@ -311,6 +310,11 @@ export const LPTimeTableHeader = function TimeTableHeader<
const isLastOfDay =
i === slotsArray.length - 1 ||
!slotsArray[i + 1].isSame(slot, "day")
const timeSlotMinutes = getTimeSlotMinutes(
slotsArray[i],
timeFrameDay,
viewType,
)
return (
<CustomHeaderRowCell
customHeaderRow={customHeaderRow}
Expand Down
Loading