32 | {footerText} 33 |
34 |├── .prettierrc.json ├── src ├── features │ ├── auth │ │ ├── index.tsx │ │ ├── login.page.tsx │ │ ├── register.page.tsx │ │ ├── model │ │ │ ├── use-login.ts │ │ │ └── use-register.ts │ │ └── ui │ │ │ ├── auth-layout.tsx │ │ │ ├── login-form.tsx │ │ │ └── register-form.tsx │ ├── board-templates │ │ ├── index.ts │ │ ├── use-templates-modal.ts │ │ ├── templates-modal.tsx │ │ ├── templates-gallery.tsx │ │ └── template-card.tsx │ ├── board │ │ └── board.page.tsx │ ├── boards-list │ │ ├── ui │ │ │ ├── boards-search-input.tsx │ │ │ ├── view-mode-toggle.tsx │ │ │ ├── boards-favorite-toggle.tsx │ │ │ ├── boards-sort-select.tsx │ │ │ ├── boards-sidebar.tsx │ │ │ ├── boards-list-card.tsx │ │ │ ├── boards-list-item.tsx │ │ │ └── boards-list-layout.tsx │ │ ├── model │ │ │ ├── use-boards-filters.ts │ │ │ ├── use-delete-board.tsx │ │ │ ├── use-create-board.ts │ │ │ ├── use-update-favorite.ts │ │ │ ├── use-recent-groups.ts │ │ │ └── use-boards-list.tsx │ │ ├── compose │ │ │ ├── board-card.tsx │ │ │ └── board-item.tsx │ │ ├── boards-list-favorite.page.tsx │ │ ├── boards-list-recent.page.tsx │ │ └── boards-list.page.tsx │ └── header │ │ └── index.tsx ├── shared │ ├── model │ │ ├── config.ts │ │ ├── routes.ts │ │ └── session.ts │ ├── api │ │ ├── query-client.ts │ │ ├── schema │ │ │ ├── index.ts │ │ │ ├── shared │ │ │ │ └── responses.yaml │ │ │ ├── main.yaml │ │ │ ├── endpoints │ │ │ │ ├── auth.yaml │ │ │ │ └── boards.yaml │ │ │ └── generated.ts │ │ ├── mocks │ │ │ ├── index.ts │ │ │ ├── browser.ts │ │ │ ├── http.ts │ │ │ ├── session.ts │ │ │ └── handlers │ │ │ │ ├── auth.ts │ │ │ │ └── boards.ts │ │ └── instance.ts │ ├── lib │ │ ├── css.ts │ │ └── react.ts │ ├── env.d.ts │ └── ui │ │ └── kit │ │ ├── skeleton.tsx │ │ ├── label.tsx │ │ ├── input.tsx │ │ ├── switch.tsx │ │ ├── scroll-area.tsx │ │ ├── tabs.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── dialog.tsx │ │ ├── form.tsx │ │ ├── select.tsx │ │ └── dropdown-menu.tsx └── app │ ├── app.tsx │ ├── providers.tsx │ ├── main.tsx │ ├── protected-route.tsx │ ├── router.tsx │ └── index.css ├── .env.development ├── tsconfig.json ├── vite.config.ts ├── .gitignore ├── index.html ├── components.json ├── tsconfig.node.json ├── tsconfig.app.json ├── eslint.config.js ├── public ├── vite.svg └── mockServiceWorker.js ├── eslint.boundaries.js ├── README.md ├── package.json └── bundle.yaml /.prettierrc.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /src/features/auth/index.tsx: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | VITE_API_BASE_URL=/api -------------------------------------------------------------------------------- /src/shared/model/config.ts: -------------------------------------------------------------------------------- 1 | export const CONFIG = { 2 | API_BASE_URL: import.meta.env.VITE_API_BASE_URL, 3 | }; 4 | -------------------------------------------------------------------------------- /src/shared/api/query-client.ts: -------------------------------------------------------------------------------- 1 | import { QueryClient } from "@tanstack/react-query"; 2 | 3 | export const queryClient = new QueryClient(); 4 | -------------------------------------------------------------------------------- /src/shared/api/schema/index.ts: -------------------------------------------------------------------------------- 1 | import { paths, components } from "./generated"; 2 | 3 | export type ApiPaths = paths; 4 | export type ApiSchemas = components["schemas"]; 5 | -------------------------------------------------------------------------------- /src/shared/lib/css.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /src/features/board-templates/index.ts: -------------------------------------------------------------------------------- 1 | export { TemplatesGallery } from "./templates-gallery"; 2 | export { TemplatesModal } from "./templates-modal"; 3 | export { useTemplatesModal } from "./use-templates-modal"; 4 | -------------------------------------------------------------------------------- /src/app/app.tsx: -------------------------------------------------------------------------------- 1 | import { Outlet } from "react-router-dom"; 2 | 3 | export function App() { 4 | return ( 5 |
32 | {footerText} 33 |
34 |{template.description}
40 | 47 |151 | {body} 152 |
153 | ) 154 | } 155 | 156 | export { 157 | useFormField, 158 | Form, 159 | FormItem, 160 | FormLabel, 161 | FormControl, 162 | FormDescription, 163 | FormMessage, 164 | FormField, 165 | } 166 | -------------------------------------------------------------------------------- /src/app/index.css: -------------------------------------------------------------------------------- 1 | @import "tailwindcss"; 2 | @import "tw-animate-css"; 3 | 4 | @custom-variant dark (&:is(.dark *)); 5 | 6 | @theme inline { 7 | --radius-sm: calc(var(--radius) - 4px); 8 | --radius-md: calc(var(--radius) - 2px); 9 | --radius-lg: var(--radius); 10 | --radius-xl: calc(var(--radius) + 4px); 11 | --color-background: var(--background); 12 | --color-foreground: var(--foreground); 13 | --color-card: var(--card); 14 | --color-card-foreground: var(--card-foreground); 15 | --color-popover: var(--popover); 16 | --color-popover-foreground: var(--popover-foreground); 17 | --color-primary: var(--primary); 18 | --color-primary-foreground: var(--primary-foreground); 19 | --color-secondary: var(--secondary); 20 | --color-secondary-foreground: var(--secondary-foreground); 21 | --color-muted: var(--muted); 22 | --color-muted-foreground: var(--muted-foreground); 23 | --color-accent: var(--accent); 24 | --color-accent-foreground: var(--accent-foreground); 25 | --color-destructive: var(--destructive); 26 | --color-border: var(--border); 27 | --color-input: var(--input); 28 | --color-ring: var(--ring); 29 | --color-chart-1: var(--chart-1); 30 | --color-chart-2: var(--chart-2); 31 | --color-chart-3: var(--chart-3); 32 | --color-chart-4: var(--chart-4); 33 | --color-chart-5: var(--chart-5); 34 | --color-sidebar: var(--sidebar); 35 | --color-sidebar-foreground: var(--sidebar-foreground); 36 | --color-sidebar-primary: var(--sidebar-primary); 37 | --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 38 | --color-sidebar-accent: var(--sidebar-accent); 39 | --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 40 | --color-sidebar-border: var(--sidebar-border); 41 | --color-sidebar-ring: var(--sidebar-ring); 42 | } 43 | 44 | :root { 45 | --radius: 0.625rem; 46 | --background: oklch(1 0 0); 47 | --foreground: oklch(0.145 0 0); 48 | --card: oklch(1 0 0); 49 | --card-foreground: oklch(0.145 0 0); 50 | --popover: oklch(1 0 0); 51 | --popover-foreground: oklch(0.145 0 0); 52 | --primary: oklch(0.205 0 0); 53 | --primary-foreground: oklch(0.985 0 0); 54 | --secondary: oklch(0.97 0 0); 55 | --secondary-foreground: oklch(0.205 0 0); 56 | --muted: oklch(0.97 0 0); 57 | --muted-foreground: oklch(0.556 0 0); 58 | --accent: oklch(0.97 0 0); 59 | --accent-foreground: oklch(0.205 0 0); 60 | --destructive: oklch(0.577 0.245 27.325); 61 | --border: oklch(0.922 0 0); 62 | --input: oklch(0.922 0 0); 63 | --ring: oklch(0.708 0 0); 64 | --chart-1: oklch(0.646 0.222 41.116); 65 | --chart-2: oklch(0.6 0.118 184.704); 66 | --chart-3: oklch(0.398 0.07 227.392); 67 | --chart-4: oklch(0.828 0.189 84.429); 68 | --chart-5: oklch(0.769 0.188 70.08); 69 | --sidebar: oklch(0.985 0 0); 70 | --sidebar-foreground: oklch(0.145 0 0); 71 | --sidebar-primary: oklch(0.205 0 0); 72 | --sidebar-primary-foreground: oklch(0.985 0 0); 73 | --sidebar-accent: oklch(0.97 0 0); 74 | --sidebar-accent-foreground: oklch(0.205 0 0); 75 | --sidebar-border: oklch(0.922 0 0); 76 | --sidebar-ring: oklch(0.708 0 0); 77 | } 78 | 79 | .dark { 80 | --background: oklch(0.145 0 0); 81 | --foreground: oklch(0.985 0 0); 82 | --card: oklch(0.205 0 0); 83 | --card-foreground: oklch(0.985 0 0); 84 | --popover: oklch(0.205 0 0); 85 | --popover-foreground: oklch(0.985 0 0); 86 | --primary: oklch(0.922 0 0); 87 | --primary-foreground: oklch(0.205 0 0); 88 | --secondary: oklch(0.269 0 0); 89 | --secondary-foreground: oklch(0.985 0 0); 90 | --muted: oklch(0.269 0 0); 91 | --muted-foreground: oklch(0.708 0 0); 92 | --accent: oklch(0.269 0 0); 93 | --accent-foreground: oklch(0.985 0 0); 94 | --destructive: oklch(0.704 0.191 22.216); 95 | --border: oklch(1 0 0 / 10%); 96 | --input: oklch(1 0 0 / 15%); 97 | --ring: oklch(0.556 0 0); 98 | --chart-1: oklch(0.488 0.243 264.376); 99 | --chart-2: oklch(0.696 0.17 162.48); 100 | --chart-3: oklch(0.769 0.188 70.08); 101 | --chart-4: oklch(0.627 0.265 303.9); 102 | --chart-5: oklch(0.645 0.246 16.439); 103 | --sidebar: oklch(0.205 0 0); 104 | --sidebar-foreground: oklch(0.985 0 0); 105 | --sidebar-primary: oklch(0.488 0.243 264.376); 106 | --sidebar-primary-foreground: oklch(0.985 0 0); 107 | --sidebar-accent: oklch(0.269 0 0); 108 | --sidebar-accent-foreground: oklch(0.985 0 0); 109 | --sidebar-border: oklch(1 0 0 / 10%); 110 | --sidebar-ring: oklch(0.556 0 0); 111 | } 112 | 113 | @layer base { 114 | * { 115 | @apply border-border outline-ring/50; 116 | } 117 | body { 118 | @apply bg-background text-foreground; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/features/boards-list/ui/boards-list-layout.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@/shared/ui/kit/skeleton"; 2 | import React from "react"; 3 | import { ViewMode } from "./view-mode-toggle"; 4 | 5 | export function BoardsListLayout({ 6 | header, 7 | filters, 8 | children, 9 | sidebar, 10 | templates, 11 | }: { 12 | header: React.ReactNode; 13 | filters?: React.ReactNode; 14 | children: React.ReactNode; 15 | sidebar?: React.ReactNode; 16 | templates?: React.ReactNode; 17 | }) { 18 | return ( 19 |{description}
} 49 |