loyalty

Reads the store's loyalty program and the signed-in customer's points balance.

Use loyalty to show the store's loyalty program, or the customer's points on the cart page.

app/components/cart/CartPage.tsx
import { useQuery } from '@tanstack/react-query';
import { loyalty } from '@salla.sa/twilight-theme-engine/api/loyalty';

export function LoyaltyPoints() {
  const { data: loyaltyPoints } = useQuery(loyalty.queries.points());

  return loyaltyPoints ? <p>{loyaltyPoints} points</p> : null;
}
app/routes/loyalty.tsx
import { loyalty } from '@salla.sa/twilight-theme-engine/api/loyalty';

loader: async () => {
  const data = await loyalty.getOrThrow();
  return { page: { slug: 'loyalty', title: data.name }, loyalty: data };
},

Methods

MethodParametersReturnsRequestLogin needed
loyalty.getnonePromise<Loyalty>GET loyalty (reads data)The module does not check; customer is null for guests
loyalty.getOrThrownonePromise<Loyalty>Same as getSame
loyalty.getPointsBalancenonePromise<number>GET balance/points (reads balance)Yes

Queries

QueryKeyNotes
loyalty.queries.detail()['loyalty']Calls get
loyalty.queries.points()['loyalty', 'points']Runs only when a token exists; fresh for 30 s

Neither key includes the locale or the scope. The program text follows the request's language, so after a client-side language switch call invalidateQueries.

Gotchas

  • Guests and points. queries.points() is off without a token, because the call would fail with token_not_provided. Calling getPointsBalance() as a guest throws HTTPError.
  • getOrThrow only handles 404 and 410. Those become a not-found page; a 401 or a 500 reaches the error boundary as usual.
  • Fresh points. After an action that changes points (an order, a redeem) call queryClient.invalidateQueries({ queryKey: loyalty.queries.points().queryKey }).
  • No mutations. The module has no redeem or join method.

See also

On this page