Profile, Settings
The signed-in customer's profile and account settings pages, built from Salla's ready-made web components and refused to guests.
import { Profile, ProfilePage, profileLoader, ProfilePageProps, Settings, SettingsPage, settingsLoader, SettingsPageProps } from '@salla.sa/twilight-theme-engine/routes/account';In plain words
The pages under /account belong to a signed-in customer. /account/profile edits their name, email and phone, and /account/settings holds their preferences. Both forms are Salla's ready-made web components, so these loaders only check that someone is signed in and set the title.
Every account page renders inside the account layout, next to the customer menu. "Customer account" on Built-in pages opens the profile page; as a guest you see what the engine shows a visitor who is not signed in.
Signature
const Profile: {
readonly id: 'customer.profile';
readonly loader: (
ctx: { locale?: string },
extend?: (data: ProfilePageProps, ctx: { params: {} }) => Record<string, unknown> | Promise<Record<string, unknown>>
) => Promise<ProfilePageProps>;
readonly head: (ctx: TwilightContext, data: ProfilePageProps) => HeadDescriptor;
readonly Component: React.LazyExoticComponent<(props: ProfilePageProps) => JSX.Element>;
};
const Settings: { id: 'customer.settings'; loader; head; Component }; // same shape, SettingsPageProps
const ProfilePage: typeof Profile.Component;
const SettingsPage: typeof Settings.Component;
function profileLoader(ctx: { locale: string }): Promise<ProfilePageProps>; // locale required, unused
function settingsLoader(ctx: { locale: string }): Promise<SettingsPageProps>;
interface ProfilePageProps { page: Page } // { title, slug: 'profile' }
interface SettingsPageProps { page: Page } // { title, slug: 'settings' }Example
import { createFileRoute } from '@tanstack/react-router';
import { Profile } from '@salla.sa/twilight-theme-engine/routes/account';
import type { ProfilePageProps } from '@salla.sa/twilight-theme-engine/routes/account';
import { CustomerPageSkeleton } from '@salla.sa/twilight-theme-engine/skeleton';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';
export const Route = createFileRoute('/{-$locale}/account/profile')({
loader: ({ params }): Promise<ProfilePageProps> => Profile.loader({ locale: params.locale }),
head: withHead(Profile),
pendingComponent: () => <CustomerPageSkeleton />,
component: ProfileComponent,
});
function ProfileComponent() {
const data: ProfilePageProps = Route.useLoaderData();
return <Profile.Component {...data} />;
}
How it behaves
Both loaders read
authTokenfrom the router's request context (the customer's token cookie). Without one theythrow unauthorized(), and the router's default error component shows a 401 page with no action button. They make no API request.ProfilePagerenders Salla's user-profile, verify and user-settings web components between the slotscustomer:profile.start,customer:profile.form.start,customer:profile.form.endandcustomer:profile.end.SettingsPagerenders the user-settings component betweencustomer:settings.startandcustomer:settings.end.Account routes nest under the engine's
/{-$locale}/accountlayout route, which rendersCustomerLayoutwith thepageof the deepest loader that returned one. While it is pending it shows the component registered under the keyaccount:layout-pending, orCustomerLayoutSkeletonwhen none is.headsets the title and hreflang alternates only.All account components are lazy.
SettingsPagePropsis exported here, not by the/routesbarrel.
Gotchas
On every
/account/*page,useRouteId()returns the router's own id (/{-$locale}/account/profile), notcustomer.profile: the engine's id map lists/{-$locale}/profile,/{-$locale}/ordersand so on, withoutaccount(TANSTACK_ROUTE_ID_MAPin packages/theme-engine/src/tanstack/router.tsx).useIsCustomer()is thereforefalseon these pages.
Related
The account area's frame: a breadcrumb band, the account menu sidebar and the page title around each account page.
notFound, redirect, unauthorizedThrow helpers for route loaders: stop and show the not-found page, send the visitor to another address, or refuse a guest.
useIsHome, useIsProduct…Seven yes-or-no hooks that tell a component which kind of store page is showing: home, product, cart, account, blog, brands or search.
OrdersThe signed-in customer's order history, optionally filtered by status, as a table that loads more orders on request.
Source and docs
- Engine source:
packages/theme-engine/src/routes/account/profile/index.tsx