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
430 changes: 194 additions & 236 deletions bun.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion frontend/Dockerfile.playwright
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.61.1-noble
FROM mcr.microsoft.com/playwright:v1.62.1-noble

WORKDIR /app

Expand Down
18 changes: 15 additions & 3 deletions frontend/biome.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.14/schema.json",
"$schema": "https://biomejs.dev/schemas/2.5.6/schema.json",
"assist": { "actions": { "source": { "organizeImports": "on" } } },
"files": {
"includes": [
Expand All @@ -16,7 +16,7 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"preset": "recommended",
"suspicious": {
"noExplicitAny": "off",
"noArrayIndexKey": "off"
Expand All @@ -42,5 +42,17 @@
"parser": {
"tailwindDirectives": true
}
}
},
"overrides": [
{
"includes": ["**/*.svg"],
"linter": {
"rules": {
"a11y": {
"noSvgWithoutTitle": "off"
}
}
}
}
]
Comment on lines +45 to +57

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Biome 2.5.4 started linting .svg files. Checking title in .svg-files is useless - alt text is usually provided as <alt>, and it's checked by another rule (useAltText).
We disable noSvgWithoutTitle for svg-files only, but keep checking this for inlined .svg-files

}
60 changes: 30 additions & 30 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,54 @@
"test:ui": "bunx playwright test --ui"
},
"dependencies": {
"@hookform/resolvers": "^5.4.0",
"@radix-ui/react-avatar": "^1.1.12",
"@radix-ui/react-checkbox": "^1.3.4",
"@radix-ui/react-dialog": "^1.1.16",
"@radix-ui/react-dropdown-menu": "^2.1.17",
"@radix-ui/react-label": "^2.1.9",
"@radix-ui/react-radio-group": "^1.4.0",
"@radix-ui/react-scroll-area": "^1.2.11",
"@radix-ui/react-select": "^2.3.0",
"@radix-ui/react-separator": "^1.1.9",
"@hookform/resolvers": "^5.5.7",
"@radix-ui/react-avatar": "^1.2.6",
"@radix-ui/react-checkbox": "^1.3.11",
"@radix-ui/react-dialog": "^1.1.23",
"@radix-ui/react-dropdown-menu": "^2.1.24",
"@radix-ui/react-label": "^2.1.15",
"@radix-ui/react-radio-group": "^1.4.7",
"@radix-ui/react-scroll-area": "^1.2.18",
"@radix-ui/react-select": "^2.3.7",
"@radix-ui/react-separator": "^1.1.15",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.14",
"@radix-ui/react-tooltip": "^1.2.9",
"@tailwindcss/vite": "^4.3.0",
"@tanstack/react-query": "^5.101.0",
"@tanstack/react-query-devtools": "^5.101.0",
"@tanstack/react-router": "^1.170.15",
"@radix-ui/react-tabs": "^1.1.21",
"@radix-ui/react-tooltip": "^1.2.16",
"@tailwindcss/vite": "^4.3.3",
"@tanstack/react-query": "^5.101.4",
"@tanstack/react-query-devtools": "^5.101.4",
"@tanstack/react-router": "^1.170.18",
"@tanstack/react-router-devtools": "^1.167.0",
"@tanstack/react-table": "^8.21.3",
"axios": "1.18.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"form-data": "4.0.6",
"lucide-react": "^1.17.0",
"lucide-react": "^1.28.0",
"next-themes": "^0.4.6",
"react": "^19.2.7",
"react-dom": "^19.2.7",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"react-error-boundary": "^6.1.2",
"react-hook-form": "^7.78.0",
"react-icons": "^5.6.0",
"react-hook-form": "^7.83.0",
"react-icons": "^5.7.0",
"sonner": "^2.0.7",
"tailwind-merge": "^3.6.0",
"tailwindcss": "^4.2.1",
"zod": "^4.4.3"
},
"devDependencies": {
"@biomejs/biome": "^2.4.16",
"@biomejs/biome": "^2.5.6",
"@hey-api/openapi-ts": "0.97.3",
"@playwright/test": "1.61.1",
"@playwright/test": "1.62.1",
"@tanstack/router-devtools": "^1.167.0",
"@tanstack/router-plugin": "^1.168.18",
"@types/node": "^25.9.2",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react-swc": "^4.3.1",
"@tanstack/router-plugin": "^1.168.23",
"@types/node": "^26.1.2",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.4",
"@vitejs/plugin-react-swc": "^4.3.3",
"dotenv": "^17.4.2",
"tw-animate-css": "^1.4.0",
"typescript": "^5.9.3",
"vite": "^8.0.16"
"typescript": "^6.0.3",
"vite": "^8.2.0"
}
}
106 changes: 53 additions & 53 deletions frontend/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,58 +9,58 @@
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.

