Deps Update + Table improvements (#351)

* fix: enhance DataTable pagination examples and improve display logic

- Added a note in the DataTableStory component to clarify that examples show only the first page of data for demonstration purposes.
- Adjusted pagination examples to reflect smaller datasets, changing the displayed data slices for better clarity and testing.
- Updated the Pagination component to calculate and display the current record range more accurately based on the current page index and size.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@supabase/supabase-js` from `2.55.0` to `2.57.0` for enhanced functionality and performance.
- Bumped `@tanstack/react-query` from `5.85.5` to `5.85.9` to incorporate the latest improvements.
- Updated `ai` from `5.0.28` to `5.0.30` for better performance.
- Incremented `nodemailer` from `7.0.5` to `7.0.6` for stability.
- Updated `typescript-eslint` from `8.41.0` to `8.42.0` for improved type definitions and linting capabilities.
- Adjusted various package dependencies across multiple components to ensure compatibility and stability.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@ai-sdk/openai` from `2.0.23` to `2.0.24` for enhanced functionality.
- Bumped `@tanstack/react-query` from `5.85.9` to `5.86.0` to incorporate the latest improvements.
- Updated `ai` from `5.0.30` to `5.0.33` for better performance.
- Incremented `@types/node` from `24.3.0` to `24.3.1` for type safety enhancements.
- Updated `dotenv` from `17.2.1` to `17.2.2` for stability.
- Adjusted `tailwindcss` and related packages to `4.1.13` for improved styling capabilities.
- Updated `react-i18next` from `15.7.3` to `15.7.3` to include the latest localization fixes.
- Incremented `@sentry/nextjs` from `10.8.0` to `10.10.0` for enhanced monitoring features.
- Updated various package dependencies across multiple components to ensure compatibility and stability.

* fix(config): conditionally disable `devIndicators` in CI environment

* feat(settings): encapsulate danger zone actions in a styled card component

- Introduced a new `DangerZoneCard` component to enhance the visual presentation of danger zone actions in the team account settings.
- Updated `TeamAccountDangerZone` to wrap deletion and leave actions within the `DangerZoneCard` for improved user experience.
- Removed redundant card structure from `TeamAccountSettingsContainer` to streamline the component hierarchy.

* fix(e2e): improve admin account tests for response handling and visibility checks

- Enhanced the admin test suite by adding a check for the POST request method when waiting for the response from the `/admin/accounts` endpoint.
- Reduced wait times in the `filterAccounts` function for improved test performance.
- Updated the `selectAccount` function to ensure the account link is visible before clicking, enhancing reliability in the test flow.

* chore(dependencies): update package versions for improved compatibility

- Upgraded `@supabase/supabase-js` from `2.57.0` to `2.57.2` for enhanced functionality and performance.
- Bumped `@tanstack/react-query` from `5.86.0` to `5.87.1` to incorporate the latest improvements.
- Updated `i18next` from `25.5.1` to `25.5.2` for better localization support.
- Incremented `eslint` from `9.34.0` to `9.35.0` for improved linting capabilities.
- Adjusted various package dependencies across multiple components to ensure compatibility and stability.

* feat(admin): enhance user ban and reactivation actions with success handling

- Updated `AdminBanUserDialog` and `AdminReactivateUserDialog` components to handle success states based on the results of the respective actions.
- Modified `banUserAction` and `reactivateUserAction` to return success status and log errors if the actions fail.
- Introduced `revalidatePage` function to refresh the user account page after banning or reactivating a user.
- Improved error handling in the dialogs to provide better feedback to the admin user.

* feat(admin): refactor user ban and reactivation dialogs for improved structure and error handling

- Introduced `BanUserForm` and `ReactivateUserForm` components to encapsulate form logic within the respective dialogs, enhancing readability and maintainability.
- Updated the `AdminBanUserDialog` and `AdminReactivateUserDialog` components to utilize the new form components, streamlining the user interface.
- Enhanced error handling to provide clearer feedback to the admin user during ban and reactivation actions.
- Removed unnecessary revalidation calls in the server actions to optimize performance and maintain clarity in the action flow.
- Added `@types/react-dom` dependency for improved type definitions.

* refactor(admin): streamline user dialogs and server actions for improved clarity

- Removed unnecessary `useRouter` imports from `AdminBanUserDialog` and `AdminReactivateUserDialog` components to simplify the code.
- Updated `revalidateAdmin` function calls to use `revalidatePath` with specific paths, enhancing clarity in the server actions.
- Ensured that the user dialogs maintain a clean structure while focusing on form logic and error handling.
This commit is contained in:
Giancarlo Buomprisco
2025-09-06 17:30:09 +07:00
committed by GitHub
parent b3acbbe801
commit 9fae142f2d
37 changed files with 2293 additions and 2313 deletions

View File

@@ -1248,6 +1248,16 @@ export function DataTableStory() {
</CardHeader>
<CardContent>
<div className="space-y-6">
{/* Note about pagination examples */}
<div className="rounded-lg border border-amber-200 bg-amber-50 p-3">
<p className="text-sm text-amber-800">
<strong>Note:</strong> These examples show only the first page
of data for demonstration. In a real application, pagination
would fetch different pages from your backend based on the
current page index.
</p>
</div>
{/* Small dataset with pagination */}
<div className="space-y-3">
<h4 className="text-sm font-semibold">
@@ -1267,7 +1277,7 @@ export function DataTableStory() {
),
},
]}
data={data.slice(0, 15)}
data={data.slice(0, 5)}
pageSize={5}
pageCount={3}
getRowId={(row) => row.id}
@@ -1303,7 +1313,7 @@ export function DataTableStory() {
},
},
]}
data={data.slice(0, 30)}
data={data.slice(0, 10)}
pageSize={10}
pageCount={3}
getRowId={(row) => row.id}
@@ -1416,7 +1426,7 @@ export function DataTableStory() {
size: 80,
},
]}
data={data.slice(0, 50)}
data={data.slice(0, 15)}
pageSize={15}
pageCount={Math.ceil(50 / 15)}
getRowId={(row) => row.id}

