feature: add projects page (2 parts works)
This commit is contained in:
@@ -6,6 +6,7 @@ import { FunctionComponent } from "react"
|
||||
import { useForm } from "react-hook-form"
|
||||
|
||||
import Link from "next/link"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
import api from "@shared/api"
|
||||
import { useCookie } from "@shared/hooks/useCookie"
|
||||
@@ -26,6 +27,7 @@ interface ILoginFormData {
|
||||
export const LoginPage: FunctionComponent<
|
||||
ILoginPageProps
|
||||
> = (): JSX.Element => {
|
||||
const router = useRouter()
|
||||
const [, setAccessTokenCookie] = useCookie(ACCESS_TOKEN_COOKIE)
|
||||
const [, setRefreshTokenCookie] = useCookie(REFRESH_TOKEN_COOKIE)
|
||||
|
||||
@@ -33,7 +35,7 @@ export const LoginPage: FunctionComponent<
|
||||
onSuccess: ({ access, refresh, user }) => {
|
||||
setAccessTokenCookie(access)
|
||||
setRefreshTokenCookie(refresh)
|
||||
console.log("Login successful:", user)
|
||||
router.push("/")
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error("Login failed:", error)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./ui/ProjectsPage"
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface IProjectsPageProps {
|
||||
message?: string
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
.root {
|
||||
padding: 0 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include typography.font-display;
|
||||
color: variables.$text-primary;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
@include typography.font-body-16(600);
|
||||
color: variables.$text-primary;
|
||||
}
|
||||
|
||||
.projectList {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
gap: 24px;
|
||||
margin-top: 24px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
"use client"
|
||||
|
||||
import type { JSX } from "react"
|
||||
|
||||
import { PlusIcon } from "lucide-react"
|
||||
import { FunctionComponent, useState } from "react"
|
||||
|
||||
import { ProjectCard } from "@entities/ProjectCard"
|
||||
import { CreateProjectModal } from "@features/CreateProjectModal"
|
||||
import api from "@shared/api"
|
||||
import { Button } from "@shared/ui"
|
||||
import { StaticLoader } from "@shared/ui/Loader"
|
||||
import { ProjectsHeader } from "@widgets/Projects/ProjectsHeader/ui/ProjectsHeader"
|
||||
|
||||
import { IProjectsPageProps } from "../model/ProjectsPage.d"
|
||||
import styles from "./ProjectsPage.module.scss"
|
||||
|
||||
export const ProjectsPage: FunctionComponent<
|
||||
IProjectsPageProps
|
||||
> = (): JSX.Element => {
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false)
|
||||
|
||||
const {
|
||||
data: projects,
|
||||
isLoading: projectsLoading,
|
||||
refetch: refetchProjects,
|
||||
} = api.useQuery("get", "/api/projects/")
|
||||
|
||||
return (
|
||||
<div className={styles.root} data-testid="ProjectsPage">
|
||||
{projectsLoading && <StaticLoader fullscreen />}
|
||||
<div className={styles.header}>
|
||||
<div className={styles.titles}>
|
||||
<h1 className={styles.title}>Мои проекты</h1>
|
||||
<h4 className={styles.subtitle}>
|
||||
Управляйте своими последними проектами
|
||||
</h4>
|
||||
</div>
|
||||
<div>
|
||||
<Button
|
||||
variant="primary"
|
||||
size="lg"
|
||||
onClick={() => setIsCreateModalOpen(true)}
|
||||
>
|
||||
<PlusIcon /> Создать проект
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CreateProjectModal
|
||||
open={isCreateModalOpen}
|
||||
onOpenChange={setIsCreateModalOpen}
|
||||
onCreated={async () => {
|
||||
await refetchProjects()
|
||||
}}
|
||||
/>
|
||||
|
||||
<ProjectsHeader />
|
||||
|
||||
<div className={styles.projectList}>
|
||||
{projects?.map((project) => (
|
||||
<ProjectCard
|
||||
key={project.id}
|
||||
project={project}
|
||||
// Mock random progress for demo since API doesn't provide it yet
|
||||
progress={project.status === "PROCESSING" ? 45 : 0}
|
||||
currentAction={
|
||||
project.status === "PROCESSING" ? "Rendering" : undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user