Switch path alias from @ to ~, add Prettier with organize-imports

This commit is contained in:
2026-04-23 21:13:59 +04:00
parent d68d780a00
commit 8dd618ce88
25 changed files with 118 additions and 77 deletions

3
frontend/.prettierignore Normal file
View File

@@ -0,0 +1,3 @@
node_modules
dist
pnpm-lock.yaml

View File

@@ -0,0 +1,8 @@
{
"printWidth": 110,
"singleQuote": true,
"trailingComma": "all",
"semi": false,
"arrowParens": "always",
"plugins": ["prettier-plugin-organize-imports"]
}

View File

@@ -10,10 +10,10 @@
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
"components": "~/components",
"utils": "~/lib/utils",
"ui": "~/components/ui",
"lib": "~/lib",
"hooks": "~/hooks"
}
}

View File

@@ -12,7 +12,9 @@
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
"typecheck": "tsc -b --noEmit"
"typecheck": "tsc -b --noEmit",
"format": "prettier --ignore-unknown --write .",
"format:check": "prettier --check ."
},
"dependencies": {
"@radix-ui/react-dropdown-menu": "2.1.16",
@@ -40,6 +42,8 @@
"@types/react": "18.3.28",
"@types/react-dom": "18.3.7",
"@vitejs/plugin-react": "4.7.0",
"prettier": "3.8.3",
"prettier-plugin-organize-imports": "4.3.0",
"tailwindcss": "4.1.16",
"typescript": "5.9.3",
"vite": "6.4.2"

View File

@@ -1,4 +1,4 @@
import type { Globals, Menu } from '@/lib/types'
import type { Globals, Menu } from '~/lib/types'
type Props = {
globals: Globals

View File

@@ -1,5 +1,5 @@
import { Link } from '@tanstack/react-router'
import type { Globals, Menu } from '@/lib/types'
import type { Globals, Menu } from '~/lib/types'
import { ThemeToggle } from './theme-toggle'
type Props = {

View File

@@ -1,7 +1,7 @@
import { useSuspenseQuery } from '@tanstack/react-query'
import { globalsQuery, menusQuery } from '@/lib/queries'
import { Header } from './header'
import { globalsQuery, menusQuery } from '~/lib/queries'
import { Footer } from './footer'
import { Header } from './header'
export function Shell({ children }: { children: React.ReactNode }) {
const { data: globals } = useSuspenseQuery(globalsQuery)

View File

@@ -1,6 +1,6 @@
import { Moon, Sun } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { useTheme } from '@/components/theme-provider'
import { useTheme } from '~/components/theme-provider'
import { Button } from '~/components/ui/button'
export function ThemeToggle() {
const { theme, toggle } = useTheme()

View File

@@ -1,6 +1,6 @@
import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import * as React from 'react'
import { cn } from '~/lib/utils'
const alertVariants = cva(
'relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7',
@@ -32,9 +32,10 @@ export const AlertTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttribu
)
AlertTitle.displayName = 'AlertTitle'
export const AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} />
),
)
export const AlertDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn('text-sm [&_p]:leading-relaxed', className)} {...props} />
))
AlertDescription.displayName = 'AlertDescription'

View File

@@ -1,7 +1,7 @@
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
import * as React from 'react'
import { cn } from '~/lib/utils'
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
@@ -30,8 +30,7 @@ const buttonVariants = cva(
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
asChild?: boolean
}

View File

