-
Notifications
You must be signed in to change notification settings - Fork 0
Project Set Detail Page #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 43 commits
1fd51c2
a6a58a9
06238a8
a0b266e
f363234
546e64b
883e837
e25c86f
2c57b56
fd6c07a
e0b5348
62569f9
86af834
3fc605f
87d788b
81704cb
ae2a42a
46f8563
639eace
3a56891
cece221
4a6fc72
d0f7c9a
54b24b5
54534a2
1a7e386
482b7a1
4d41ddd
560256c
d50ec7c
6f25339
518cc9b
658335c
db63e6e
1b26227
8aab055
045f607
715ba1f
56959ae
bb4ae36
7faf73b
51e0345
7d2f128
cf7e2e5
ac1bc6a
c02ecca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for consistency, let's keep naming component files with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this applies to every component file |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| 'use client' | ||
|
|
||
| import {Button} from "@/components/ui/button" | ||
| import {FileIcon, Pencil1Icon} from "@radix-ui/react-icons" | ||
| import * as React from "react" | ||
| import {useRouter} from "next/navigation" | ||
|
|
||
| export type EditModeButtonProps = { | ||
| currentSearchTerm: string | ||
| currentProjectId: number | ||
| currentEditMode: boolean | ||
| } | ||
|
|
||
| export function EditModeButton({currentSearchTerm, currentProjectId, currentEditMode}: EditModeButtonProps) { | ||
| const router = useRouter() | ||
|
|
||
| const updateIsEditMode = (isEditMode: boolean) => { | ||
| router.push(`?isEdit=${isEditMode}&projectId=${currentProjectId}&search=${currentSearchTerm}`) | ||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| {currentEditMode ? ( | ||
| <Button variant="outline" size="sm" onClick={() => updateIsEditMode(false)}> | ||
| <FileIcon className="mr-2"/> | ||
| Save changes | ||
| </Button> | ||
| ) : ( | ||
| <Button variant="outline" size="sm" onClick={() => updateIsEditMode(true)}> | ||
| <Pencil1Icon className="mr-2"/> | ||
| Edit mode | ||
| </Button> | ||
| )} | ||
| </> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,57 @@ | ||||||
| 'use client' | ||||||
|
|
||||||
| import {Text} from "@/components/ui/text" | ||||||
| import {Input} from "@/components/ui/input" | ||||||
| import * as React from "react" | ||||||
| import {type Project} from "@/_temp_types/projects" | ||||||
| import {useRouter} from "next/navigation" | ||||||
|
|
||||||
| export type NumProjectsSubtitleProps = { | ||||||
| project: Project | ||||||
| isEditMode: boolean | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the concept of something being in edit mode is begging to be a Context, not. just a prop we pass down |
||||||
| projectSetId: number | ||||||
| } | ||||||
|
|
||||||
| export function NumProjectsSubtitle({project, isEditMode, projectSetId}: NumProjectsSubtitleProps) { | ||||||
| const router = useRouter() | ||||||
|
|
||||||
| async function handleUpdateNumTeamsPerProject(numOfTeams: number) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| return fetch(process.env.BACKEND_URL + '/api/v1/teamset-templates/' + projectSetId + '/team-templates/' + project.id + '/', { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit; why no string literals |
||||||
| method: 'PATCH', | ||||||
| headers: { | ||||||
| 'Content-Type': 'application/json', | ||||||
| }, | ||||||
| body: JSON.stringify({ | ||||||
| number_of_teams: numOfTeams, | ||||||
| }), | ||||||
| }) | ||||||
| } | ||||||
|
|
||||||
| return ( | ||||||
| <> | ||||||
| <Text element="p" as="smallText"> | ||||||
| This project can be completed by | ||||||
| </Text> | ||||||
| {isEditMode ? ( | ||||||
| <Input | ||||||
| className="w-8 text-center h-fit text-foreground text-sm font-medium leading-none border-0 border-b p-0 focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:ring-offset-transparent focus-visible:ring-transparent focus-visible:outline-none" | ||||||
| defaultValue={project.numberOfTeams} | ||||||
| onBlur={(e) => { | ||||||
| if (!isNaN(parseInt(e.target.value))) { | ||||||
| handleUpdateNumTeamsPerProject(parseInt(e.target.value)) | ||||||
| .then(() => router.refresh()) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why router.refresh here? |
||||||
| .catch((err) => console.error(err)) | ||||||
| } | ||||||
| }} | ||||||
| /> | ||||||
| ) : ( | ||||||
| <Text element="p" as="smallText"> | ||||||
| {project.numberOfTeams} | ||||||
| </Text> | ||||||
| )} | ||||||
| <Text element="p" as="smallText" className=""> | ||||||
| team{project.numberOfTeams > 1 && 's'}. | ||||||
| </Text> | ||||||
| </> | ||||||
| ) | ||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| 'use client' | ||
|
|
||
| import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select" | ||
| import * as React from "react" | ||
| import {type ProjectSet} from "@/_temp_types/projects" | ||
| import {useRouter} from "next/navigation" | ||
|
|
||
| export type ProjectSetSelectProps = { | ||
| currentProjectSetId: number | ||
| allProjectSets: ProjectSet[] | ||
| } | ||
|
|
||
| export function ProjectSetSelect({ currentProjectSetId, allProjectSets }: ProjectSetSelectProps) { | ||
| const router = useRouter() | ||
| const handleProjectSetChanged = (newProjectSetId: string) => { | ||
| router.push(`/project-sets/${newProjectSetId}`) | ||
| } | ||
|
|
||
| return ( | ||
| <Select | ||
| value={currentProjectSetId.toString()} | ||
| onValueChange={(newProjectSetId) => handleProjectSetChanged(newProjectSetId)} | ||
| > | ||
| <SelectTrigger> | ||
| <SelectValue/> | ||
| </SelectTrigger> | ||
| <SelectContent> | ||
| {allProjectSets.map((projectSet) => ( | ||
| <SelectItem | ||
| value={projectSet.id.toString()} | ||
| key={projectSet.id}>{projectSet.name} | ||
| </SelectItem> | ||
| ))} | ||
| </SelectContent> | ||
| </Select> | ||
| ) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| 'use client' | ||
|
|
||
| import * as React from "react" | ||
|
|
||
| import {SearchBar} from "@/components/SearchBar" | ||
| import {Button} from "@/components/ui/button" | ||
| import {type Project} from "@/_temp_types/projects" | ||
| import {useRouter} from "next/navigation" | ||
|
|
||
| export type SidebarProjectsDisplayProps = { | ||
| projects: Project[] | ||
| currentSearchTerm: string | ||
| currentProjectId: number | ||
| currentEditMode: boolean | ||
| } | ||
|
|
||
| export function SidebarProjectsDisplay({projects, currentSearchTerm, currentProjectId, currentEditMode}: SidebarProjectsDisplayProps) { | ||
| const router = useRouter() | ||
|
|
||
| const updateSearchTerm = (newSearchTerm: string) => { | ||
| router.push(`?isEdit=${currentEditMode}&projectId=${currentProjectId}&search=${newSearchTerm}`) | ||
| } | ||
|
|
||
| const updateProjectIdx = (newProjectId: number) => { | ||
| router.push(`?isEdit=${currentEditMode}&projectId=${newProjectId}&search=${currentSearchTerm}`) | ||
| } | ||
|
|
||
| const handleProjectChanged = (project: Project) => { | ||
| updateProjectIdx(project.id) | ||
| // TODO: shoot update api | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what? why? |
||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| <SearchBar | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UX-wise, it'd be nice if the search would dynamically filter as you type, but I know the whole search param thing makes that weird - even more reason to rethink how we're doing this |
||
| className="ml-0" | ||
| placeholder="Search Projects" | ||
| defaultValue={currentSearchTerm} | ||
| onBlur={(e) => updateSearchTerm(e.target.value)} | ||
| onKeyDown={(e) => { | ||
| if (e.key === 'Enter') { | ||
| updateSearchTerm(e.currentTarget.value) | ||
| } | ||
| }} | ||
| /> | ||
| <div className="flex flex-col w-full mt-2 gap-1 pr-4"> | ||
| {projects.map((project) => ( | ||
| <Button | ||
| className="justify-start" | ||
| variant={project.id === currentProjectId ? "secondary" : "ghost"} | ||
| key={project.id} | ||
| onClick={() => handleProjectChanged(project)} | ||
| > | ||
| {project.name} | ||
| </Button> | ||
| ))} | ||
| </div> | ||
| </> | ||
| ) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought Abhinav already put this env variable into the repo?