diff --git a/apps/web/app/(marketing)/_components/site-header-account-section.tsx b/apps/web/app/(marketing)/_components/site-header-account-section.tsx index 9b91f4f8a..5e1753c30 100644 --- a/apps/web/app/(marketing)/_components/site-header-account-section.tsx +++ b/apps/web/app/(marketing)/_components/site-header-account-section.tsx @@ -26,9 +26,7 @@ export function SiteHeaderAccountSection( return ; } - return ( - - ); + return ; } function SuspendedPersonalAccountDropdown(props: { session: Session | null }) { diff --git a/apps/web/package.json b/apps/web/package.json index 78ed89d02..c6f849c50 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -82,4 +82,4 @@ ] }, "prettier": "@kit/prettier-config" -} \ No newline at end of file +} diff --git a/apps/web/public/locales/en/admin.json b/apps/web/public/locales/en/admin.json index 9e26dfeeb..0967ef424 100644 --- a/apps/web/public/locales/en/admin.json +++ b/apps/web/public/locales/en/admin.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/apps/web/public/locales/en/marketing.json b/apps/web/public/locales/en/marketing.json index 9e26dfeeb..0967ef424 100644 --- a/apps/web/public/locales/en/marketing.json +++ b/apps/web/public/locales/en/marketing.json @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/packages/features/accounts/src/server/personal-accounts-server-actions.ts b/packages/features/accounts/src/server/personal-accounts-server-actions.ts index 9722f5e70..66e18f3f0 100644 --- a/packages/features/accounts/src/server/personal-accounts-server-actions.ts +++ b/packages/features/accounts/src/server/personal-accounts-server-actions.ts @@ -33,9 +33,15 @@ export async function deletePersonalAccountAction(formData: FormData) { `Deleting personal account...`, ); - const deleteAccountResponse = await service.deletePersonalAccount({ - userId, - }); + const deleteAccountResponse = await service.deletePersonalAccount( + getSupabaseServerActionClient({ admin: true }), + { + userId, + }, + ); + + // + // also delete any associated data and subscriptions if (deleteAccountResponse.error) { Logger.error( diff --git a/packages/features/accounts/src/server/services/personal-accounts.service.ts b/packages/features/accounts/src/server/services/personal-accounts.service.ts index 808ed218f..8d4e9a404 100644 --- a/packages/features/accounts/src/server/services/personal-accounts.service.ts +++ b/packages/features/accounts/src/server/services/personal-accounts.service.ts @@ -13,5 +13,10 @@ import { Database } from '@kit/supabase/database'; export class PersonalAccountsService { constructor(private readonly client: SupabaseClient) {} - async deletePersonalAccount(param: { userId: string }) {} + async deletePersonalAccount( + adminClient: SupabaseClient, + params: { userId: string }, + ) { + return adminClient.auth.admin.deleteUser(params.userId); + } } diff --git a/packages/ui/src/makerkit/language-dropdown-switcher.tsx b/packages/ui/src/makerkit/language-dropdown-switcher.tsx index 2a67ce30b..275a88457 100644 --- a/packages/ui/src/makerkit/language-dropdown-switcher.tsx +++ b/packages/ui/src/makerkit/language-dropdown-switcher.tsx @@ -2,9 +2,9 @@ import { useCallback, useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; +import { useRouter } from 'next/navigation'; -import useRefresh from '@kit/shared/hooks/use-refresh'; +import { useTranslation } from 'react-i18next'; import { Select, @@ -14,11 +14,11 @@ import { SelectValue, } from '../shadcn/select'; -const LanguageDropdownSwitcher: React.FC<{ +export const LanguageDropdownSwitcher: React.FC<{ onChange?: (locale: string) => unknown; }> = ({ onChange }) => { const { i18n } = useTranslation(); - const refresh = useRefresh(); + const router = useRouter(); const { language: currentLanguage, options } = i18n; @@ -43,9 +43,10 @@ const LanguageDropdownSwitcher: React.FC<{ } await i18n.changeLanguage(locale); - return refresh(); + + return router.refresh(); }, - [i18n, onChange, refresh], + [i18n, onChange, router], ); return ( @@ -77,5 +78,3 @@ const LanguageDropdownSwitcher: React.FC<{ function capitalize(lang: string) { return lang.slice(0, 1).toUpperCase() + lang.slice(1); } - -export default LanguageDropdownSwitcher; diff --git a/packages/ui/src/shadcn/command.tsx b/packages/ui/src/shadcn/command.tsx index 279c76540..e89cae4df 100644 --- a/packages/ui/src/shadcn/command.tsx +++ b/packages/ui/src/shadcn/command.tsx @@ -42,6 +42,7 @@ const CommandInput = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( + // eslint-disable-next-line react/no-unknown-property
; - } - | { - type: ActionType['DISMISS_TOAST']; - toastId?: ToasterToast['id']; - } - | { - type: ActionType['REMOVE_TOAST']; - toastId?: ToasterToast['id']; - }; - -interface State { - toasts: ToasterToast[]; -} - -const toastTimeouts = new Map>(); - -const addToRemoveQueue = (toastId: string) => { - if (toastTimeouts.has(toastId)) { - return; - } - - const timeout = setTimeout(() => { - toastTimeouts.delete(toastId); - dispatch({ - type: 'REMOVE_TOAST', - toastId: toastId, - }); - }, TOAST_REMOVE_DELAY); - - toastTimeouts.set(toastId, timeout); -}; - -export const reducer = (state: State, action: Action): State => { - switch (action.type) { - case 'ADD_TOAST': - return { - ...state, - toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT), - }; - - case 'UPDATE_TOAST': - return { - ...state, - toasts: state.toasts.map((t) => - t.id === action.toast.id ? { ...t, ...action.toast } : t, - ), - }; - - case 'DISMISS_TOAST': { - const { toastId } = action; - - // ! Side effects ! - This could be extracted into a dismissToast() action, - // but I'll keep it here for simplicity - if (toastId) { - addToRemoveQueue(toastId); - } else { - state.toasts.forEach((toast) => { - addToRemoveQueue(toast.id); - }); - } - - return { - ...state, - toasts: state.toasts.map((t) => - t.id === toastId || toastId === undefined - ? { - ...t, - open: false, - } - : t, - ), - }; - } - case 'REMOVE_TOAST': - if (action.toastId === undefined) { - return { - ...state, - toasts: [], - }; - } - return { - ...state, - toasts: state.toasts.filter((t) => t.id !== action.toastId), - }; - } -}; - -const listeners: ((state: State) => void)[] = []; - -let memoryState: State = { toasts: [] }; - -function dispatch(action: Action) { - memoryState = reducer(memoryState, action); - listeners.forEach((listener) => { - listener(memoryState); - }); -} - -type Toast = Omit; - -function toast({ ...props }: Toast) { - const id = genId(); - - const update = (props: ToasterToast) => - dispatch({ - type: 'UPDATE_TOAST', - toast: { ...props, id }, - }); - const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id }); - - dispatch({ - type: 'ADD_TOAST', - toast: { - ...props, - id, - open: true, - onOpenChange: (open) => { - if (!open) dismiss(); - }, - }, - }); - - return { - id: id, - dismiss, - update, - }; -} - -function useToast() { - const [state, setState] = React.useState(memoryState); - - React.useEffect(() => { - listeners.push(setState); - return () => { - const index = listeners.indexOf(setState); - if (index > -1) { - listeners.splice(index, 1); - } - }; - }, [state]); - - return { - ...state, - toast, - dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }), - }; -} - -export { useToast, toast }; diff --git a/supabase/migrations/20221215192558_schema.sql b/supabase/migrations/20221215192558_schema.sql index 557b4dd03..9f513c636 100644 --- a/supabase/migrations/20221215192558_schema.sql +++ b/supabase/migrations/20221215192558_schema.sql @@ -671,7 +671,7 @@ create table if not exists id serial primary key, email varchar(255) not null, account_id uuid references public.accounts (id) on delete cascade not null, - invited_by uuid references auth.users not null, + invited_by uuid references auth.users on delete cascade not null, role public.account_role not null, invite_token varchar(255) unique not null, created_at timestamp default current_timestamp not null,