Skip to content

Commit

Permalink
chore: add bounty card
Browse files Browse the repository at this point in the history
  • Loading branch information
jordan-ae committed Dec 27, 2024
1 parent 6206317 commit 115b11b
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 3 deletions.
40 changes: 40 additions & 0 deletions cypress/e2e/62_BountyCard.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// cypress/e2e/bountyCard.spec.js
describe('BountyCardComponent', () => {
beforeEach(() => {
cy.viewport(500, 800);
});

it('renders correctly with given props', () => {
const props = {
id: 'bounty123',
title: 'Test Bounty Card',
features: { name: 'Feature A' },
phase: { name: 'Phase 1' },
assignee_img: 'https://via.placeholder.com/40',
workspace: { name: 'Workspace X' },
onTitleClick: cy.stub()
};

cy.get('h3').should('contain', props.title);
cy.get('span').should('contain', props.features.name);
cy.get('span').should('contain', props.phase.name);
cy.get('span').should('contain', props.workspace.name);
cy.get('img').should('have.attr', 'src', props.assignee_img);
});

it('triggers onTitleClick when title is clicked', () => {
const onTitleClick = cy.stub();
const props = {
id: 'bounty123',
title: 'Clickable Title',
features: {},
phase: {},
assignee_img: '',
workspace: {},
onTitleClick
};

cy.get('h3').click();
cy.wrap(onTitleClick).should('be.calledWith', 'bounty123');
});
});
145 changes: 145 additions & 0 deletions src/people/WorkSpacePlanner/BountyCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Senior-level React implementation of BountyCardComponent
import React from 'react';
import styled from 'styled-components';
import PropTypes from 'prop-types';
import { BountyCard } from 'store/interface';
import { colors } from '../../../config';

const Card = styled.div`
width: 384px;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
display: flex;
flex-direction: column;
background-color: ${colors.light.grayish.G950};
transition:
box-shadow 0.3s ease,
border 0.3s ease;
&:hover {
border: 1px solid ${colors.light.light_blue100};
box-shadow: 0 0 5px 1px ${colors.light.light_blue200};
}
`;

const Row = styled.div`
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 14px;
font-weight: 400;
margin-bottom: 8px;
color: ${colors.light.text2};
span {
margin-right: 20%;
white-space: nowrap;
}
.span {
margin-left: auto;
justify-content: flex-end;
}
`;

const Header = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
`;

const CardTitle = styled.h3`
font-size: 20px;
font-weight: 700;
padding-right: 16px;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
text-align: left;
color: ${colors.light.text1};
&:hover {
color: ${colors.light.primaryColor};
}
`;

const AssignerPic = styled.div`
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
background-color: ${colors.light.red1};
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
color: white;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
`;

interface BountyCardProps extends BountyCard {
onclick: (bountyId: string) => void;
}

const BountyCardComp = ({
id,
title,
features,
phase,
assigneePic,
workspace,
onclick
}: BountyCardProps) => {
const handleTitleClick = (
event: React.MouseEvent<HTMLHeadingElement> | React.KeyboardEvent<HTMLHeadingElement>
) => {
event.preventDefault();
onclick(id);
};

return (
<Card>
<Header>
<CardTitle onClick={handleTitleClick}>{title}</CardTitle>
<AssignerPic>{assigneePic ? <img src={assigneePic} alt="Assigner" /> : 'Pic'}</AssignerPic>
</Header>

<Row>
<span>{features?.name ?? 'No Feature'}</span>
<span>{phase?.name ?? 'No Phase'}</span>
</Row>
<Row>
<span>{id}</span>
<span>{workspace?.name ?? 'No Workspace'}</span>
<span className="span">Paid?</span>
</Row>
</Card>
);
};

BountyCardComp.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
features: PropTypes.shape({
name: PropTypes.string
}),
phase: PropTypes.shape({
name: PropTypes.string
}),
assignee_img: PropTypes.string,
workspace: PropTypes.shape({
name: PropTypes.string
}),
onclick: PropTypes.func.isRequired
};

export default BountyCardComp;
10 changes: 7 additions & 3 deletions src/people/WorkSpacePlanner/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import { EuiLoadingSpinner } from '@elastic/eui';
import styled from 'styled-components';
import { useBountyCardStore } from 'store/bountyCard';
import { BountyCard } from 'store/interface';
import history from 'config/history';
import { useStores } from '../../store';
import { colors } from '../../config';
import { WorkspacePlannerHeader } from './WorkspacePlannerHeader';
import BountyCardComp from './BountyCard';

const PlannerContainer = styled.div`
padding: 0;
Expand Down Expand Up @@ -67,6 +69,10 @@ const WorkspacePlanner = () => {
);
}

const onclick = (bountyId: string) => {
history.push(`/bounty/${bountyId}`);
};

return (
<PlannerContainer>
<WorkspacePlannerHeader workspace_uuid={uuid} workspaceData={workspaceData} />
Expand All @@ -80,9 +86,7 @@ const WorkspacePlanner = () => {
) : (
<BountyCardList>
{bountyCardStore.bountyCards.map((card: BountyCard) => (
<li key={card.id}>
<strong>{card.title}</strong>
</li>
<BountyCardComp key={card.id} {...card} onclick={onclick} />
))}
</BountyCardList>
)}
Expand Down
1 change: 1 addition & 0 deletions src/store/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -511,4 +511,5 @@ export interface BountyCard {
features: Feature;
phase: Phase;
workspace: Workspace;
assigneePic: string;
}

0 comments on commit 115b11b

Please sign in to comment.