Skip to content
Merged
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
40 changes: 35 additions & 5 deletions apps/web/app/(auth)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { FEATURES } from '@/hooks/use-feature-flag'
import Link from 'next/link'
import { notFound } from 'next/navigation'

import { HStack } from '@repo/ui'

interface Props {
children: React.ReactNode
}
Expand All @@ -13,8 +12,39 @@ export default function AuthLayout({ children }: Props) {
}

return (
<HStack align='center' justify='center' className='min-h-screen bg-foreground'>
{children}
</HStack>
<div className='relative min-h-screen overflow-hidden bg-background text-foreground'>
<div className='pointer-events-none absolute inset-0'>
<div className='absolute left-0 top-0 h-[320px] w-[320px] rounded-full bg-primary/14 blur-[110px]' />
<div className='absolute bottom-[-120px] right-[-40px] h-[320px] w-[320px] rounded-full bg-accent/10 blur-[120px]' />
</div>

<div className='relative mx-auto flex min-h-screen w-full max-w-[1180px] flex-col px-4 py-6 sm:px-6'>
<div className='flex items-center justify-between gap-3'>
<Link
href='/'
className='inline-flex items-center gap-3 rounded-full border border-border/70 bg-card/55 px-3 py-2 transition-colors hover:bg-card'
>
<div className='flex h-10 w-10 items-center justify-center rounded-xl border border-primary/30 bg-primary/12 text-sm font-semibold text-primary'>
TT
</div>
<div className='hidden sm:block'>
<p className='text-sm font-medium tracking-[0.24em] text-primary/90'>
TRACKER TASK
</p>
<p className='text-xs text-muted-foreground'>Вернуться на главную</p>
</div>
</Link>

<Link
href='/'
className='inline-flex items-center rounded-full border border-border/70 bg-background/70 px-4 py-2 text-sm text-muted-foreground transition-colors hover:border-primary/25 hover:text-foreground'
>
На главную
</Link>
</div>

<div className='flex flex-1 items-center justify-center py-8'>{children}</div>
</div>
</div>
)
}
15 changes: 14 additions & 1 deletion apps/web/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use client'
Comment thread
SuvStreet marked this conversation as resolved.

import Link from 'next/link'

import { Button, Form } from '@repo/ui'

import { AuthFormLayout } from '../auth-form-layout'
Expand Down Expand Up @@ -29,7 +31,18 @@ export default function LoginPage() {
</Button>
}
>
<LoginForm />
<div className='space-y-4'>
<LoginForm />
<p className='text-center text-sm text-muted-foreground'>
Еще нет аккаунта?{' '}
<Link
href='/register'
className='font-medium text-primary transition-opacity hover:opacity-80'
>
Зарегистрироваться
</Link>
</p>
</div>
</AuthFormLayout>
</form>
</Form>
Expand Down
15 changes: 14 additions & 1 deletion apps/web/app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use client'
Comment thread
SuvStreet marked this conversation as resolved.

import Link from 'next/link'

import { Button, Form } from '@repo/ui'

import { AuthFormLayout } from '../auth-form-layout'
Expand Down Expand Up @@ -29,7 +31,18 @@ export default function RegisterPage() {
</Button>
}
>
<RegisterForm />
<div className='space-y-4'>
<RegisterForm />
<p className='text-center text-sm text-muted-foreground'>
Уже есть аккаунт?{' '}
<Link
href='/login'
className='font-medium text-primary transition-opacity hover:opacity-80'
>
Войти
</Link>
</p>
</div>
</AuthFormLayout>
</form>
</Form>
Expand Down
46 changes: 2 additions & 44 deletions apps/web/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,5 @@
import styles from './page.module.css'
import { HomePage } from '@/views/home'

export default function Home() {
return (
<div className={styles.page}>
<main className={styles.main}>
<div className={styles.hero}>
<h1 className={styles.title}>Tracker Task</h1>
<p className={styles.subtitle}>Открытая система управления IT-проектами</p>
</div>

<div className={styles.content}>
<section className={styles.section}>
<h2>О проекте</h2>
<p>
Лёгкая, современная альтернатива Jira и Яндекс.Трекер для разработчиков и
небольших команд.
</p>
</section>

<section className={styles.section}>
<h2>Цель</h2>
<p>
Создать open-source решение для управления проектами, спринтами и задачами,
которое просто развернуть на собственном сервере.
</p>
</section>

<section className={styles.section}>
<h2>Возможности</h2>
<ul>
<li>Управление проектами и задачами</li>
<li>Спринты и бэклог</li>
<li>Issue tracking</li>
<li>Простое развёртывание</li>
<li>Открытый исходный код</li>
</ul>
</section>
</div>

<div className={styles.footer}>
<p className={styles.status}>🚧 Проект находится в разработке</p>
</div>
</main>
</div>
)
return <HomePage />
}
1 change: 1 addition & 0 deletions apps/web/views/home/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { HomePage } from './ui/home-page'
121 changes: 121 additions & 0 deletions apps/web/views/home/model/content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import type { ComponentType, SVGProps } from 'react'

import {
BookOpen,
Brain,
CheckCircle2,
KanbanSquare,
Radio,
Server,
Shield,
Terminal,
Users,
Zap,
} from '@repo/ui/icons'

type IconType = ComponentType<SVGProps<SVGSVGElement>>

export const navigationItems = [
{ label: 'Возможности', href: '#features' },
{ label: 'Установка', href: '#deploy' },
{ label: 'Сообщество', href: '#community' },
] as const

