Skip to content

Commit

Permalink
build mobile view for roadmap kanban
Browse files Browse the repository at this point in the history
  • Loading branch information
mapra99 committed Oct 27, 2023
1 parent 6031464 commit 3b8edfb
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 9 deletions.
15 changes: 11 additions & 4 deletions web/src/components/issues-kanban/mobile.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
'use client';

import { useState } from "react"
import StatusSelector from "../status-selector"
import StatusSelector from "@/components/status-selector"
import KanbanColumn from "@/components/kanban-column"
import { IssuesKanbanProps } from "./types"
import type { IssueStatus } from "@/feedbackr-api/v1/schemas";

export default function MobileIssuesKanban({ groupedIssues }: IssuesKanbanProps) {
const [activeStatus, setActiveStatus] = useState('planned')
const handleStatusChange = (status: string) => { setActiveStatus(status) }
const [activeStatus, setActiveStatus] = useState<IssueStatus>('planned')
const handleStatusChange = (status: IssueStatus) => { setActiveStatus(status) }

const issuesCount: { [key: string]: number } = {}
Object.keys(groupedIssues).forEach(status => {
Expand All @@ -16,6 +18,11 @@ export default function MobileIssuesKanban({ groupedIssues }: IssuesKanbanProps)
const issues = groupedIssues[activeStatus]

return (
<StatusSelector activeStatus={activeStatus} onStatusChange={handleStatusChange} issuesCount={issuesCount} />
<div className="flex flex-col gap-6">
<StatusSelector activeStatus={activeStatus} onStatusChange={handleStatusChange} issuesCount={issuesCount} />
<div className="px-6">
<KanbanColumn status={activeStatus} issues={issues} />
</div>
</div>
)
}
25 changes: 25 additions & 0 deletions web/src/components/kanban-column/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { KanbanColumnProps } from './types'
import { LABEL_MAPPING, DESCRIPTION_MAPPING } from '@/constants/issue-statuses'
import KanbanElement from '@/components/kanban-element'

export default function KanbanColumn({ status, issues }: KanbanColumnProps) {
return (
<div className="flex flex-col gap-6">
<div className="flex flex-col gap-1">
<h2 className="text-marian-blue font-sans font-bold text-xl">
{ LABEL_MAPPING[status] } ({ issues.length })
</h2>

<p className="text-glaucous font-sans text-xs font-normal">
{ DESCRIPTION_MAPPING[status] }
</p>
</div>

<div className="flex flex-col gap-4">
{ issues.map(issue => (
<KanbanElement issue={issue} key={issue.uuid} />
)) }
</div>
</div>
)
}
6 changes: 6 additions & 0 deletions web/src/components/kanban-column/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Issue, IssueStatus } from '@/feedbackr-api/v1/schemas'

export interface KanbanColumnProps {
issues: Issue[];
status: IssueStatus;
}
36 changes: 36 additions & 0 deletions web/src/components/kanban-element/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { KanbanElementProps } from './types'
import StatusLabel from '@/components/status-label'
import { BG_COLOR_MAPPING } from '@/constants/issue-statuses'
import CategoryLabel from '@/components/category-label'
import ISSUE_CATEGORY_LABELS from '@/constants/issue-category-labels'
import invariant from 'tiny-invariant'
import UpvoteButton from '@/components/upvote-button'
import CommentsCounter from '@/components/comments-counter'

export default function KanbanElement({ issue }: KanbanElementProps) {
const categoryLabel = ISSUE_CATEGORY_LABELS.find((category) => category.name === issue.category.name)?.label
invariant(categoryLabel, `Category label not found for category name: ${issue.category.name}`)

return (
<div className="flex flex-col gap-4 relative p-6 rounded-xl bg-white">
<div className={`absolute w-full left-0 top-0 h-1.5 rounded-tl-xl rounded-tr-xl ${BG_COLOR_MAPPING[issue.status]}`} />

<StatusLabel status={issue.status} size="small" />

<div className="flex flex-col gap-2">
<h3 className="font-sans font-bold text-xs text-marian-blue">
{ issue.title }
</h3>
<p className="font-sans font-normal text-xs text-glaucous">
{ issue.detail }
</p>
<CategoryLabel label={categoryLabel} />
</div>

<div className='flex justify-between items-center'>
<UpvoteButton issueUuid={issue.uuid} upvotes={issue.upvotes} initialActive={issue.alreadyUpvoted} />
<CommentsCounter commentsCount={issue.commentsCount} />
</div>
</div>
)
}
5 changes: 5 additions & 0 deletions web/src/components/kanban-element/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Issue } from '@/feedbackr-api/v1/schemas'

export interface KanbanElementProps {
issue: Issue;
}
4 changes: 2 additions & 2 deletions web/src/components/status-label/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { BG_COLOR_MAPPING, LABEL_MAPPING } from '@/constants/issue-statuses'
import type { StatusLabelProps } from './types'

export default function StatusLabel({ status }: StatusLabelProps) {
export default function StatusLabel({ status, size = "large" }: StatusLabelProps) {
return (
<div className="flex items-center gap-4 font-sans">
<div className={`w-2 h-2 rounded-full ${BG_COLOR_MAPPING[status]}`} />

<span className="text-base text-glaucous">
<span className={`${size === "small" ? "text-xs" : "text-base"} text-glaucous`}>
{LABEL_MAPPING[status]}
</span>
</div>
Expand Down
1 change: 1 addition & 0 deletions web/src/components/status-label/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import type { IssueStatus } from '@/feedbackr-api/v1/schemas'

export interface StatusLabelProps {
status: IssueStatus
size?: 'small' | 'large'
}
4 changes: 3 additions & 1 deletion web/src/components/status-selector/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { IssueStatus } from '@/feedbackr-api/v1/schemas'

export interface StatusSelectorProps {
activeStatus: string;
onStatusChange: (status: string) => void;
onStatusChange: (status: IssueStatus) => void;
issuesCount: { [key: string]: number };
}
4 changes: 2 additions & 2 deletions web/src/components/upvote-button/upvote-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ export default function UpvoteButton({ issueUuid, upvotes, initialActive = false
return (
<button
className={`
h-8 sm:h-14 w-20 sm:w-10 px-4 sm:px-1 p-1 font-sans text-xs font-bold rounded-xl flex flex-row sm:flex-col justify-between sm:justify-center items-center gap-2 transition-all
h-8 sm:h-14 w-14 sm:w-10 px-4 sm:px-1 p-1 font-sans text-xs font-bold rounded-xl flex flex-row sm:flex-col justify-between sm:justify-center items-center gap-2 transition-all
${selected ? 'bg-savoy-blue text-white hover:opacity-80' : 'text-marian-blue bg-ghost-white hover:bg-periwinkle'}
`}
onClick={handleClick}
type="button"
>
<div className={`w-3 ${selected ? 'text-white' : 'text-savoy-blue'}`}>
<div className={`!w-3 ${selected ? 'text-white' : 'text-savoy-blue'}`}>
<ChevronIconUp />
</div>

Expand Down
7 changes: 7 additions & 0 deletions web/src/constants/issue-statuses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,10 @@ export const LABEL_MAPPING = {
in_progress: 'In Progress',
live: 'Live'
}

export const DESCRIPTION_MAPPING = {
suggestion: 'Open suggestions that need to be triaged',
planned: 'Ideas prioritized for research',
in_progress: 'Currently being developed',
live: 'Released features'
}

0 comments on commit 3b8edfb

Please sign in to comment.