View File

@@ -8,14 +8,14 @@
"format": "prettier --check --write \"**/*.{js,cjs,mjs,ts,tsx,md,json}\""
},
"dependencies": {
"@ai-sdk/openai": "^2.0.23",
"@ai-sdk/openai": "^2.0.24",
"@faker-js/faker": "^10.0.0",
"@hookform/resolvers": "^5.2.1",
"@tanstack/react-query": "5.85.5",
"ai": "5.0.28",
"@tanstack/react-query": "5.87.1",
"ai": "5.0.33",
"lucide-react": "^0.542.0",
"next": "15.5.2",
"nodemailer": "^7.0.5",
"nodemailer": "^7.0.6",
"react": "19.1.1",
"react-dom": "19.1.1",
"rxjs": "^7.8.2"
@@ -27,8 +27,8 @@
"@kit/shared": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@tailwindcss/postcss": "^4.1.12",
"@types/node": "^24.3.0",
"@tailwindcss/postcss": "^4.1.13",
"@types/node": "^24.3.1",
"@types/nodemailer": "7.0.1",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
@@ -36,7 +36,7 @@
"pino-pretty": "13.0.0",
"react-hook-form": "^7.62.0",
"recharts": "2.15.3",
"tailwindcss": "4.1.12",
"tailwindcss": "4.1.13",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.2",
"zod": "^3.25.74"

View File

@@ -13,8 +13,8 @@
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.55.0",
"@types/node": "^24.3.0",
"dotenv": "17.2.1",
"@types/node": "^24.3.1",
"dotenv": "17.2.2",
"node-html-parser": "^7.0.1",
"totp-generator": "^1.0.0"
}

View File

