notification
Reads the signed-in customer's notifications and marks one of them, or all of them, as read.
import { notification, NotificationsListResponse } from '@salla.sa/twilight-theme-engine/api/notification';In plain words
Stores send customers notifications: an order shipped, a price dropped. notification.list() returns the latest ones, each with a title, a body and whether it has been read. markAsRead(id) and markAllAsRead() tell Salla the customer has seen them.
Like everything in a customer's account, it needs a signed-in shopper.
Signature
notification.list(): Promise<NotificationsListResponse> // GET notifications (first page)
notification.markAsRead(id: number): Promise<void> // PUT notifications/{id}/read
notification.markAllAsRead(): Promise<void> // PUT notifications/read-all
notification.queries.list() // key ['notifications', 'list']
interface NotificationsListResponse {
data: Notification[];
cursor: { current: number; previous: number | null; next: number | null; count: number };
}
// import type { Notification } from '@salla.sa/twilight-theme-engine/routes/account'
// { id; title; body; icon; color; url; is_read; time_ago; created_at }Try it live
import { useQuery } from '@tanstack/react-query';
import { getAuthToken } from '@salla.sa/twilight-theme-engine/api/client';
import { notification } from '@salla.sa/twilight-theme-engine/api/notification';
export function NotificationBell() {
const { data } = useQuery({
...notification.queries.list(),
enabled: Boolean(getAuthToken()),
});
const unread = data?.data.filter((item) => !item.is_read).length ?? 0;
return <span className="bell" data-count={unread} />;
}
Example
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { notification } from '@salla.sa/twilight-theme-engine/api/notification';
/** On the account notifications page, where the customer is signed in. */
export function MarkAllRead() {
const queryClient = useQueryClient();
const { data } = useQuery(notification.queries.list());
const unread = data?.data.filter((item) => !item.is_read).length ?? 0;
const markAll = async () => {
await notification.markAllAsRead();
// The module does not touch the cache: read the list again.
await queryClient.invalidateQueries({ queryKey: notification.queries.list().queryKey });
};
return (
<button type="button" disabled={unread === 0} onClick={() => void markAll()}>
Mark {unread} as read
</button>
);
}
How it behaves
A guest gets HTTP 400
token_not_provided(demo store). The engine notifications loader wrapslist()inorUnauthorized, which lets that 400 through as an error.Both marks parse the answer with ky's
.json(), which throws on an empty body or a 204: they expect Salla's usual JSON envelope back.Here
cursor.nextis a page number, not a URL or a token.
Gotchas
list()takes no arguments, so only the first page is reachable. docs/notifications-route.md and route-pagination.md shownotification.list(1)and readresponse.items; that call does not compile, and the result hasdata, notitems.markAsReadandmarkAllAsReaddo not update the cached list. Invalidatenotification.queries.list().queryKey, or update it withsetQueryData.