export const heroBadge = {
icon: Shield,
label: 'Open Source & Self-Hosted',
} as const

export const heroActions = {
primary: {
label: 'Попробовать демо',
href: '/projects',
},
secondary: {
label: 'Развернуть',
href: '#deploy',
icon: Terminal,
},
} as const

export const features: Array<{
icon: IconType
title: string
description: string
highlight?: boolean
}> = [
{
icon: Server,
title: 'Свой сервер',
description: 'Полный контроль над данными. Разверните на своём сервере за минуты.',
},
{
icon: Zap,
title: 'Быстрый старт',
description: 'Минимальный порог входа. Начните работать без долгой настройки.',
},
{
icon: KanbanSquare,
title: 'Kanban-first',
description: 'Визуальное управление задачами с drag & drop. Интуитивно и быстро.',
},
{
icon: Brain,
title: 'AI-помощник',
description: 'Генерация эпиков и задач из описания. Ускоряет планирование в разы.',
},
{
icon: Radio,
title: 'Мгновенные события',
description: 'Мгновенные уведомления через WebSocket. Команда всегда в курсе.',
},
{
icon: Users,
title: 'Для команд 3-15',
description:
'Оптимизировано для небольших продуктовых команд. Роли, права и приглашения.',
highlight: true,
},
] as const

export const boardColumns = [
{ title: 'To Do', count: 2 },
{ title: 'In Progress', count: 3 },
{ title: 'Review', count: 1 },
{ title: 'Done', count: 2 },
] as const

export const deploySteps = [
{
step: '1',
code: 'git clone https://github.com/ITBooster-practice/tracker-task.git',
},
{
step: '2',
code: 'cd tracker-task && cp apps/api/.env.example apps/api/.env',
},
{
step: '3',
code: 'docker compose up -d',
},
{
step: '4',
code: 'open http://localhost:3001',
},
] as const

export const communityActions: Array<{
label: string
href: string
icon: IconType
}> = [
{ label: 'Дорожная карта', href: '#', icon: CheckCircle2 },
{ label: 'Как внести вклад', href: '#', icon: BookOpen },
] as const

export const footerLinks = [
{ label: 'GitHub', href: 'https://github.com/ITBooster-practice/tracker-task' },
{ label: 'Документация', href: '#' },
{ label: 'Issues', href: '#' },
{ label: 'Сообщество', href: '#' },
] as const
35 changes: 35 additions & 0 deletions apps/web/views/home/ui/cta-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Button } from '@repo/ui'

import { communityActions } from '../model/content'

function CtaSection() {
return (
<section id='community' className='border-t border-border py-[80px]'>
<div className='mx-auto max-w-[1200px] text-center'>
<h2 className='animate-home-fade-up mb-3 text-[28px] font-bold tracking-tight md:text-[32px]'>
Открытый код
</h2>
<p className='mx-auto mb-10 max-w-[500px] text-base text-muted-foreground'>
MIT лицензия. Предлагай улучшения, следи за roadmap и участвуй в развитии
продукта.
</p>
<div className='animate-home-fade-up-delay flex flex-wrap items-center justify-center gap-4'>
{communityActions.map((action) => {
const Icon = action.icon

return (
<Button key={action.label} variant='outline' asChild>
<a href={action.href}>
<Icon className='mr-2 h-4 w-4' />
{action.label}
</a>
</Button>
)
})}
</div>
</div>
</section>
)
}

export { CtaSection }
59 changes: 59 additions & 0 deletions apps/web/views/home/ui/deploy-section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Button } from '@repo/ui'
import { BookOpen, Github, Terminal } from '@repo/ui/icons'

import { deploySteps } from '../model/content'

function DeploySection() {
return (
<section id='deploy' className='border-t border-border py-[80px]'>
<div className='mx-auto max-w-[1200px]'>
<div className='animate-home-fade-up mb-[48px] text-center'>
<h2 className='mb-3 text-[28px] font-bold tracking-tight md:text-[32px]'>
Развернуть за 4 шага
</h2>
<p className='text-base text-muted-foreground'>Docker Compose — и вы в деле</p>
</div>
<div className='animate-home-fade-up-delay mx-auto max-w-[640px]'>
<div className='overflow-hidden rounded-xl border border-border bg-card'>
<div className='flex items-center gap-2 border-b border-border px-6 py-4'>
<Terminal className='h-4 w-4 text-muted-foreground' />
<span className='text-sm text-muted-foreground'>Terminal</span>
</div>
<div className='space-y-4 p-6'>
{deploySteps.map((step) => (
<div key={step.step} className='flex items-start gap-4'>
<span className='mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary/10 text-xs font-medium text-primary'>
{step.step}
</span>
<code className='break-all font-mono text-sm text-foreground/80'>
{step.code}
</code>
</div>
))}
</div>
</div>
<div className='mt-8 flex flex-wrap items-center justify-center gap-4'>
<Button variant='outline' asChild>
<a href='#'>
<BookOpen className='mr-2 h-4 w-4' />
Документация
</a>
</Button>
<Button asChild>
<a
href='https://github.com/ITBooster-practice/tracker-task'
target='_blank'
rel='noopener noreferrer'
>
<Github className='mr-2 h-4 w-4' />
Репозиторий
</a>
</Button>
</div>
</div>
</div>
</section>
)
}

export { DeploySection }
Loading
Loading