@@ -1,5 +1,5 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
import { cn } from '~/lib/utils'
export const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (

View File

@@ -1,7 +1,7 @@
import * as React from 'react'
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
import { Check } from 'lucide-react'
import { cn } from '@/lib/utils'
import * as React from 'react'
import { cn } from '~/lib/utils'
export const DropdownMenu = DropdownMenuPrimitive.Root
export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
@@ -86,6 +86,10 @@ export const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator ref={ref} className={cn('-mx-1 my-1 h-px bg-muted', className)} {...props} />
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName

View File

@@ -1,5 +1,5 @@
import * as React from 'react'
import { cn } from '@/lib/utils'
import { cn } from '~/lib/utils'
export const Input = React.forwardRef<HTMLInputElement, React.InputHTMLAttributes<HTMLInputElement>>(
({ className, type, ...props }, ref) => {

View File

@@ -1,6 +1,6 @@
import * as React from 'react'
import * as SeparatorPrimitive from '@radix-ui/react-separator'
import { cn } from '@/lib/utils'
import * as React from 'react'
import { cn } from '~/lib/utils'
export const Separator = React.forwardRef<
React.ElementRef<typeof SeparatorPrimitive.Root>,

View File

@@ -1,4 +1,4 @@
import { cn } from '@/lib/utils'
import { cn } from '~/lib/utils'
export function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn('animate-pulse rounded-md bg-muted', className)} {...props} />

View File

@@ -80,7 +80,12 @@
body {
@apply bg-background text-foreground;
margin: 0;
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
font-family:
system-ui,
-apple-system,
'Segoe UI',
Roboto,
sans-serif;
}
}

View File

@@ -31,7 +31,10 @@ function buildUrl(collection: string, q: DirectusQuery = {}): string {
return url.toString()
}
export async function directusList<T>(collection: string, q: DirectusQuery = {}): Promise<DirectusListResponse<T>> {
export async function directusList<T>(
collection: string,
q: DirectusQuery = {},
): Promise<DirectusListResponse<T>> {
const res = await fetch(buildUrl(collection, q))
if (!res.ok) throw new Error(`Directus error ${res.status} on /items/${collection}`)
return (await res.json()) as DirectusListResponse<T>

View File

@@ -1,9 +1,9 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { RouterProvider, createRouter } from '@tanstack/react-router'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { HelmetProvider } from 'react-helmet-async'
import { routeTree } from '@generated/tanstack-router/routeTree.gen'
import { routeTree } from '~generated/tanstack-router/routeTree.gen'
import { ThemeProvider } from './components/theme-provider'
import './index.css'

View File

@@ -1,8 +1,8 @@
import { createFileRoute, notFound } from '@tanstack/react-router'
import { useSuspenseQuery } from '@tanstack/react-query'
import { createFileRoute, notFound } from '@tanstack/react-router'
import { Helmet } from 'react-helmet-async'
import { pageBySlugQuery } from '@/lib/queries'
import { PageView } from '@/components/page-view'
import { PageView } from '~/components/page-view'
import { pageBySlugQuery } from '~/lib/queries'
export const Route = createFileRoute('/$slug')({
loader: async ({ context: { queryClient }, params: { slug } }) => {

View File

@@ -1,22 +1,18 @@
import { Outlet, createRootRouteWithContext } from '@tanstack/react-router'
import type { QueryClient } from '@tanstack/react-query'
import { useSuspenseQuery } from '@tanstack/react-query'
import { createRootRouteWithContext, Outlet } from '@tanstack/react-router'
import { lazy, Suspense } from 'react'
import { Helmet } from 'react-helmet-async'
import { useSuspenseQuery } from '@tanstack/react-query'
import { globalsQuery, menusQuery } from '@/lib/queries'
import { Shell } from '@/components/layout/shell'
import { Shell } from '~/components/layout/shell'
import { globalsQuery, menusQuery } from '~/lib/queries'
const TanStackRouterDevtools = import.meta.env.PROD
? () => null
: lazy(() =>
import('@tanstack/react-router-devtools').then((m) => ({ default: m.TanStackRouterDevtools })),
)
: lazy(() => import('@tanstack/react-router-devtools').then((m) => ({ default: m.TanStackRouterDevtools })))
const ReactQueryDevtools = import.meta.env.PROD
? () => null
: lazy(() =>
import('@tanstack/react-query-devtools').then((m) => ({ default: m.ReactQueryDevtools })),
)
: lazy(() => import('@tanstack/react-query-devtools').then((m) => ({ default: m.ReactQueryDevtools })))
export const Route = createRootRouteWithContext<{ queryClient: QueryClient }>()({
loader: async ({ context: { queryClient } }) => {

View File

@@ -1,7 +1,7 @@
import { createFileRoute } from '@tanstack/react-router'
import { useSuspenseQuery } from '@tanstack/react-query'
import { pageBySlugQuery } from '@/lib/queries'
import { PageView } from '@/components/page-view'
import { createFileRoute } from '@tanstack/react-router'
import { PageView } from '~/components/page-view'
import { pageBySlugQuery } from '~/lib/queries'
export const Route = createFileRoute('/')({
loader: async ({ context: { queryClient } }) => {

View File

@@ -19,8 +19,8 @@
"noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@generated/*": ["node_modules/.cache/*"]
"~/*": ["src/*"],
"~generated/*": ["node_modules/.cache/*"]
}
},
"include": ["src", "node_modules/.cache/tanstack-router/routeTree.gen.ts"]

View File

@@ -1,7 +1,4 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
"references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }]
}

View File

@@ -1,8 +1,8 @@
import path from 'node:path'
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite'
import { TanStackRouterVite } from '@tanstack/router-plugin/vite'
import react from '@vitejs/plugin-react'
import path from 'node:path'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
@@ -17,8 +17,8 @@ export default defineConfig({
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@generated': path.resolve(__dirname, './node_modules/.cache'),
'~': path.resolve(__dirname, './src'),
'~generated': path.resolve(__dirname, './node_modules/.cache'),
},
},
server: {