Move app to apps/web-react in pnpm workspace layout

This commit is contained in:
Kalle
2026-08-16 09:20:33 +03:00
parent 7e365ccfcf
commit bbc8ea57af
2913 changed files with 227 additions and 250 deletions

View File

@@ -0,0 +1,65 @@
.itemDivider {
margin-inline: var(--s-3);
border-width: 0.5px;
border-color: var(--color-bg-high);
}
.imageContainer {
place-self: center;
grid-area: image;
border-radius: var(--radius-avatar);
width: 30px;
height: 30px;
background-color: var(--color-bg-high);
display: grid;
place-items: center;
position: relative;
}
.item {
padding: var(--s-1) var(--s-3);
display: grid;
grid-template-areas: "image header" "image timestamp";
grid-template-columns: 30px 1fr;
column-gap: var(--s-2);
padding-block: var(--s-3);
color: var(--color-text);
&:hover .imageContainer {
outline: 3px solid var(--color-bg-higher);
}
&:focus-within .imageContainer {
outline: 3px solid var(--color-accent-low);
}
}
.unseenDot {
background-color: var(--color-text-accent);
border-radius: 100%;
width: 8px;
height: 8px;
position: absolute;
top: -1px;
left: -1px;
outline: 2px solid var(--color-bg);
}
.itemImage {
width: 30px;
height: 30px;
border-radius: var(--radius-avatar);
}
.itemHeader {
grid-area: header;
font-size: var(--font-sm);
font-weight: var(--weight-semi);
}
.timestamp {
grid-area: timestamp;
color: var(--color-text-high);
font-size: var(--font-2xs);
font-weight: var(--weight-body);
}

View File

@@ -0,0 +1,99 @@
import { formatDistance } from "date-fns";
import { useTranslation } from "react-i18next";
import { Link } from "react-router";
import { Image } from "~/components/Image";
import type { LoaderNotification } from "~/components/layout/NotificationPopover";
import {
notificationLink,
notificationMeta,
notificationNavIcon,
} from "~/features/notifications/notifications-utils";
import { databaseTimestampToDate } from "~/utils/dates";
import { navIconUrl } from "~/utils/urls";
import styles from "./NotificationList.module.css";
export function NotificationsList({ children }: { children: React.ReactNode }) {
return <div>{children}</div>;
}
export function NotificationItem({
notification,
onClose,
}: {
notification: LoaderNotification;
onClose?: () => void;
}) {
const { t } = useTranslation(["common"]);
return (
<Link
to={notificationLink(notification)}
className={styles.item}
data-testid="notification-item"
onClick={onClose}
>
<NotificationImage notification={notification}>
{!notification.seen ? (
<div
className={styles.unseenDot}
data-testid="notification-unseen-dot"
/>
) : null}
</NotificationImage>
<div className={styles.itemHeader}>
{t(
`common:notifications.text.${notification.type}`,
notificationMeta(notification),
)}
</div>
<div className={styles.timestamp}>
{formatDistance(
databaseTimestampToDate(notification.createdAt),
new Date(),
{
addSuffix: true,
},
)}
</div>
</Link>
);
}
export function NotificationItemDivider() {
return <hr className={styles.itemDivider} />;
}
function NotificationImage({
notification,
children,
}: {
notification: LoaderNotification;
children: React.ReactNode;
}) {
if (notification.pictureUrl) {
return (
<div className={styles.imageContainer}>
{children}
<img
src={notification.pictureUrl}
alt="Notification"
className={styles.itemImage}
width={124}
height={124}
/>
</div>
);
}
return (
<div className={styles.imageContainer}>
{children}
<Image
path={navIconUrl(notificationNavIcon(notification.type))}
width={24}
height={24}
alt=""
/>
</div>
);
}