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

expiring offers ui fixes #2167

Merged
merged 1 commit into from
Sep 25, 2023
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
13 changes: 11 additions & 2 deletions packages/gui/src/components/nfts/NFTCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { IconButton, Flex } from '@chia-network/core';
import { Color, IconButton, Flex } from '@chia-network/core';
import { MoreVert } from '@mui/icons-material';
import { Card, CardActionArea, CardContent, Checkbox, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import React, { useMemo, memo } from 'react';
import { useNavigate } from 'react-router-dom';

Expand Down Expand Up @@ -38,6 +39,7 @@ function NFTCard(props: NFTCardProps) {
const nftId = useMemo(() => getNFTId(id), [id]);

const [isNFTHidden] = useHiddenNFTs();
const theme = useTheme();
const navigate = useNavigate();

const { nft, isLoading } = useNFT(nftId);
Expand All @@ -58,7 +60,14 @@ function NFTCard(props: NFTCardProps) {

return (
<Flex flexDirection="column" flexGrow={1} minWidth={0}>
<Card sx={{ borderRadius: '8px', opacity: isHidden ? 0.5 : 1 }} variant="outlined">
<Card
sx={{
borderRadius: '8px',
borderColor: theme.palette.mode === 'light' ? Color.Neutral[300] : Color.Neutral[700],
opacity: isHidden ? 0.5 : 1,
}}
variant="outlined"
>
<CardActionArea onClick={handleClick}>
{onSelect && (
<Checkbox
Expand Down
156 changes: 90 additions & 66 deletions packages/gui/src/components/offers2/OfferBuilderExpirationSection.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
import { useLocalStorage } from '@chia-network/api-react';
import { Button, Color, Flex, Form, TextField } from '@chia-network/core';
import { Button, Color, Flex, Form, Link, TextField } from '@chia-network/core';
import { Hourglass as HourglassIcon } from '@chia-network/icons';
import { useIsWalletSynced } from '@chia-network/wallets';
import { Trans, t } from '@lingui/macro';
import { plural, Trans, t } from '@lingui/macro';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined';
import {
Accordion,
AccordionDetails,
AccordionSummary,
Alert,
AlertTitle,
Badge,
Grid,
Typography,
} from '@mui/material';
import { Accordion, AccordionDetails, AccordionSummary, Alert, Badge, Grid, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import React from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { useNavigate } from 'react-router';

import useOfferExpirationDefaultTime, {
getOfferExpirationTimeInSeconds,
Expand All @@ -40,8 +32,28 @@ type SetExpirationData = {
minutes: string | number;
};

function ViewTitle({ expirationValues, willExpirationBeEnabled }: any) {
const displayDays = Number(expirationValues[0]) > 0 ? expirationValues[0] : null;
const displayDaysText = displayDays ? plural(displayDays, { one: 'day', other: 'days' }) : null;
const displayHours = Number(expirationValues[1]) > 0 ? expirationValues[1] : null;
const displayHoursText = displayHours ? plural(displayHours, { one: 'hour', other: 'hours' }) : null;
const displayMinutes = Number(expirationValues[2]) > 0 ? expirationValues[2] : null;
const displayMinutesText = displayMinutes ? plural(displayMinutes, { one: 'minute', other: 'minutes' }) : null;
const hoursComma = displayDays && (displayHours || displayMinutes) ? ', ' : null;
const minutesComma = displayHours && displayMinutes ? ', ' : null;
const displayText = willExpirationBeEnabled
? t`This offer will expire in ${displayDays} ${displayDaysText}${hoursComma} ${displayHours} ${displayHoursText}${minutesComma} ${displayMinutes} ${displayMinutesText}`
: t`This offer will not expire`;
return (
<Flex>
<Typography variant="subtitle2">{displayText}</Typography>
</Flex>
);
}

export default function OfferBuilderExpirationSection(props: OfferExpirationProps) {
const theme = useTheme();
const navigate = useNavigate();
const {
isViewing,
canCounter,
Expand Down Expand Up @@ -76,7 +88,7 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
});

const willExpirationBeEnabled = expirationValues.map((value) => Number(value)).some((value) => value > 0);
const [isExpirationExpanded, setIsExpirationExpanded] = React.useState<boolean>(willExpirationBeEnabled);
const [isExpirationExpanded, setIsExpirationExpanded] = React.useState<boolean>(false);

const isExpired = expirationTime < currentTime;

Expand All @@ -86,6 +98,10 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
{ name: 'minutes', label: t`Minutes`, max: 60 },
];

async function handleNavToSettings() {
navigate('/dashboard/settings/general');
}

function setExpirationTime() {
const formatTime = { days: expirationValues[0], hours: expirationValues[1], minutes: expirationValues[2] };
const timeInSeconds = getOfferExpirationTimeInSeconds(formatTime);
Expand Down Expand Up @@ -116,7 +132,8 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
item
border={1}
borderColor={theme.palette.mode === 'light' ? Color.Neutral[300] : Color.Neutral[600]}
borderRadius={1}
borderRadius={2}
overflow="hidden"
>
<Accordion
expanded={isExpirationExpanded}
Expand All @@ -126,7 +143,7 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
}
setIsExpirationExpanded(isExpanded);
}}
sx={{ boxShadow: 'none' }}
sx={{ boxShadow: 'none', bgcolor: 'transparent' }}
>
<AccordionSummary
expandIcon={<ExpandMoreIcon color="info" />}
Expand All @@ -144,48 +161,69 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
}}
invisible={wasOfferExpirationVisited}
>
<Typography variant="subtitle2">
<Trans>Add option to set expiration time {canCounter ? ' to counteroffer' : null}</Trans>
</Typography>
<Flex flexDirection="row" alignItems="center" gap="0.5rem" paddingTop="0px" bgcolor="none">
<Flex
height="32px"
width="32px"
bgcolor={theme.palette.mode === 'light' ? Color.Neutral[200] : Color.Neutral[700]}
borderRadius="10px"
justifyContent="center"
alignItems="center"
>
<Flex marginTop="12px">
<HourglassIcon color="info" sx={{ fontSize: '32px' }} />
</Flex>
</Flex>
<ViewTitle expirationValues={expirationValues} willExpirationBeEnabled={willExpirationBeEnabled} />
</Flex>
</Badge>
</AccordionSummary>
<AccordionDetails>
<Alert
severity="info"
sx={{
marginBottom: 3,
backgroundColor: theme.palette.mode === 'light' ? Color.Neutral[200] : Color.Neutral[700],
}}
<Flex
flexDirection="row"
justifyContent="space-between"
width="100%"
bgcolor={theme.palette.mode === 'light' ? Color.Neutral[200] : Color.Neutral[700]}
borderRadius="10px"
padding="1rem"
>
<Trans>
- Set a time after which the offer expires.
<br />- An expiring offer can only be claimed prior to the expiration time.
</Trans>
</Alert>
<Flex gap={2}>
{fields.map((field) => (
<TextField
name={field.name}
key={field.name}
label={field.label}
type="number"
size="small"
InputProps={{
inputProps: {
min: 0,
step: 1,
max: field.max,
},
}}
data-testid={`WalletSend-${field.name}`}
sx={{ width: 100 }}
onChange={setExpirationTime()}
/>
))}
{willExpirationBeEnabled && (
<Flex flexDirection="column" gap={1}>
<Typography variant="h6" fontWeight="500">
<Trans>Offer Expiration</Trans>
</Typography>
<Typography variant="body2" color="textSecondary">
<Trans>Set a time after which this offer expires.</Trans>
<br />
<Link onClick={handleNavToSettings}>
<Trans>Change default timing.</Trans>
</Link>
</Typography>
</Flex>
<Flex alignSelf="center" gap={2}>
{fields.map((field) => (
<TextField
name={field.name}
key={field.name}
label={field.label}
type="number"
size="small"
InputProps={{
inputProps: {
min: 0,
step: 1,
max: field.max,
},
}}
data-testid={`WalletSend-${field.name}`}
sx={{ width: 100 }}
onChange={setExpirationTime()}
/>
))}
<Button
variant="outlined"
type="submit"
disabled={!willExpirationBeEnabled}
color="primary"
onClick={() => {
methods.setValue('days', 0);
methods.setValue('hours', 0);
Expand All @@ -194,22 +232,8 @@ export default function OfferBuilderExpirationSection(props: OfferExpirationProp
>
<Trans>Disable</Trans>
</Button>
)}
</Flex>
</Flex>
{willExpirationBeEnabled && (
<Alert severity="info" sx={{ marginTop: 3 }} icon={<ReportProblemOutlinedIcon />}>
<AlertTitle>
<Trans>
Expiration time will be {isViewing && canCounter ? 'applied to counteroffer.' : 'applied.'}
</Trans>
</AlertTitle>
</Alert>
)}
{!willExpirationBeEnabled && (
<Typography component="div" variant="subtitle2" sx={{ width: '100%', marginTop: 3 }}>
<Trans>This offer will never expire. </Trans>{' '}
</Typography>
)}
</AccordionDetails>
</Accordion>
</Grid>
Expand Down
8 changes: 8 additions & 0 deletions packages/icons/src/Hourglass.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SvgIcon, SvgIconProps } from '@mui/material';
import React from 'react';

import HourglassIcon from './images/Hourglass.svg';

export default function Hourglass(props: SvgIconProps) {
return <SvgIcon component={HourglassIcon} viewBox="0 0 16 27" {...props} />;
}
3 changes: 3 additions & 0 deletions packages/icons/src/images/Hourglass.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions packages/icons/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as Fees } from './Fees';
export { default as FullNode } from './FullNode';
export { default as Harvest } from './Harvest';
export { default as Home } from './Home';
export { default as Hourglass } from './Hourglass';
export { default as Keys } from './Keys';
export { default as LinkSmall } from './Link';
export { default as MyContacts } from './MyContacts';
Expand Down