Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions web/apps/client-demo/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Updates from './pages/Updates';
import Organization from './pages/Organization';
import Settings from './pages/Settings';
import General from './pages/settings/General';
import Preferences from './pages/settings/Preferences';

function Router() {
return (
Expand All @@ -24,6 +25,7 @@ function Router() {
<Route path="/organizations/:orgId" element={<Organization />} />
<Route path="/:orgId/settings" element={<Settings />}>
<Route path="general" element={<General />} />
<Route path="preferences" element={<Preferences />} />
</Route>
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
Expand Down
3 changes: 2 additions & 1 deletion web/apps/client-demo/src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Outlet, useParams, useLocation, Navigate } from 'react-router-dom';
import { useFrontier } from '@raystack/frontier/react';

const NAV_ITEMS = [
{ label: 'General', path: 'general' }
{ label: 'General', path: 'general' },
{ label: 'Preferences', path: 'preferences' }
];

export default function Settings() {
Expand Down
5 changes: 5 additions & 0 deletions web/apps/client-demo/src/pages/settings/Preferences.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PreferencesView } from '@raystack/frontier/react';

export default function Preferences() {
return <PreferencesView />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
}

.content {
max-width: 1512px;
width: 100%;
}
2 changes: 1 addition & 1 deletion web/sdk/react/components/view-container/view-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface ViewContainerProps extends ComponentProps<typeof Flex> {

export function ViewContainer({ children, contentProps, className, ...props }: ViewContainerProps) {
return (
<Flex direction="column" className={cx(styles.container, className)} {...props}>
<Flex direction="column" align="center" className={cx(styles.container, className)} {...props}>
<Flex direction="column" gap={7} {...contentProps} className={cx(styles.content, contentProps?.className)}>
{children}
</Flex>
Expand Down
1 change: 1 addition & 0 deletions web/sdk/react/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export { ImageUpload } from './components/image-upload';
export { ViewContainer } from './components/view-container';
export { ViewHeader } from './components/view-header';
export { GeneralView } from './views-new/general';
export { PreferencesView, PreferenceRow } from './views-new/preferences';

export type {
FrontierClientOptions,
Expand Down
46 changes: 46 additions & 0 deletions web/sdk/react/views-new/preferences/components/preference-row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ComponentProps } from 'react';
import { Flex, Text, Skeleton } from '@raystack/apsara-v1';
import styles from './preferences-row.module.css';
import { cx } from 'class-variance-authority';

export interface PreferenceRowProps extends ComponentProps<typeof Flex> {
title: string;
description: string;
isLoading?: boolean;
contentProps?: ComponentProps<typeof Flex>;
}

export function PreferenceRow({
title,
description,
isLoading,
children,
className,
contentProps,
...props
}: PreferenceRowProps) {
return (
<Flex align="center" gap={9} className={cx(styles.row, className)} {...props}>
<Flex direction="column" gap={3} className={styles.content}>
{isLoading ? (
<>
<Skeleton width="20%" height={24} />
<Skeleton width="40%" height={16} />
</>
) : (
<>
<Text size="large" weight="medium">
{title}
</Text>
<Text size="small" variant="secondary">
{description}
</Text>
</>
)}
</Flex>
<Flex {...contentProps} className={cx(styles.children, contentProps?.className)}>
{isLoading ? <Skeleton width={135} height={33} /> : children}
</Flex>
</Flex>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.row {
padding: var(--rs-space-7) 0;
border-bottom: 1px dashed var(--rs-color-border-base-primary);
}
.content {
flex: 1;
}
.children {
min-width: 135px;
}
2 changes: 2 additions & 0 deletions web/sdk/react/views-new/preferences/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { PreferencesView } from './preferences-view';
export { PreferenceRow } from './components/preference-row';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.selectTrigger {
width: 100%;
}
80 changes: 80 additions & 0 deletions web/sdk/react/views-new/preferences/preferences-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Flex, Select, Skeleton } from '@raystack/apsara-v1';
import { SunIcon, MoonIcon, GearIcon } from '@radix-ui/react-icons';
import { BellIcon, BellSlashIcon } from '@raystack/apsara-v1/icons';
import { ViewContainer } from '~/react/components/view-container';
import { ViewHeader } from '~/react/components/view-header';
import { usePreferences } from '~/react/hooks/usePreferences';
import { PREFERENCE_OPTIONS } from '~/react/utils/constants';
import { PreferenceRow } from './components/preference-row';
import { useTheme } from '@raystack/apsara';
import styles from './preferences-view.module.css';

export function PreferencesView() {
const { theme, setTheme } = useTheme();
const { preferences, isLoading, isFetching, updatePreferences } =
usePreferences({});
console.log(theme);

const newsletterValue =
preferences?.[PREFERENCE_OPTIONS.NEWSLETTER]?.value ?? 'false';

return (
<ViewContainer>
<ViewHeader
title="Preferences"
description="Manage members for this domain."
/>
<Flex direction="column">
<PreferenceRow
title="Theme"
description="Customise your interface color scheme."
>
<Select defaultValue={theme} onValueChange={setTheme}>
<Select.Trigger className={styles.selectTrigger}>
<Select.Value placeholder="Theme" />
</Select.Trigger>
<Select.Content>
<Select.Item value="light" leadingIcon={<SunIcon />}>
Light
</Select.Item>
<Select.Item value="dark" leadingIcon={<MoonIcon />}>
Dark
</Select.Item>
<Select.Item value="system" leadingIcon={<GearIcon />}>
System
</Select.Item>
</Select.Content>
</Select>
</PreferenceRow>

<PreferenceRow
title="Updates, News & Events"
description="Stay informed on new features, improvements, and key updates."
isLoading={isFetching}
>
<Select
defaultValue={newsletterValue}
onValueChange={value => {
updatePreferences([
{ name: PREFERENCE_OPTIONS.NEWSLETTER, value }
]);
}}
disabled={isLoading}
>
<Select.Trigger className={styles.selectTrigger}>
<Select.Value placeholder="Newsletter" />
</Select.Trigger>
<Select.Content>
<Select.Item value="true" leadingIcon={<BellIcon />}>
Subscribed
</Select.Item>
<Select.Item value="false" leadingIcon={<BellSlashIcon />}>
Unsubscribed
</Select.Item>
</Select.Content>
</Select>
</PreferenceRow>
</Flex>
</ViewContainer>
);
}