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: allow seller to remove and drag a supported jurisdiction while creating a product and make them optional #965

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
6 changes: 4 additions & 2 deletions src/components/product/Preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export default function Preview({
<DetailGrid>
{(values.shippingInfo.returnPeriod ||
(values?.shippingInfo?.jurisdiction?.length > 0 &&
values?.shippingInfo?.jurisdiction[0]?.region?.length >
(values?.shippingInfo?.jurisdiction[0]?.region?.length ?? 0) >
0)) && (
<div>
<Typography tag="h3">Shipping information</Typography>
Expand All @@ -251,7 +251,9 @@ export default function Preview({
</Typography>
<DetailTable
data={map(
values?.shippingInfo?.jurisdiction,
values?.shippingInfo?.jurisdiction.filter(
(v) => v.time && v.region
),
({ region, time }) => {
return {
name: region,
Expand Down
159 changes: 88 additions & 71 deletions src/components/product/ShippingInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { arrayMoveImmutable } from "array-move";
import { FieldArray } from "formik";
import { Plus } from "phosphor-react";
import { useEffect, useMemo, useState } from "react";
import { Plus, X } from "phosphor-react";
import { useMemo } from "react";
import SortableList, { SortableItem } from "react-easy-sort";
import styled from "styled-components";

import Collapse from "../../components/collapse/Collapse";
Expand All @@ -25,7 +27,8 @@ import {

const FieldContainerJurisdictions = styled.div`
display: grid;
grid-template-columns: minmax(150px, 1fr) 3fr;
grid-template-columns: minmax(150px, 1fr) 3fr min-content;
align-items: start;
grid-gap: 1rem;
margin-bottom: 1rem;
`;
Expand Down Expand Up @@ -64,99 +67,113 @@ const checkLastElementIsPristine = (
elements: ShippingInfoType["shippingInfo"]["jurisdiction"]
): boolean => {
const element = elements[elements.length - 1];
return element?.region.length === 0 || element?.time.length === 0;
return element?.region?.length === 0 || element?.time?.length === 0;
};

const AddSupportedJurisdictions = () => {
const { values } = useForm();
const { values, setFieldValue, setFieldTouched, handleBlur } = useForm();

const jurisdictions = useMemo(
() => values?.shippingInfo?.jurisdiction,
[values?.shippingInfo?.jurisdiction]
);

const onSortEnd = (oldIndex: number, newIndex: number) => {
if (!jurisdictions) {
return;
}
setFieldValue(
"shippingInfo.jurisdiction",
arrayMoveImmutable(jurisdictions, oldIndex, newIndex)
);
};
return (
<FormField
title="Supported jurisdictions"
subTitle="Select the jurisdictions you will ship to."
>
<FieldArray
name="shippingInfo.jurisdiction"
render={(arrayHelpers) => {
const render = jurisdictions && jurisdictions.length > 0;
<SortableList onSortEnd={onSortEnd} draggedItemClassName="dragged">
<FieldArray
name="shippingInfo.jurisdiction"
render={(arrayHelpers) => {
const render = jurisdictions && jurisdictions.length > 0;

return (
<>
{render && (
<>
{jurisdictions.map((_, index) => (
<FieldContainerJurisdictions
key={`field_container_jurisdictions_${index}`}
>
<div>
<Input
placeholder="Region"
name={`shippingInfo.jurisdiction[${index}].region`}
/>
</div>
<div>
<Input
placeholder="Time"
name={`shippingInfo.jurisdiction[${index}].time`}
/>
</div>
</FieldContainerJurisdictions>
))}
</>
)}
{!checkLastElementIsPristine(jurisdictions) && (
<Button
onClick={() => arrayHelpers.push({ region: "", time: "" })}
theme="blankSecondary"
style={{ borderBottom: `1px solid ${colors.border}` }}
>
Add new <Plus size={18} />
</Button>
)}
</>
);
}}
/>
return (
<>
{render && (
<>
{jurisdictions.map((_, index, array) => (
<SortableItem
key={`field_container_jurisdictions_${index}`}
>
<FieldContainerJurisdictions>
<div>
<Input
placeholder="Region"
name={`shippingInfo.jurisdiction[${index}].region`}
onBlur={(e) => {
handleBlur(e);
setFieldTouched(
`shippingInfo.jurisdiction[${index}].time`,
true
);
}}
/>
</div>
<div>
<Input
placeholder="Time"
name={`shippingInfo.jurisdiction[${index}].time`}
onBlur={(e) => {
handleBlur(e);
setFieldTouched(
`shippingInfo.jurisdiction[${index}].region`,
true
);
}}
/>
</div>
{array.length > 1 && (
<div style={{ alignSelf: "center" }}>
<X
size={14}
style={{ cursor: "pointer" }}
onClick={() => {
arrayHelpers.remove(index);
}}
/>
</div>
)}
</FieldContainerJurisdictions>
</SortableItem>
))}
</>
)}
{!checkLastElementIsPristine(jurisdictions) && (
<Button
onClick={() => arrayHelpers.push({ region: "", time: "" })}
theme="blankSecondary"
style={{ borderBottom: `1px solid ${colors.border}` }}
>
Add new <Plus size={18} />
</Button>
)}
</>
);
}}
/>
</SortableList>
</FormField>
);
};

const validJurisdiction = (
jurisdictionElements: ShippingInfoType["shippingInfo"]["jurisdiction"]
): boolean => {
const validation = jurisdictionElements.some(({ time, region }) => {
return (
(region.length === 0 && time.length > 0) ||
(time.length === 0 && region.length > 0)
);
});
return !validation;
};

export default function ShippingInfo() {
const { values, nextIsDisabled } = useForm();
const [isValidJurisdiction, setIsValidJurisdiction] = useState<boolean>(true);

const unit = useMemo(
() => (values?.shippingInfo?.measurementUnit?.value || "").toUpperCase(),
[values?.shippingInfo?.measurementUnit?.value]
);

const jurisdictionElements = useMemo(
() => values?.shippingInfo?.jurisdiction,
[values?.shippingInfo?.jurisdiction]
);

useEffect(() => {
const isValid = validJurisdiction(jurisdictionElements);
setIsValidJurisdiction(isValid);
}, [jurisdictionElements]);

const lwh = useMemo(
() =>
`${values?.shippingInfo?.length || 0}${
Expand Down Expand Up @@ -302,7 +319,7 @@ export default function ShippingInfo() {
<BosonButton
variant="primaryFill"
type="submit"
disabled={nextIsDisabled || !isValidJurisdiction}
disabled={nextIsDisabled}
>
Next
</BosonButton>
Expand Down
7 changes: 4 additions & 3 deletions src/components/product/utils/useInitialValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,10 @@ function loadExistingProduct<T extends CreateProductForm>(
? {
voucherValidDurationInDays:
Number(firstOffer.voucherValidDuration) / 86400,
redemptionPeriod: dayjs(
getDateTimestamp(firstOffer.voucherRedeemableFromDate)
),
redemptionPeriod:
firstOffer.voucherRedeemableFromDate === "0"
? undefined
: dayjs(getDateTimestamp(firstOffer.voucherRedeemableFromDate)),
offerValidityPeriod: dayjs(getDateTimestamp(firstOffer.validFromDate))
}
: {
Expand Down
16 changes: 14 additions & 2 deletions src/components/product/utils/validationSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,8 +537,20 @@ export const shippingInfoValidationSchema = Yup.object({
// }).default([{ value: "", label: "" }]),
jurisdiction: Yup.array(
Yup.object({
region: Yup.string().required(validationMessage.required),
time: Yup.string().required(validationMessage.required)
region: Yup.string().test({
message: "Region is required if time is defined",
test: function (value, context) {
const { time } = context.parent;
return !(!value && time);
}
}),
time: Yup.string().test({
message: "Time is required if region is defined",
test: function (value, context) {
const { region } = context.parent;
return !(!value && region);
}
})
})
).default([{ region: "", time: "" }]),
returnPeriod: Yup.string()
Expand Down
32 changes: 18 additions & 14 deletions src/pages/create-product/CreateProductInner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -626,19 +626,22 @@ function CreateProductInner({
});

const supportedJurisdictions: Array<SupportedJuridiction> =
shippingInfo.jurisdiction.reduce((prev, { region, time }) => {
if (region.length === 0 || time.length === 0) {
return prev;
} else {
return [
...prev,
{
label: region,
deliveryTime: time
}
];
}
}, [] as Array<SupportedJuridiction>);
shippingInfo.jurisdiction
.filter((v) => v.time && v.region)
.reduce((prev, current) => {
const { region, time } = current;
if (!region || region.length === 0 || !time || time.length === 0) {
return prev;
} else {
return [
...prev,
{
label: region,
deliveryTime: time
}
];
}
}, [] as Array<SupportedJuridiction>);

// filter empty attributes
const additionalAttributes = productAttributes.filter((attribute) => {
Expand Down Expand Up @@ -1036,7 +1039,8 @@ function CreateProductInner({
tokenType?.value === TOKEN_TYPES[0].value
) {
try {
const { decimals } = await coreSDK.getExchangeTokenInfo(tokenContract);
const result = await coreSDK.getExchangeTokenInfo(tokenContract);
const { decimals } = result ?? {};
setDecimals(decimals);
} catch (error) {
setDecimals(undefined);
Expand Down
Loading