2.21.5 (#417)
* refactor: streamline sign-in and sign-up methods containers for improved conditional rendering - Updated SignInMethodsContainer and SignUpMethodsContainer to conditionally render the separator and "or continue with" text only when applicable authentication methods are available. - Enhanced code readability by removing redundant div elements and improving the structure of conditional rendering. * refactor: enhance UI components with improved styling and structure - Updated PlanIntervalSwitcher to include hover effects and adjusted button size for better user interaction. - Refined PersonalAccountDropdown by removing unnecessary animation classes for cleaner code. - Modified Footer component to standardize padding across different screen sizes. - Adjusted Pill component's height and padding for a more consistent appearance. * refactor: enhance admin members and memberships tables with date rendering and sorting adjustments - Removed User ID column from both AdminMembersTable and AdminMembershipsTable for a cleaner interface. - Added date rendering functionality for Created At and Updated At columns, displaying time in a user-friendly format. - Disabled sorting for Name, Email, Role, Created At, and Updated At columns to improve usability. * fix: update account linking messages and redirect logic - Changed the success message for account linking to indicate that a request has been sent and to prompt the user to wait. - Added a redirect path to the PersonalAccountSettingsContainer for improved navigation after account linking. - Removed the unused useUnlinkIdentity hook to clean up the codebase.
This commit is contained in:
committed by
GitHub
parent
db4aa6007e
commit
a78da16790
@@ -123,7 +123,7 @@
|
|||||||
"linkEmailPasswordSuccess": "Email and password linked",
|
"linkEmailPasswordSuccess": "Email and password linked",
|
||||||
"linkEmailPasswordError": "Failed to link email and password",
|
"linkEmailPasswordError": "Failed to link email and password",
|
||||||
"linkingAccount": "Linking account...",
|
"linkingAccount": "Linking account...",
|
||||||
"accountLinked": "Account linked",
|
"accountLinked": "Account linking request sent. Please wait...",
|
||||||
"unlinkAccount": "Unlink Account",
|
"unlinkAccount": "Unlink Account",
|
||||||
"failedToLinkAccount": "Failed to link account",
|
"failedToLinkAccount": "Failed to link account",
|
||||||
"availableMethods": "Available Methods",
|
"availableMethods": "Available Methods",
|
||||||
|
|||||||
@@ -417,7 +417,11 @@ function PlanIntervalSwitcher(
|
|||||||
}>,
|
}>,
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div className={'flex gap-x-1 rounded-full border'}>
|
<div
|
||||||
|
className={
|
||||||
|
'hover:border-border flex gap-x-1 rounded-full border border-transparent transition-colors'
|
||||||
|
}
|
||||||
|
>
|
||||||
{props.intervals.map((plan, index) => {
|
{props.intervals.map((plan, index) => {
|
||||||
const selected = plan === props.interval;
|
const selected = plan === props.interval;
|
||||||
|
|
||||||
@@ -434,13 +438,14 @@ function PlanIntervalSwitcher(
|
|||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
key={plan}
|
key={plan}
|
||||||
|
size={'sm'}
|
||||||
variant={selected ? 'secondary' : 'ghost'}
|
variant={selected ? 'secondary' : 'ghost'}
|
||||||
className={className}
|
className={className}
|
||||||
onClick={() => props.setInterval(plan)}
|
onClick={() => props.setInterval(plan)}
|
||||||
>
|
>
|
||||||
<span className={'flex items-center'}>
|
<span className={'flex items-center'}>
|
||||||
<CheckCircle
|
<CheckCircle
|
||||||
className={cn('animate-in fade-in zoom-in-95 h-3.5', {
|
className={cn('animate-in fade-in zoom-in-95 h-3', {
|
||||||
hidden: !selected,
|
hidden: !selected,
|
||||||
'slide-in-from-left-4': index === 0,
|
'slide-in-from-left-4': index === 0,
|
||||||
'slide-in-from-right-4': index === props.intervals.length - 1,
|
'slide-in-from-right-4': index === props.intervals.length - 1,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ export function PersonalAccountDropdown({
|
|||||||
aria-label="Open your profile menu"
|
aria-label="Open your profile menu"
|
||||||
data-test={'account-dropdown-trigger'}
|
data-test={'account-dropdown-trigger'}
|
||||||
className={cn(
|
className={cn(
|
||||||
'animate-in group/trigger fade-in focus:outline-primary flex cursor-pointer items-center group-data-[minimized=true]/sidebar:px-0',
|
'group/trigger fade-in focus:outline-primary flex cursor-pointer items-center group-data-[minimized=true]/sidebar:px-0',
|
||||||
className ?? '',
|
className ?? '',
|
||||||
{
|
{
|
||||||
['active:bg-secondary/50 items-center gap-4 rounded-md' +
|
['active:bg-secondary/50 items-center gap-4 rounded-md' +
|
||||||
@@ -108,7 +108,7 @@ export function PersonalAccountDropdown({
|
|||||||
<If condition={showProfileName}>
|
<If condition={showProfileName}>
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
'fade-in animate-in flex w-full flex-col truncate text-left group-data-[minimized=true]/sidebar:hidden'
|
'fade-in flex w-full flex-col truncate text-left group-data-[minimized=true]/sidebar:hidden'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ export function PersonalAccountSettingsContainer(
|
|||||||
enabled={props.features.enableAccountLinking}
|
enabled={props.features.enableAccountLinking}
|
||||||
showEmailOption={props.features.showLinkEmailOption}
|
showEmailOption={props.features.showLinkEmailOption}
|
||||||
showPasswordOption={props.features.enablePasswordUpdate}
|
showPasswordOption={props.features.enablePasswordUpdate}
|
||||||
|
redirectTo={'/home/settings'}
|
||||||
/>
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -17,12 +17,9 @@ export function AdminMembersTable(props: { members: Memberships[] }) {
|
|||||||
|
|
||||||
function getColumns(): ColumnDef<Memberships>[] {
|
function getColumns(): ColumnDef<Memberships>[] {
|
||||||
return [
|
return [
|
||||||
{
|
|
||||||
header: 'User ID',
|
|
||||||
accessorKey: 'user_id',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
|
enableSorting: false,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const name = row.original.name ?? row.original.email;
|
const name = row.original.name ?? row.original.email;
|
||||||
|
|
||||||
@@ -48,9 +45,11 @@ function getColumns(): ColumnDef<Memberships>[] {
|
|||||||
{
|
{
|
||||||
header: 'Email',
|
header: 'Email',
|
||||||
accessorKey: 'email',
|
accessorKey: 'email',
|
||||||
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Role',
|
header: 'Role',
|
||||||
|
enableSorting: false,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return row.original.role;
|
return row.original.role;
|
||||||
},
|
},
|
||||||
@@ -58,10 +57,22 @@ function getColumns(): ColumnDef<Memberships>[] {
|
|||||||
{
|
{
|
||||||
header: 'Created At',
|
header: 'Created At',
|
||||||
accessorKey: 'created_at',
|
accessorKey: 'created_at',
|
||||||
|
enableSorting: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return renderDate(row.original.created_at);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Updated At',
|
header: 'Updated At',
|
||||||
accessorKey: 'updated_at',
|
accessorKey: 'updated_at',
|
||||||
|
enableSorting: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return renderDate(row.original.updated_at);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDate(date: string) {
|
||||||
|
return <span className={'text-xs'}>{new Date(date).toTimeString()}</span>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,12 +20,9 @@ export function AdminMembershipsTable(props: { memberships: Membership[] }) {
|
|||||||
|
|
||||||
function getColumns(): ColumnDef<Membership>[] {
|
function getColumns(): ColumnDef<Membership>[] {
|
||||||
return [
|
return [
|
||||||
{
|
|
||||||
header: 'User ID',
|
|
||||||
accessorKey: 'user_id',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
header: 'Team',
|
header: 'Team',
|
||||||
|
enableSorting: false,
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
@@ -40,14 +37,27 @@ function getColumns(): ColumnDef<Membership>[] {
|
|||||||
{
|
{
|
||||||
header: 'Role',
|
header: 'Role',
|
||||||
accessorKey: 'account_role',
|
accessorKey: 'account_role',
|
||||||
|
enableSorting: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Created At',
|
header: 'Created At',
|
||||||
accessorKey: 'created_at',
|
accessorKey: 'created_at',
|
||||||
|
enableSorting: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return renderDate(row.original.created_at);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: 'Updated At',
|
header: 'Updated At',
|
||||||
accessorKey: 'updated_at',
|
accessorKey: 'updated_at',
|
||||||
|
enableSorting: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
return renderDate(row.original.updated_at);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderDate(date: string) {
|
||||||
|
return <span className={'text-xs'}>{new Date(date).toTimeString()}</span>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -72,17 +72,25 @@ export function SignInMethodsContainer(props: {
|
|||||||
</If>
|
</If>
|
||||||
|
|
||||||
<If condition={props.providers.oAuth.length}>
|
<If condition={props.providers.oAuth.length}>
|
||||||
<div className="relative">
|
<If
|
||||||
<div className="absolute inset-0 flex items-center">
|
condition={
|
||||||
<Separator />
|
props.providers.magicLink ||
|
||||||
</div>
|
props.providers.password ||
|
||||||
|
props.providers.otp
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute inset-0 flex items-center">
|
||||||
|
<Separator />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="relative flex justify-center text-xs uppercase">
|
<div className="relative flex justify-center text-xs uppercase">
|
||||||
<span className="bg-background text-muted-foreground px-2">
|
<span className="bg-background text-muted-foreground px-2">
|
||||||
<Trans i18nKey="auth:orContinueWith" />
|
<Trans i18nKey="auth:orContinueWith" />
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</If>
|
||||||
|
|
||||||
<OauthProviders
|
<OauthProviders
|
||||||
enabledProviders={props.providers.oAuth}
|
enabledProviders={props.providers.oAuth}
|
||||||
|
|||||||
@@ -64,17 +64,25 @@ export function SignUpMethodsContainer(props: {
|
|||||||
</If>
|
</If>
|
||||||
|
|
||||||
<If condition={props.providers.oAuth.length}>
|
<If condition={props.providers.oAuth.length}>
|
||||||
<div className="relative">
|
<If
|
||||||
<div className="absolute inset-0 flex items-center">
|
condition={
|
||||||
<Separator />
|
props.providers.magicLink ||
|
||||||
</div>
|
props.providers.password ||
|
||||||
|
props.providers.otp
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute inset-0 flex items-center">
|
||||||
|
<Separator />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="relative flex justify-center text-xs uppercase">
|
<div className="relative flex justify-center text-xs uppercase">
|
||||||
<span className="bg-background text-muted-foreground px-2">
|
<span className="bg-background text-muted-foreground px-2">
|
||||||
<Trans i18nKey="auth:orContinueWith" />
|
<Trans i18nKey="auth:orContinueWith" />
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</If>
|
||||||
|
|
||||||
<OauthProviders
|
<OauthProviders
|
||||||
enabledProviders={props.providers.oAuth}
|
enabledProviders={props.providers.oAuth}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
import type { UserIdentity } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
import { useMutation } from '@tanstack/react-query';
|
|
||||||
|
|
||||||
import { useSupabase } from './use-supabase';
|
|
||||||
|
|
||||||
export function useUnlinkIdentity() {
|
|
||||||
const client = useSupabase();
|
|
||||||
const mutationKey = ['auth', 'unlink-identity'];
|
|
||||||
|
|
||||||
const mutationFn = async (identity: UserIdentity) => {
|
|
||||||
const { error } = await client.auth.unlinkIdentity(identity);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
throw error.message ?? error;
|
|
||||||
}
|
|
||||||
|
|
||||||
await client.auth.refreshSession();
|
|
||||||
};
|
|
||||||
|
|
||||||
return useMutation({ mutationKey, mutationFn });
|
|
||||||
}
|
|
||||||
@@ -26,7 +26,7 @@ export const Footer: React.FC<FooterProps> = ({
|
|||||||
return (
|
return (
|
||||||
<footer
|
<footer
|
||||||
className={cn(
|
className={cn(
|
||||||
'site-footer bg-muted/20 relative mt-auto w-full py-8 2xl:py-20',
|
'site-footer bg-muted/20 relative mt-auto w-full py-8 xl:py-16 2xl:py-20',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const Pill: React.FC<
|
|||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-muted/50 flex min-h-10 items-center gap-x-1.5 rounded-full border px-2 py-1 text-center text-sm font-medium text-transparent',
|
'flex min-h-9 items-center gap-x-1.5 rounded-full border px-1.5 py-1 text-center text-sm font-medium text-transparent',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -22,7 +22,7 @@ export const Pill: React.FC<
|
|||||||
{props.label && (
|
{props.label && (
|
||||||
<span
|
<span
|
||||||
className={
|
className={
|
||||||
'text-primary-foreground bg-primary rounded-2xl border px-1.5 py-0.5 text-xs font-bold tracking-tight'
|
'text-primary-foreground bg-primary rounded-2xl border px-1.5 py-1.5 text-xs font-bold tracking-tight'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{props.label}
|
{props.label}
|
||||||
|
|||||||
Reference in New Issue
Block a user