Skip to content

Commit

Permalink
Feat/offers revisited (#1157)
Browse files Browse the repository at this point in the history
* improving offer component and moving offers to the right section

* getting offers component working properly, accepting, rejecting and sending messages

* getting offers accepting and viewing
  • Loading branch information
alexanmtz authored Nov 24, 2024
1 parent 7388bad commit e5d3cb5
Show file tree
Hide file tree
Showing 11 changed files with 752 additions and 292 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import OffersList from './offers-list';

export default {
title: 'Design Library/Molecules/OffersList',
component: OffersList,
};

const Template = (args) => <OffersList {...args} />;

export const Default = Template.bind({});
Default.args = {
offers: [
{
User: {
username: 'username',
picture_url: 'https://via.placeholder.com/150',
name: 'name',
},
status: 'status',
value: 100,
suggestedDate: new Date(),
},
],
onMessage: (id) => console.log('onMessage', id),
assigned: false,
onAccept: (id) => console.log('onAccept', id),
onReject: (id) => console.log('onReject', id),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React from 'react';
import {
Button,
Chip,
Typography,
List,
ListItem,
ListItemText,
ListItemAvatar,
Avatar,
Divider
} from '@material-ui/core';
import MessageIcon from '@mui/icons-material/Message';
import MomentComponent from 'moment';
import { FormattedMessage } from 'react-intl';

interface OfferListProps {
offers: any;
onMessage?: any;
assigned?: boolean;
onAccept?: any;
onReject?: any;
viewMode?: boolean;
}


export default function OffersList({
offers,
onMessage,
assigned,
onAccept,
onReject,
viewMode
}:OfferListProps) {
const onSendMessage = (id) => {
onMessage(id);
}

return (
<List style={{ width: '100%' }}>
{offers?.map((offer) => (
<>
<ListItem alignItems="flex-start">
<ListItemAvatar>
<Avatar alt={ offer?.User?.username } src={ offer?.User?.picture_url} />
</ListItemAvatar>
<ListItemText
primary={
<>
{offer?.User?.username || offer?.User?.name}
<Chip
label={offer?.status || 'pending'}
color='secondary'
variant="default"
size='small'
style={{marginLeft: 10, display: 'inline-block'}}
/>
</>
}
secondary={
<div style={{display: 'flex', justifyContent: 'space-between'}}>
<div>
<Typography
style={{ display: 'inline-block' }}
variant="subtitle1"
color="primary"
>
{ offer?.User?.name }
</Typography>
<Typography variant="subtitle2" color="secondary" gutterBottom>
$ {offer?.value}
</Typography>
{ offer?.suggestedDate &&
<Typography variant="caption" color="secondary" gutterBottom>
Finish {MomentComponent(offer?.suggestedDate).fromNow()}
</Typography>
}
{ offer?.comment &&
<Typography variant="body1" color="secondary" component='div' gutterBottom>
Comment:<br />
{offer?.comment}
</Typography>
}
{ offer?.learn &&
<Typography variant="body1" color="secondary" gutterBottom>
<FormattedMessage id='task.learn' defaultMessage={'For learning purposes'} />
</Typography>
}
{ offer?.createdAt &&
<Typography variant="caption" color="secondary" gutterBottom>
{ MomentComponent(offer?.createdAt).fromNow() }
</Typography>
}
</div>

{ !viewMode ? (
<div>
<Button onClick={ (event) => onReject(event, offer) } disabled={assigned || offer.status === 'rejected' || offer.status === 'accepted'} variant="outlined" color="secondary" size={'small'} style={{marginRight: 20}}>
Reject
</Button>
<Button onClick={(event) => onAccept(event, offer)} disabled={assigned || offer.status === 'accepted'} variant="contained" color="primary" size={'small'} style={{marginRight: 20}}>
Accept
</Button>
<Button onClick={(e) => onSendMessage(offer.id)} variant="outlined" color="secondary" size={'small'}>
<MessageIcon fontSize='small' />
</Button>
</div>
) : null }
</div>
}
/>
</ListItem>
<Divider variant="fullWidth" component="li" />
</>
))}
</List>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { FormControl, Input, InputLabel } from "@material-ui/core";

const EmailInviteInput = ({
onEmailInviteChange
}) => {
return (
<FormControl fullWidth style={{ marginTop: 10, marginBottom: 10 }}>
<InputLabel htmlFor='email-funding-invite'>
<FormattedMessage id='task.funding.email' defaultMessage='Please provide the invitee e-mail' />
</InputLabel>
<Input
id='email'
type='email'
name='email-funding-invite'
onChange={onEmailInviteChange}
/>
</FormControl>
)
}

export default EmailInviteInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Introduction from '../../../molecules/introduction/introduction';
import IssueCard from '../../../organisms/issue-card/issue-card';
import SimpleInfo from '../../../molecules/simple-info/simple-info';
import DeliveryDate from '../../../organisms/delivery-date/delivery-date';
import PickupTagList from '../../../molecules/pickup-tag-list/pickup-tag-list';
import PricePlan from '../../../organisms/price-plan/price-plan';
import InputComment from '../../../molecules/input-comment/input-comment';
import OfferDrawerCheckboxes from './offer/offer-drawer-checkboxes';
import InviteInput from './invite/invite-input';
import { makeStyles } from '@material-ui/core';
import CheckboxTerms from '../../../molecules/checkbox-terms/checkbox-terms';

const useStyles = makeStyles(theme => ({
details: {
display: 'flex',
flexDirection: 'column'
},
spanText: {
display: 'inline-block',
verticalAlign: 'middle'
},
}));

interface OfferDrawerCreateProps {
introTitle: any;
introMessage: any;
introImage: any;
issue: any;
simpleInfoText: any;
commentAreaPlaceholder: any;
onDeliveryDateChange: any;
pickupTagListTitle: any;
pickutTagListDescription: any;
setCurrentPrice: any;
currentPrice: any;
onCommentChange: any;
offerCheckboxes: boolean;
onLearnCheckboxChange: any;
onConfirmOfferChange: any;
onTermsCheckboxChange: any;
onEmailInviteChange: any;
hasEmailInput?: boolean;
}

const OfferDrawerCreate: React.FC<OfferDrawerCreateProps> = ({
introTitle,
introMessage,
introImage,
issue,
simpleInfoText,
commentAreaPlaceholder,
onDeliveryDateChange,
pickupTagListTitle,
pickutTagListDescription,
setCurrentPrice,
currentPrice,
onCommentChange,
offerCheckboxes,
onLearnCheckboxChange,
onConfirmOfferChange,
onTermsCheckboxChange,
onEmailInviteChange,
hasEmailInput = false
}) => {

const classes = useStyles();

return (
<>
<Introduction
title={introTitle}
image={introImage}
>
<span className={classes.spanText}>
{introMessage}
</span>
</Introduction>
<IssueCard issue={issue} />
<SimpleInfo text={
simpleInfoText
} />
{hasEmailInput && <InviteInput onEmailInviteChange={onEmailInviteChange} />}
<DeliveryDate
date={issue.data.deadline}
onDateChange={onDeliveryDateChange}
/>
<PickupTagList
primaryText={
pickupTagListTitle
}
secondaryText={
pickutTagListDescription
}
onPickItem={(price) => setCurrentPrice(price)}
/>
<PricePlan plan={
{
fee: 8,
category: <FormattedMessage id='actions.task.payment.plan.opensource' defaultMessage='Open Source' />,
title: <FormattedMessage id='actions.task.payment.plan.opensource.info' defaultMessage='For Open Source Project' />,
items: [
<FormattedMessage id='actions.task.payment.plan.bullet.public' defaultMessage='For Public Projects' />,
<FormattedMessage id='actions.task.payment.plan.bullet.basic' defaultMessage='Basic Campaign' />,
],
}
} price={currentPrice} onChange={(price) => setCurrentPrice(price)} />
<InputComment
placeholder={commentAreaPlaceholder}
onChange={onCommentChange}
/>
{offerCheckboxes &&
<OfferDrawerCheckboxes
currentPrice={currentPrice}
onLearnCheckboxChange={onLearnCheckboxChange}
onConfirmOfferChange={onConfirmOfferChange}
/>
}
<CheckboxTerms
onAccept={onTermsCheckboxChange}
/>
</>
);
};

export default OfferDrawerCreate;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React, { useState } from 'react';
import { Tab, Tabs } from "@material-ui/core";


const OfferDrawerTabs = ({ tabs, onTabChange }) => {
const [tabValue, setTabValue] = useState(0)

const handleChange = (event, newValue) => {
setTabValue(newValue)
onTabChange(newValue)
}

return (
<>
<Tabs
value={tabValue}
onChange={handleChange}
indicatorColor='secondary'
textColor='secondary'
>
{tabs.map((tab) => <Tab label={tab.label} value={tab.value} />)}
</Tabs>
{tabs.map((tab) => tab.value === tabValue && tab.component)}
</>
);
}

export default OfferDrawerTabs;
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,21 @@ Primary.args = {
}
}
};

export const WithTabs = Template.bind({});
WithTabs.args = {
...Primary.args,
offers: [
{
User: {
username: 'username',
picture_url: 'https://via.placeholder.com/150',
name: 'name',
},
status: 'status',
value: 100,
suggestedDate: new Date(),
},
],
tabs: true,
};
Loading

0 comments on commit e5d3cb5

Please sign in to comment.