import { Route as rootRouteImport } from './routes/__root'
import { Route as SignupRouteImport } from './routes/signup'
import { Route as ResetPasswordRouteImport } from './routes/reset-password'
import { Route as RecoverPasswordRouteImport } from './routes/recover-password'
import { Route as LoginRouteImport } from './routes/login'
import { Route as LayoutRouteImport } from './routes/_layout'
import { Route as LoginRouteImport } from './routes/login'

@YuriiMotov YuriiMotov Aug 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All changes in routeTree.gen.ts file are pure re-ordering. Confirmed using the script below:

Details
import argparse
import sys
from collections import Counter
from pathlib import Path


def read_lines(path: Path) -> list[str]:
    lines = path.read_text(encoding="utf-8").splitlines()
    # Ignore blank lines and strip whitespaces
    lines = [line.strip() for line in lines if line.strip()]
    return lines


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("left", type=Path)
    parser.add_argument("right", type=Path)
    args = parser.parse_args()

    try:
        left = read_lines(args.left)
        right = read_lines(args.right)
    except OSError as exc:
        print(f"error: {exc}", file=sys.stderr)
        return 2

    # Counter difference is asymmetric, so compute it both ways to catch
    # duplicate-count changes (e.g. a line present twice on one side only).
    lc, rc = Counter(left), Counter(right)
    only_left = lc - rc
    only_right = rc - lc

    if not only_left and not only_right:
        if left == right:
            print(f"identical: {len(left)} lines, same order")
        else:
            moved = sum(1 for a, b in zip(left, right) if a != b)
            print(
                f"reorder only: {len(left)} lines, same multiset, "
                f"{moved} line positions changed"
            )
        return 0

    print(
        f"content differs: {args.left} has {len(left)} lines, "
        f"{args.right} has {len(right)} lines"
    )
    for label, counts in (
        ("only in " + str(args.left), only_left),
        ("only in " + str(args.right), only_right),
    ):
        if not counts:
            continue
        total = sum(counts.values())
        print(f"\n{label} ({total} line{'s' if total != 1 else ''}):")
        for i, (line, count) in enumerate(counts.most_common()):
            suffix = f"  (x{count})" if count > 1 else ""
            print(f"  {line!r}{suffix}")
    return 1


if __name__ == "__main__":
    sys.exit(main())

import { Route as RecoverPasswordRouteImport } from './routes/recover-password'
import { Route as ResetPasswordRouteImport } from './routes/reset-password'
import { Route as SignupRouteImport } from './routes/signup'
import { Route as LayoutIndexRouteImport } from './routes/_layout/index'
import { Route as LayoutSettingsRouteImport } from './routes/_layout/settings'
import { Route as LayoutItemsRouteImport } from './routes/_layout/items'
import { Route as LayoutAdminRouteImport } from './routes/_layout/admin'
import { Route as LayoutItemsRouteImport } from './routes/_layout/items'
import { Route as LayoutSettingsRouteImport } from './routes/_layout/settings'

