diff --git a/src/lib/datetime.ts b/src/lib/datetime.ts index 7dafd50..35db356 100644 --- a/src/lib/datetime.ts +++ b/src/lib/datetime.ts @@ -57,11 +57,15 @@ function getLocalizedNowWord(locale: string) { return translations[locale as keyof typeof translations] || 'now'; } -export const humanDeltaFromNow = (start: string | Date | Dayjs, end: string | Date | Dayjs): { +export const humanDeltaFromNow = (start: string | Date | Dayjs, end?: string | Date | Dayjs): { message: string, delta: "PAST" | "FUTURE" | "NOW" } => { + if (!end) { + end = start + } + // check if end is in the past if (dayjs(end).isBefore(dayjs())) { return { @@ -112,29 +116,27 @@ export const pprintDateRange = (d1: string | Date | Dayjs, d2: string | Date | D * @param date2 */ export function formatDuration(date1: string | Date | Dayjs, date2: string | Date | Dayjs) { - const start = dayjs(date1) - const end = dayjs(date2) - const diff = end.diff(start) - const duration = dayjs.duration(diff) - const weeks = Math.floor(duration.asDays() / 7); - const days = duration.days() % 7; - const hours = duration.hours(); - const minutes = duration.minutes(); - const parts = []; + // ignore seconds and milliseconds + date1 = dayjs(date1).startOf('minute'); + date2 = dayjs(date2).startOf('minute'); - if (weeks > 0) { - parts.push(`${weeks} Wo`); - } - if (days > 0 || weeks > 0) { - parts.push(`${days} Tag${days > 1 ? 'e' : ''}`); - } - if (hours > 0) { - parts.push(`${hours} Std`); - } - if (minutes > 0) { - parts.push(`${minutes} Min`); - } + // get the difference in milliseconds + const diff = dayjs(date2).diff(dayjs(date1)); + const durationObj = dayjs.duration(diff); - return parts.join(', '); + // get the duration in weeks, days, hours and minutes + const weeks = Math.floor(durationObj.asWeeks()); + const days = durationObj.days(); + const hours = durationObj.hours(); + const minutes = durationObj.minutes(); + + // create a string array with the duration parts + const result: string[] = []; + if (weeks > 0) result.push(`${weeks} Wo`); + if (days > 0) result.push(`${days} Tag${days > 1 ? 'e' : ''}`); + if (hours > 0) result.push(`${hours} Std`); + if (minutes > 0) result.push(`${minutes} Min`); + + return result.join(', '); } \ No newline at end of file diff --git a/src/pages/chat/components/Announcement.module.css b/src/pages/chat/components/Announcement.module.css index 993b4e7..b331de3 100644 --- a/src/pages/chat/components/Announcement.module.css +++ b/src/pages/chat/components/Announcement.module.css @@ -3,17 +3,14 @@ position: relative; flex-direction: column; - box-shadow: var(--shadow); - background-color: var(--mantine-color-body); padding: var(--padding); border: var(--border); border-color: var(--mantine-primary-color-5); - border-radius: var(--mantine-radius-lg); + border-radius: var(--border-radius); - margin: var(--gap); max-width: 100%; word-break: break-all; @@ -24,4 +21,11 @@ font-size: var(--mantine-font-size-lg); font-weight: bold; color: var(--mantine-primary-color-5); + margin: 0; +} + +.subjectStack { + display: flex; + flex-direction: column; + justify-content: center; } \ No newline at end of file diff --git a/src/pages/chat/components/Announcement.tsx b/src/pages/chat/components/Announcement.tsx index 4d32197..5611f41 100644 --- a/src/pages/chat/components/Announcement.tsx +++ b/src/pages/chat/components/Announcement.tsx @@ -1,26 +1,37 @@ import InnerHtml from "@/components/InnerHtml"; import classes from './Announcement.module.css' -import {Group, ThemeIcon} from "@mantine/core"; +import {Group, Text, ThemeIcon, Tooltip} from "@mantine/core"; import {IconSpeakerphone} from "@tabler/icons-react"; +import {MessagesModel} from "@/models/MessageTypes.ts"; +import {getUserName} from "@/components/users/modals/util.tsx"; +import {humanDeltaFromNow, pprintDate} from "@/lib/datetime.ts"; -export default function Announcement({subject, content}: { - subject: string | null, - content: string, +export default function Announcement({announcement}: { + announcement: MessagesModel }) { + const senderName = getUserName(announcement.expand.sender) return
- {subject &&
- {subject} -
} +
+ {announcement.subject &&
+ {announcement.subject} +
} - - - + + {senderName} • {pprintDate(announcement.created)} • {humanDeltaFromNow(announcement.created).message} + +
+ + + + + +
- +
} \ No newline at end of file diff --git a/src/pages/chat/components/Announcements.module.css b/src/pages/chat/components/Announcements.module.css index 3db7f98..b24a26e 100644 --- a/src/pages/chat/components/Announcements.module.css +++ b/src/pages/chat/components/Announcements.module.css @@ -2,5 +2,6 @@ flex-grow: 1; overflow-y: auto; display: flex; - flex-direction: column-reverse; + flex-direction: column; + gap: var(--gap); } \ No newline at end of file diff --git a/src/pages/chat/components/Announcements.tsx b/src/pages/chat/components/Announcements.tsx index d5722ec..27017c1 100644 --- a/src/pages/chat/components/Announcements.tsx +++ b/src/pages/chat/components/Announcements.tsx @@ -2,7 +2,7 @@ import {useInfiniteQuery} from "@tanstack/react-query"; import {PocketBaseErrorAlert, usePB} from "@/lib/pocketbase.tsx"; import {Button, Center, Loader, Text} from "@mantine/core"; import classes from './Announcements.module.css' -import {IconMessageCircleUp} from "@tabler/icons-react"; +import {IconMessageCircleDown} from "@tabler/icons-react"; import Announcement from "@/pages/chat/components/Announcement.tsx"; export default function Announcements() { @@ -11,9 +11,10 @@ export default function Announcements() { const query = useInfiniteQuery({ queryKey: ["announcements"], queryFn: async ({pageParam}) => ( - await pb.collection("messages").getList(pageParam, 100, { + await pb.collection("messages").getList(pageParam, 50, { filter: `isAnnouncement=true&&sender!='${user?.id}'`, - sort: "-created" + sort: "-created", + expand: "sender" }) ), getNextPageParam: (lastPage) => @@ -39,8 +40,7 @@ export default function Announcements() { {announcements.map((announcement) => ( ))} @@ -50,21 +50,18 @@ export default function Announcements() { variant={"transparent"} color={"blue"} radius={"xl"} onClick={() => query.fetchNextPage()} - leftSection={} + leftSection={} loading={query.isFetchingNextPage} > Mehr laden - ) :
+ ) : announcements.length === 0 ?
- { - announcements.length > 0 ? - "Keine weiteren Ankündigungen" - : "Noch keine Ankündigungen" - } + "Noch keine Ankündigungen" -
} +
: null + } } \ No newline at end of file diff --git a/src/pages/chat/components/Messages.module.css b/src/pages/chat/components/Messages.module.css index e1a27ce..6ee4c10 100644 --- a/src/pages/chat/components/Messages.module.css +++ b/src/pages/chat/components/Messages.module.css @@ -17,8 +17,6 @@ position: relative; flex-direction: column; - box-shadow: var(--shadow); - background-color: var(--mantine-color-body); padding: var(--padding); diff --git a/src/pages/chat/components/Messages.tsx b/src/pages/chat/components/Messages.tsx index 239da97..860eec1 100644 --- a/src/pages/chat/components/Messages.tsx +++ b/src/pages/chat/components/Messages.tsx @@ -8,7 +8,7 @@ import {useInfiniteQuery, useMutation} from "@tanstack/react-query"; import {PocketBaseErrorAlert, usePB} from "@/lib/pocketbase.tsx"; import InnerHtml from "@/components/InnerHtml"; import {getUserName} from "@/components/users/modals/util.tsx"; -import {pprintDateTime} from "@/lib/datetime.ts"; +import {humanDeltaFromNow, pprintDateTime} from "@/lib/datetime.ts"; import {EventListModel} from "@/models/EventTypes.ts"; export default function Messages({eventList}: { @@ -87,7 +87,7 @@ export default function Messages({eventList}: {
- {pprintDateTime(message.created)} + {humanDeltaFromNow(message.created).message} • {pprintDateTime(message.created)}
))} diff --git a/src/pages/home/index.module.css b/src/pages/home/index.module.css index a856c9d..9e6fe13 100644 --- a/src/pages/home/index.module.css +++ b/src/pages/home/index.module.css @@ -1,5 +1,5 @@ .announcementsContainer { - max-height: 60vh; + max-height: 40vh; display: flex; & > * { max-height: 100%;