@@ -126,7 +126,7 @@ test.describe('Admin', () => {
page.waitForResponse(
(response) =>
response.url().includes('/admin/accounts') &&
response.status() === 200,
response.request().method() === 'POST',
),
]);
@@ -172,10 +172,12 @@ test.describe('Admin', () => {
page.waitForResponse(
(response) =>
response.url().includes('/admin/accounts') &&
response.status() === 200,
response.request().method() === 'POST',
),
]);
await page.waitForTimeout(250);
// Verify ban badge is removed
await expect(page.getByText('Banned')).not.toBeVisible();
@@ -388,14 +390,17 @@ async function filterAccounts(page: Page, email: string) {
.fill(email);
await page.keyboard.press('Enter');
await page.waitForTimeout(500);
await page.waitForTimeout(250);
}
async function selectAccount(page: Page, email: string) {
await page
const link = page
.locator('tr', { hasText: email.split('@')[0] })
.locator('a')
.click();
.locator('a');
await expect(link).toBeVisible();
await link.click();
await page.waitForURL(new RegExp(`/admin/accounts/[a-z0-9-]+`));
await page.waitForTimeout(500);

View File

@@ -46,7 +46,10 @@ const config = {
resolveExtensions: ['.ts', '.tsx', '.js', '.jsx'],
resolveAlias: getModulesAliases(),
},
devIndicators: {
devIndicators:
process.env.NEXT_PUBLIC_CI === 'true'
? false
: {
position: 'bottom-right',
},
experimental: {
@@ -131,7 +134,6 @@ function getModulesAliases() {
// exclude the modules that are not needed
const excludeSentry = monitoringProvider !== 'sentry';
const excludeBaselime = monitoringProvider !== 'baselime';
const excludeStripe = billingProvider !== 'stripe';
const excludeNodemailer = mailerProvider !== 'nodemailer';
const excludeTurnstile = !captchaProvider;
@@ -146,10 +148,6 @@ function getModulesAliases() {
aliases['@sentry/nextjs'] = noopPath;
}
if (excludeBaselime) {
aliases['@baselime/react-rum'] = noopPath;
}
if (excludeStripe) {
aliases['stripe'] = noopPath;
aliases['@stripe/stripe-js'] = noopPath;

View File

@@ -54,10 +54,10 @@
"@makerkit/data-loader-supabase-core": "^0.0.10",
"@makerkit/data-loader-supabase-nextjs": "^1.2.5",
"@marsidev/react-turnstile": "^1.3.0",
"@nosecone/next": "1.0.0-beta.10",
"@nosecone/next": "1.0.0-beta.11",
"@radix-ui/react-icons": "^1.3.2",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@tanstack/react-table": "^8.21.3",
"date-fns": "^4.1.0",
"lucide-react": "^0.542.0",
@@ -77,8 +77,8 @@
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@next/bundle-analyzer": "15.5.2",
"@tailwindcss/postcss": "^4.1.12",
"@types/node": "^24.3.0",
"@tailwindcss/postcss": "^4.1.13",
"@types/node": "^24.3.1",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"babel-plugin-react-compiler": "19.1.0-rc.3",
@@ -86,7 +86,7 @@
"pino-pretty": "13.0.0",
"prettier": "^3.6.2",
"supabase": "2.39.2",
"tailwindcss": "4.1.12",
"tailwindcss": "4.1.13",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.2"
},

View File

@@ -17,7 +17,7 @@
"@kit/eslint-config": "workspace:*",
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@types/node": "^24.3.0"
"@types/node": "^24.3.1"
},
"typesVersions": {
"*": {

View File

@@ -26,7 +26,7 @@
"@kit/supabase": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@supabase/supabase-js": "2.57.2",
"@types/react": "19.1.12",
"date-fns": "^4.1.0",
"lucide-react": "^0.542.0",

View File

@@ -15,7 +15,7 @@
"./components": "./src/components/index.ts"
},
"dependencies": {
"@stripe/react-stripe-js": "^3.9.2",
"@stripe/react-stripe-js": "^4.0.0",
"@stripe/stripe-js": "^7.9.0",
"stripe": "^18.5.0"
},

View File

@@ -20,7 +20,7 @@
"@kit/shared": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/wordpress": "workspace:*",
"@types/node": "^24.3.0"
"@types/node": "^24.3.1"
},
"typesVersions": {
"*": {

View File

@@ -26,7 +26,7 @@
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@types/node": "^24.3.0",
"@types/node": "^24.3.1",
"@types/react": "19.1.12",
"react": "19.1.1",
"zod": "^3.25.74"

View File

@@ -20,7 +20,7 @@
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@types/node": "^24.3.0",
"@types/node": "^24.3.1",
"@types/react": "19.1.12",
"wp-types": "^4.68.1"
},

View File

@@ -22,7 +22,7 @@
"@kit/supabase": "workspace:*",
"@kit/team-accounts": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@supabase/supabase-js": "2.57.2",
"zod": "^3.25.74"
},
"typesVersions": {

View File

@@ -34,8 +34,8 @@
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@radix-ui/react-icons": "^1.3.2",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"lucide-react": "^0.542.0",

View File

@@ -20,8 +20,8 @@
"@kit/ui": "workspace:*",
"@makerkit/data-loader-supabase-core": "^0.0.10",
"@makerkit/data-loader-supabase-nextjs": "^1.2.5",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@tanstack/react-table": "^8.21.3",
"@types/react": "19.1.12",
"lucide-react": "^0.542.0",

View File

@@ -37,17 +37,6 @@ export function AdminBanUserDialog(
userId: string;
}>,
) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(BanUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<AlertDialog>
<AlertDialogTrigger asChild>{props.children}</AlertDialogTrigger>
@@ -62,6 +51,25 @@ export function AdminBanUserDialog(
</AlertDialogDescription>
</AlertDialogHeader>
<BanUserForm userId={props.userId} />
</AlertDialogContent>
</AlertDialog>
);
}
function BanUserForm(props: { userId: string }) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(BanUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<Form {...form}>
<form
data-test={'admin-ban-user-form'}
@@ -69,8 +77,9 @@ export function AdminBanUserDialog(
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
await banUserAction(data);
setError(false);
const result = await banUserAction(data);
setError(!result.success);
} catch {
setError(true);
}
@@ -82,8 +91,8 @@ export function AdminBanUserDialog(
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error banning the user. Please check the server
logs to see what went wrong.
There was an error banning the user. Please check the server logs
to see what went wrong.
</AlertDescription>
</Alert>
</If>
@@ -115,19 +124,13 @@ export function AdminBanUserDialog(
/>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={pending}>Cancel</AlertDialogCancel>
<Button
disabled={pending}
type={'submit'}
variant={'destructive'}
>
Ban User
<Button disabled={pending} type={'submit'} variant={'destructive'}>
{pending ? 'Banning...' : 'Ban User'}
</Button>
</AlertDialogFooter>
</form>
</Form>
</AlertDialogContent>
</AlertDialog>
);
}

View File

@@ -37,17 +37,6 @@ export function AdminReactivateUserDialog(
userId: string;
}>,
) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(ReactivateUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<AlertDialog>
<AlertDialogTrigger asChild>{props.children}</AlertDialogTrigger>
@@ -61,6 +50,25 @@ export function AdminReactivateUserDialog(
</AlertDialogDescription>
</AlertDialogHeader>
<ReactivateUserForm userId={props.userId} />
</AlertDialogContent>
</AlertDialog>
);
}
function ReactivateUserForm(props: { userId: string }) {
const [pending, startTransition] = useTransition();
const [error, setError] = useState<boolean>(false);
const form = useForm({
resolver: zodResolver(ReactivateUserSchema),
defaultValues: {
userId: props.userId,
confirmation: '',
},
});
return (
<Form {...form}>
<form
data-test={'admin-reactivate-user-form'}
@@ -68,8 +76,9 @@ export function AdminReactivateUserDialog(
onSubmit={form.handleSubmit((data) => {
startTransition(async () => {
try {
await reactivateUserAction(data);
setError(false);
const result = await reactivateUserAction(data);
setError(!result.success);
} catch {
setError(true);
}
@@ -81,8 +90,8 @@ export function AdminReactivateUserDialog(
<AlertTitle>Error</AlertTitle>
<AlertDescription>
There was an error reactivating the user. Please check the
server logs to see what went wrong.
There was an error reactivating the user. Please check the server
logs to see what went wrong.
</AlertDescription>
</Alert>
</If>
@@ -114,7 +123,7 @@ export function AdminReactivateUserDialog(
/>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogCancel disabled={pending}>Cancel</AlertDialogCancel>
<Button disabled={pending} type={'submit'}>
{pending ? 'Reactivating...' : 'Reactivate User'}
@@ -122,7 +131,5 @@ export function AdminReactivateUserDialog(
</AlertDialogFooter>
</form>
</Form>
</AlertDialogContent>
</AlertDialog>
);
}

View File

@@ -33,7 +33,15 @@ export const banUserAction = adminAction(
logger.info({ userId }, `Super Admin is banning user...`);
await service.banUser(userId);
const { error } = await service.banUser(userId);
if (error) {
logger.error({ error }, `Error banning user`);
return {
success: false,
};
}
logger.info({ userId }, `Super Admin has successfully banned user`);
@@ -61,12 +69,20 @@ export const reactivateUserAction = adminAction(
logger.info({ userId }, `Super Admin is reactivating user...`);
await service.reactivateUser(userId);
const { error } = await service.reactivateUser(userId);
logger.info({ userId }, `Super Admin has successfully reactivated user`);
if (error) {
logger.error({ error }, `Error reactivating user`);
return {
success: false,
};
}
revalidateAdmin();
logger.info({ userId }, `Super Admin has successfully reactivated user`);
return {
success: true,
};
@@ -113,8 +129,6 @@ export const deleteUserAction = adminAction(
logger.info({ userId }, `Super Admin has successfully deleted user`);
revalidateAdmin();
return redirect('/admin/accounts');
},
{
@@ -137,13 +151,13 @@ export const deleteAccountAction = adminAction(
await service.deleteAccount(accountId);
revalidateAdmin();
logger.info(
{ accountId },
`Super Admin has successfully deleted account`,
);
revalidateAdmin();
return redirect('/admin/accounts');
},
{
@@ -180,7 +194,7 @@ export const createUserAction = adminAction(
`Super Admin has successfully created a new user`,
);
revalidateAdmin();
revalidatePath(`/admin/accounts`);
return {
success: true,
@@ -212,8 +226,6 @@ export const resetPasswordAction = adminAction(
`Super Admin has successfully sent password reset email`,
);
revalidateAdmin();
return result;
},
{
@@ -223,7 +235,7 @@ export const resetPasswordAction = adminAction(
);
function revalidateAdmin() {
revalidatePath('/admin', 'layout');
revalidatePath(`/admin/accounts/[id]`, 'page');
}
function getAdminAuthService() {

View File

@@ -153,7 +153,7 @@ class AdminAuthUserService {
}
private async setBanDuration(userId: string, banDuration: string) {
await this.adminClient.auth.admin.updateUserById(userId, {
return this.adminClient.auth.admin.updateUserById(userId, {
ban_duration: banDuration,
});
}

View File

@@ -29,8 +29,8 @@
"@kit/ui": "workspace:*",
"@marsidev/react-turnstile": "^1.3.0",
"@radix-ui/react-icons": "^1.3.2",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@types/react": "19.1.12",
"lucide-react": "^0.542.0",
"next": "15.5.2",

View File

@@ -19,8 +19,8 @@
"@kit/supabase": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@types/react": "19.1.12",
"lucide-react": "^0.542.0",
"react": "19.1.1",

View File

@@ -32,8 +32,8 @@
"@kit/supabase": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@tanstack/react-table": "^8.21.3",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",

View File

@@ -21,6 +21,13 @@ import {
AlertDialogTrigger,
} from '@kit/ui/alert-dialog';
import { Button } from '@kit/ui/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@kit/ui/card';
import {
Form,
FormControl,
@@ -64,7 +71,11 @@ export function TeamAccountDangerZone({
if (userIsPrimaryOwner) {
if (features.enableTeamDeletion) {
return <DeleteTeamContainer account={account} />;
return (
<DangerZoneCard>
<DeleteTeamContainer account={account} />
</DangerZoneCard>
);
}
return;
@@ -72,7 +83,11 @@ export function TeamAccountDangerZone({
// A primary owner can't leave the team account
// but other members can
return <LeaveTeamContainer account={account} />;
return (
<DangerZoneCard>
<LeaveTeamContainer account={account} />
</DangerZoneCard>
);
}
function DeleteTeamContainer(props: {
@@ -411,3 +426,21 @@ function DeleteTeamErrorAlert() {
</div>
);
}
function DangerZoneCard({ children }: React.PropsWithChildren) {
return (
<Card className={'border-destructive border'}>
<CardHeader>
<CardTitle>
<Trans i18nKey={'teams:settings.dangerZone'} />
</CardTitle>
<CardDescription>
<Trans i18nKey={'teams:settings.dangerZoneDescription'} />
</CardDescription>
</CardHeader>
<CardContent>{children}</CardContent>
</Card>
);
}

View File

@@ -67,25 +67,11 @@ export function TeamAccountSettingsContainer(props: {
</CardContent>
</Card>
<Card className={'border-destructive border'}>
<CardHeader>
<CardTitle>
<Trans i18nKey={'teams:settings.dangerZone'} />
</CardTitle>
<CardDescription>
<Trans i18nKey={'teams:settings.dangerZoneDescription'} />
</CardDescription>
</CardHeader>
<CardContent>
<TeamAccountDangerZone
primaryOwnerUserId={props.account.primaryOwnerUserId}
account={props.account}
features={props.features}
/>
</CardContent>
</Card>
</div>
);
}

View File

@@ -20,14 +20,14 @@
"@kit/prettier-config": "workspace:*",
"@kit/shared": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@tanstack/react-query": "5.85.5",
"@tanstack/react-query": "5.87.1",
"next": "15.5.2",
"react": "19.1.1",
"react-dom": "19.1.1",
"react-i18next": "^15.7.3"
},
"dependencies": {
"i18next": "25.4.2",
"i18next": "25.5.2",
"i18next-browser-languagedetector": "8.2.0",
"i18next-resources-to-backend": "^1.2.1"
},

View File

@@ -20,7 +20,7 @@
"@kit/resend": "workspace:*",
"@kit/shared": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@types/node": "^24.3.0",
"@types/node": "^24.3.1",
"zod": "^3.25.74"
},
"typesVersions": {

View File

@@ -13,7 +13,7 @@
".": "./src/index.ts"
},
"dependencies": {
"nodemailer": "^7.0.5"
"nodemailer": "^7.0.6"
},
"devDependencies": {
"@kit/eslint-config": "workspace:*",

View File

@@ -17,7 +17,7 @@
"@kit/mailers-shared": "workspace:*",
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@types/node": "^24.3.0",
"@types/node": "^24.3.1",
"zod": "^3.25.74"
},
"typesVersions": {

View File

@@ -16,7 +16,7 @@
"./config/server": "./src/sentry.client.server.ts"
},
"dependencies": {
"@sentry/nextjs": "^10.8.0",
"@sentry/nextjs": "^10.10.0",
"import-in-the-middle": "1.14.2"
},
"devDependencies": {

View File

@@ -20,7 +20,7 @@
"@kit/prettier-config": "workspace:*",
"@kit/supabase": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@supabase/supabase-js": "2.57.2",
"next": "15.5.2",
"zod": "^3.25.74"
},

View File

@@ -25,7 +25,7 @@
"@kit/tsconfig": "workspace:*",
"@kit/ui": "workspace:*",
"@radix-ui/react-icons": "^1.3.2",
"@supabase/supabase-js": "2.55.0",
"@supabase/supabase-js": "2.57.2",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"react": "19.1.1",

View File

@@ -23,7 +23,7 @@
"@types/react": "19.1.12"
},
"dependencies": {
"pino": "^9.8.0"
"pino": "^9.9.4"
},
"typesVersions": {
"*": {

View File

@@ -26,8 +26,8 @@
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@supabase/ssr": "^0.7.0",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@types/react": "19.1.12",
"next": "15.5.2",
"react": "19.1.1",

View File

@@ -25,14 +25,14 @@
"@kit/eslint-config": "workspace:*",
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"@supabase/supabase-js": "2.55.0",
"@tanstack/react-query": "5.85.5",
"@supabase/supabase-js": "2.57.2",
"@tanstack/react-query": "5.87.1",
"@tanstack/react-table": "^8.21.3",
"@types/react": "19.1.12",
"@types/react-dom": "19.1.9",
"class-variance-authority": "^0.7.1",
"date-fns": "^4.1.0",
"eslint": "^9.34.0",
"eslint": "^9.35.0",
"next": "15.5.2",
"next-themes": "0.4.6",
"prettier": "^3.6.2",
@@ -40,7 +40,7 @@
"react-hook-form": "^7.62.0",
"react-i18next": "^15.7.3",
"sonner": "^2.0.7",
"tailwindcss": "4.1.12",
"tailwindcss": "4.1.13",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.2",
"zod": "^3.25.74"

View File

@@ -364,12 +364,12 @@ export function DataTable<RecordData extends DataItem>({
? 'hover:bg-accent/50 -mx-3 cursor-pointer rounded px-3 py-1 select-none'
: '',
)}
onClick={header.column.getToggleSortingHandler()}
>
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
{header.column.getCanSort() && (
<div className="flex flex-col">
<ChevronUp
@@ -503,7 +503,6 @@ export function DataTable<RecordData extends DataItem>({
<div className={'px-2.5 py-1.5'}>
<Pagination
table={table}
pageSize={pageSize}
totalCount={
pageCount && pageSize ? pageCount * pageSize : undefined
}
@@ -519,19 +518,26 @@ export function DataTable<RecordData extends DataItem>({
function Pagination<T>({
table,
totalCount,
pageSize,
}: React.PropsWithChildren<{
table: ReactTable<T>;
totalCount?: number;
pageSize?: number;
}>) {
const currentPageIndex = table.getState().pagination.pageIndex;
const currentPageSize = table.getState().pagination.pageSize;
const rows = table.getRowModel().rows;
// Calculate what records are being shown on this page
const startRecord = currentPageIndex * currentPageSize + 1;
const endRecord = startRecord + rows.length - 1;
return (
<div className="flex items-center space-x-4">
<span className="text-muted-foreground flex items-center text-xs">
<Trans
i18nKey={'common:pageOfPages'}
values={{
page: table.getState().pagination.pageIndex + 1,
page: currentPageIndex + 1,
total: table.getPageCount(),
}}
/>
@@ -583,12 +589,9 @@ function Pagination<T>({
</Button>
</div>
<If condition={totalCount}>
<If condition={totalCount && rows.length > 0}>
<span className="text-muted-foreground flex items-center text-xs">
<Trans
i18nKey={'common:showingRecordCount'}
values={{ totalCount, pageSize }}
/>
Showing {startRecord} to {endRecord} of {totalCount} rows
</span>
</If>
</div>

4037
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -17,12 +17,12 @@
"@types/eslint": "9.6.1",
"eslint-config-next": "15.5.2",
"eslint-config-turbo": "^2.5.6",
"typescript-eslint": "8.41.0"
"typescript-eslint": "8.42.0"
},
"devDependencies": {
"@kit/prettier-config": "workspace:*",
"@kit/tsconfig": "workspace:*",
"eslint": "^9.34.0",
"eslint": "^9.35.0",
"typescript": "^5.9.2"
},
"prettier": "@kit/prettier-config"