const SignupRoute = SignupRouteImport.update({
id: '/signup',
path: '/signup',
const LayoutRoute = LayoutRouteImport.update({
id: '/_layout',
getParentRoute: () => rootRouteImport,
} as any)
const ResetPasswordRoute = ResetPasswordRouteImport.update({
id: '/reset-password',
path: '/reset-password',
const LoginRoute = LoginRouteImport.update({
id: '/login',
path: '/login',
getParentRoute: () => rootRouteImport,
} as any)
const RecoverPasswordRoute = RecoverPasswordRouteImport.update({
id: '/recover-password',
path: '/recover-password',
getParentRoute: () => rootRouteImport,
} as any)
const LoginRoute = LoginRouteImport.update({
id: '/login',
path: '/login',
const ResetPasswordRoute = ResetPasswordRouteImport.update({
id: '/reset-password',
path: '/reset-password',
getParentRoute: () => rootRouteImport,
} as any)
const LayoutRoute = LayoutRouteImport.update({
id: '/_layout',
const SignupRoute = SignupRouteImport.update({
id: '/signup',
path: '/signup',
getParentRoute: () => rootRouteImport,
} as any)
const LayoutIndexRoute = LayoutIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => LayoutRoute,
} as any)
const LayoutSettingsRoute = LayoutSettingsRouteImport.update({
id: '/settings',
path: '/settings',
const LayoutAdminRoute = LayoutAdminRouteImport.update({
id: '/admin',
path: '/admin',
getParentRoute: () => LayoutRoute,
} as any)
const LayoutItemsRoute = LayoutItemsRouteImport.update({
id: '/items',
path: '/items',
getParentRoute: () => LayoutRoute,
} as any)
const LayoutAdminRoute = LayoutAdminRouteImport.update({
id: '/admin',
path: '/admin',
const LayoutSettingsRoute = LayoutSettingsRouteImport.update({
id: '/settings',
path: '/settings',
getParentRoute: () => LayoutRoute,
} as any)

Expand Down Expand Up @@ -140,18 +140,18 @@ export interface RootRouteChildren {

declare module '@tanstack/react-router' {
interface FileRoutesByPath {
'/signup': {
id: '/signup'
path: '/signup'
fullPath: '/signup'
preLoaderRoute: typeof SignupRouteImport
'/_layout': {
id: '/_layout'
path: ''
fullPath: '/'
preLoaderRoute: typeof LayoutRouteImport
parentRoute: typeof rootRouteImport
}
'/reset-password': {
id: '/reset-password'
path: '/reset-password'
fullPath: '/reset-password'
preLoaderRoute: typeof ResetPasswordRouteImport
'/login': {
id: '/login'
path: '/login'
fullPath: '/login'
preLoaderRoute: typeof LoginRouteImport
parentRoute: typeof rootRouteImport
}
'/recover-password': {
Expand All @@ -161,18 +161,18 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof RecoverPasswordRouteImport
parentRoute: typeof rootRouteImport
}
'/login': {
id: '/login'
path: '/login'
fullPath: '/login'
preLoaderRoute: typeof LoginRouteImport
'/reset-password': {
id: '/reset-password'
path: '/reset-password'
fullPath: '/reset-password'
preLoaderRoute: typeof ResetPasswordRouteImport
parentRoute: typeof rootRouteImport
}
'/_layout': {
id: '/_layout'
path: ''
fullPath: '/'
preLoaderRoute: typeof LayoutRouteImport
'/signup': {
id: '/signup'
path: '/signup'
fullPath: '/signup'
preLoaderRoute: typeof SignupRouteImport
parentRoute: typeof rootRouteImport
}
'/_layout/': {
Expand All @@ -182,11 +182,11 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutIndexRouteImport
parentRoute: typeof LayoutRoute
}
'/_layout/settings': {
id: '/_layout/settings'
path: '/settings'
fullPath: '/settings'
preLoaderRoute: typeof LayoutSettingsRouteImport
'/_layout/admin': {
id: '/_layout/admin'
path: '/admin'
fullPath: '/admin'
preLoaderRoute: typeof LayoutAdminRouteImport
parentRoute: typeof LayoutRoute
}
'/_layout/items': {
Expand All @@ -196,11 +196,11 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutItemsRouteImport
parentRoute: typeof LayoutRoute
}
'/_layout/admin': {
id: '/_layout/admin'
path: '/admin'
fullPath: '/admin'
preLoaderRoute: typeof LayoutAdminRouteImport
'/_layout/settings': {
id: '/_layout/settings'
path: '/settings'
fullPath: '/settings'
preLoaderRoute: typeof LayoutSettingsRouteImport
parentRoute: typeof LayoutRoute
}
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"types": ["node"],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Removing baseUrl as it's deprecated and not needed here (see migration guide)

  2. Adding "types": ["node"] to address Cannot find name 'process'. Do you need to install type definitions for node? (see migration guide)

"paths": {
Comment thread
YuriiMotov marked this conversation as resolved.
"@/*": ["./src/*"]
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineConfig({
},
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
"@": path.resolve(import.meta.dirname, "./src"),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To address warning:

(!) Your Vite config uses features that are unsupported by `configLoader: 'native'`, which is planned to become the default in a future major version of Vite:
  - `__dirname` (vite.config.ts:15:25). Use `import.meta.dirname` instead

Comment thread
YuriiMotov marked this conversation as resolved.
},
},
plugins: [
Expand Down