Skip to content
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

feat: project personnel view #43

Merged
merged 6 commits into from
May 21, 2024
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
4 changes: 2 additions & 2 deletions src/clients/Governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
NewProposalTender,
PendingProposalsQuery,
PriorityProposal,
ProjectAttributes,
Project,
ProposalAttributes,
ProposalCommentsInDiscourse,
ProposalListFilter,
Expand Down Expand Up @@ -188,7 +188,7 @@ export class Governance extends API {
return proposals
}
async getProject(projectId: string) {
return await this.fetchApiResponse<ProjectAttributes>(`/projects/${projectId}`)
return await this.fetchApiResponse<Project>(`/projects/${projectId}`)
}

async getOpenPitchesTotal() {
Expand Down
16 changes: 16 additions & 0 deletions src/components/Common/Typography/Text.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@
font-stretch: normal;
}

.Text.Text--transform-none {
text-transform: none;
}

.Text.Text--transform-uppercase {
text-transform: uppercase;
}

.Text.Text--transform-lowercase {
text-transform: lowercase;
}

.Text.Text--transform-capitalize {
text-transform: capitalize;
}

.Text.Text--size-xs {
font-size: 11px;
line-height: 16px;
Expand Down
4 changes: 4 additions & 0 deletions src/components/Common/Typography/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type FontSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
export type FontWeight = 'bold' | 'semi-bold' | 'normal' | 'medium' | 'light'
type TextColor = 'default' | 'primary' | 'secondary' | 'error' | 'white-900'
type FontStyle = 'normal' | 'italic'
type TransformOptions = 'uppercase' | 'lowercase' | 'capitalize' | 'none'

interface Props {
children?: React.ReactNode
Expand All @@ -22,6 +23,7 @@ interface Props {
style?: FontStyle
as?: 'span'
title?: string
transform?: TransformOptions
}

const Text = React.forwardRef<HTMLParagraphElement, Props>(
Expand All @@ -35,6 +37,7 @@ const Text = React.forwardRef<HTMLParagraphElement, Props>(
className,
as,
title,
transform = 'none',
},
ref
) => {
Expand All @@ -44,6 +47,7 @@ const Text = React.forwardRef<HTMLParagraphElement, Props>(
`Text--weight-${weight}`,
`Text--color-${color}`,
`Text--style-${style}`,
`Text--transform-${transform}`,
className
)
const Component = as ?? 'p'
Expand Down
2 changes: 1 addition & 1 deletion src/components/GrantRequest/BreakdownAccordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import ChevronRightCircleOutline from '../Icon/ChevronRightCircleOutline'
import './BreakdownAccordion.css'

export interface BreakdownItem {
title: string
title: React.ReactNode
subtitle: string
value?: string
content: React.ReactNode
Expand Down
6 changes: 3 additions & 3 deletions src/components/GrantRequest/GrantRequestTeamSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react'
import isEmpty from 'lodash/isEmpty'

import useFormatMessage from '../../hooks/useFormatMessage'
import { GrantRequestTeam, TeamMember } from '../../types/grants'
import { ProposalRequestTeam, TeamMember } from '../../types/grants'
import { userModifiedForm } from '../../utils/proposal'
import SubLabel from '../Common/SubLabel'
import Label from '../Common/Typography/Label'
Expand All @@ -13,13 +13,13 @@ import AddBox from './AddBox'
import AddTeamMemberModal from './AddTeamMemberModal'
import BreakdownItem from './BreakdownItem'

export const INITIAL_GRANT_REQUEST_TEAM_STATE: GrantRequestTeam = {
export const INITIAL_GRANT_REQUEST_TEAM_STATE: ProposalRequestTeam = {
members: [],
}

interface Props {
sectionNumber: number
onValidation: (data: GrantRequestTeam, sectionValid: boolean) => void
onValidation: (data: ProposalRequestTeam, sectionValid: boolean) => void
isDisabled?: boolean
}

Expand Down
6 changes: 3 additions & 3 deletions src/components/Icon/Open.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
function Open({ className }: { className?: string }) {
function Open({ className, size = 12 }: { className?: string; size?: number }) {
return (
<svg
width="12"
height="12"
width={size}
height={size}
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
Expand Down
35 changes: 35 additions & 0 deletions src/components/Projects/EditableBreakdownContent.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.EditableBreakdownContent__Text {
color: var(--black-600);
font-size: 15px;
font-style: normal;
font-weight: 400;
line-height: 24px;
padding: 10px 0;
}

.EditableBreakdownContent__Footer {
display: flex;
justify-content: space-between;
align-items: end;
}

.RelevantLink {
display: flex;
padding: 5px 9px;
justify-content: center;
align-items: center;
gap: 4px;
border-radius: 6px;
background: var(--red-200);
max-width: 120px;
}

.RelevantLink__Text {
color: var(--primary);
text-align: center;
font-size: 11px;
font-style: normal;
font-weight: 600;
line-height: 18px; /* 163.636% */
text-transform: uppercase;
}
38 changes: 38 additions & 0 deletions src/components/Projects/EditableBreakdownContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Button } from 'decentraland-ui/dist/components/Button/Button'

import useFormatMessage from '../../hooks/useFormatMessage.ts'
import Link from '../Common/Typography/Link.tsx'
import Open from '../Icon/Open.tsx'

import './EditableBreakdownContent.css'

interface Props {
about: string
relevantLink?: string
onClick: () => void
}

function EditableBreakdownContent({ about, relevantLink, onClick }: Props) {
const t = useFormatMessage()

return (
<div>
<div className="EditableBreakdownContent__Text">{about}</div>
<div className="EditableBreakdownContent__Footer">
{relevantLink ? (
<Link className="RelevantLink" href={relevantLink} target="_blank">
<div className="RelevantLink__Text">{t('component.expandable_breakdown_item.relevant_link_label')}</div>
<Open size={10} />
</Link>
) : (
<div></div>
)}
<Button basic onClick={onClick}>
{t('component.expandable_breakdown_item.edit_action_label')}
</Button>
</div>
</div>
)
}

export default EditableBreakdownContent
43 changes: 43 additions & 0 deletions src/components/Projects/EditablePersonnelView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useMemo } from 'react'

import useFormatMessage from '../../hooks/useFormatMessage.ts'
import { TeamMember } from '../../types/grants.ts'
import Username from '../Common/Username.tsx'
import { BreakdownItem } from '../GrantRequest/BreakdownAccordion.tsx'

import EditableBreakdownContent from './EditableBreakdownContent.tsx'
import ExpandableBreakdownItem from './ExpandableBreakdownItem.tsx'
import ProjectSidebarSectionTitle from './ProjectSidebarSectionTitle.tsx'

interface Props {
members: TeamMember[]
}

function EditablePersonnelView({ members }: Props) {
const t = useFormatMessage()

function getTitle(name: string, address?: string) {
return address && address.length > 0 ? <Username address={address} size="sm" linked variant="address" /> : name
}

const items = useMemo(
() =>
members.map<BreakdownItem>(({ name, role, about, relevantLink, address }) => ({
title: getTitle(name, address),
subtitle: role,
content: <EditableBreakdownContent about={about} onClick={() => {}} relevantLink={relevantLink} />,
})),
[members]
)

return (
<>
<ProjectSidebarSectionTitle text={t('page.proposal_view.grant.personnel_title')} />
{items.map((item, key) => {
return <ExpandableBreakdownItem key={key} item={item} />
})}
</>
)
}

export default EditablePersonnelView
36 changes: 36 additions & 0 deletions src/components/Projects/ExpandableBreakdownItem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.ExpandableBreakdownItem {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
background: var(--white-900);
margin-bottom: 16px;
padding: 16px;
min-height: 64px;
border: 1px solid var(--black-300);
box-shadow: 0 1px 4px var(--alpha-black-300);
border-radius: 8px;
}

.ExpandableBreakdownItem__Header {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
width: 100%;
}

.ExpandableBreakdownItem__Content {
display: none;
min-height: 64px;
}

.ExpandableBreakdownItem__Content--expanded {
display: block;
align-items: center;
justify-content: space-between;
margin-top: 16px;
background: var(--white-900);
width: 100%;
border-top: 1px solid var(--black-300);
}
51 changes: 51 additions & 0 deletions src/components/Projects/ExpandableBreakdownItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useState } from 'react'

import classNames from 'classnames'

import ChevronRightCircleOutline from '../Icon/ChevronRightCircleOutline.tsx'

import './ExpandableBreakdownItem.css'

interface ExpandableBreakdownItemProps {
title: React.ReactNode
subtitle: string
content: React.ReactNode
}

interface Props {
item: ExpandableBreakdownItemProps
initiallyExpanded?: boolean
}

function ExpandableBreakdownItem({ item, initiallyExpanded = false }: Props) {
const { title, subtitle, content } = item
const [isActive, setIsActive] = useState(initiallyExpanded)

return (
<div className="ExpandableBreakdownItem">
<div role="button" className="ExpandableBreakdownItem__Header" onClick={() => setIsActive((prev) => !prev)}>
<div>
<div className="BreakdownItem__Title">{title}</div>
<div className="BreakdownItem__Subtitle">{subtitle}</div>
</div>
<div>
<span>
<ChevronRightCircleOutline
className={classNames('BreakdownAccordion__Arrow', isActive && 'BreakdownAccordion__Arrow--selected')}
/>
</span>
</div>
</div>
<div
className={classNames(
'ExpandableBreakdownItem__Content',
isActive && 'ExpandableBreakdownItem__Content--expanded'
)}
>
{content}
</div>
</div>
)
}

export default ExpandableBreakdownItem
18 changes: 18 additions & 0 deletions src/components/Projects/ProjectGeneralInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Project } from '../../types/proposals.ts'

import EditablePersonnelView from './EditablePersonnelView.tsx'
import './ProjectSidebar.css'

interface Props {
project: Project
}

function ProjectGeneralInfo({ project }: Props) {
return (
<div className="ProjectSidebar__ContentContainer">
<EditablePersonnelView members={project.personnel} />
</div>
)
}

export default ProjectGeneralInfo
7 changes: 2 additions & 5 deletions src/components/Projects/ProjectSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import useProject from '../../hooks/useProject.ts'
import BoxTabs from '../Common/BoxTabs'
import GovernanceSidebar from '../Sidebar/GovernanceSidebar'

import ProjectGeneralInfo from './ProjectGeneralInfo.tsx'
import ProjectSheetTitle from './ProjectSheetTitle.tsx'
import './ProjectSidebar.css'

Expand Down Expand Up @@ -33,11 +34,7 @@ function ProjectSidebar({ projectId, isSidebarVisible, onClose }: Props) {
<BoxTabs.Tab active={false}>Activity</BoxTabs.Tab>
</BoxTabs.Left>
</BoxTabs>
<div className="ProjectSidebar__ContentContainer">
{/*{hasUpdates && (*/}
{/* <ProposalUpdate expanded={false} index={updates.length} update={updates[0]} proposal={proposal} showHealth />*/}
{/*)}*/}
</div>
{project && <ProjectGeneralInfo project={project} />}
</GovernanceSidebar>
)
}
Expand Down
15 changes: 15 additions & 0 deletions src/components/Projects/ProjectSidebarSectionTitle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Text from '../Common/Typography/Text.tsx'

interface Props {
text: string
}

function ProjectSidebarSectionTitle({ text }: Props) {
return (
<Text size="sm" color="default" weight="semi-bold" transform="uppercase">
{text}
</Text>
)
}

export default ProjectSidebarSectionTitle
4 changes: 4 additions & 0 deletions src/intl/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,10 @@
"markdown_field": {
"preview_button": "Preview",
"edit_button": "Edit"
},
"expandable_breakdown_item": {
"relevant_link_label": "Relevant Link",
"edit_action_label": "Edit"
}
},
"page": {
Expand Down
Loading
Loading