2023-01-16 09:45:12 +00:00
|
|
|
import VerticalSpacer from "@dashboard/apps/components/VerticalSpacer";
|
|
|
|
import CardTitle from "@dashboard/components/CardTitle";
|
|
|
|
import Container from "@dashboard/components/Container";
|
|
|
|
import Grid from "@dashboard/components/Grid";
|
|
|
|
import Metadata from "@dashboard/components/Metadata";
|
|
|
|
import PageHeader from "@dashboard/components/PageHeader";
|
|
|
|
import Savebar from "@dashboard/components/Savebar";
|
|
|
|
import Skeleton from "@dashboard/components/Skeleton";
|
|
|
|
import { configurationMenuUrl } from "@dashboard/configuration";
|
|
|
|
import { TaxClassFragment } from "@dashboard/graphql";
|
2023-01-20 12:51:46 +00:00
|
|
|
import { useClientPagination } from "@dashboard/hooks/useClientPagination/useClientPagination";
|
2023-01-16 09:45:12 +00:00
|
|
|
import { SubmitPromise } from "@dashboard/hooks/useForm";
|
|
|
|
import useNavigator from "@dashboard/hooks/useNavigator";
|
|
|
|
import { getById } from "@dashboard/misc";
|
|
|
|
import { parseQuery } from "@dashboard/orders/components/OrderCustomerAddressesEditDialog/utils";
|
|
|
|
import TaxPageTitle from "@dashboard/taxes/components/TaxPageTitle";
|
|
|
|
import { taxesMessages } from "@dashboard/taxes/messages";
|
|
|
|
import { TaxClassesPageFormData } from "@dashboard/taxes/types";
|
|
|
|
import { useAutofocus } from "@dashboard/taxes/utils/useAutofocus";
|
|
|
|
import { isLastElement } from "@dashboard/taxes/utils/utils";
|
|
|
|
import { getFormErrors } from "@dashboard/utils/errors";
|
|
|
|
import getTaxesErrorMessage from "@dashboard/utils/errors/taxes";
|
2022-11-17 12:48:50 +00:00
|
|
|
import {
|
|
|
|
Card,
|
|
|
|
CardContent,
|
|
|
|
Divider,
|
|
|
|
InputAdornment,
|
|
|
|
TextField,
|
|
|
|
} from "@material-ui/core";
|
|
|
|
import {
|
|
|
|
ConfirmButtonTransitionState,
|
|
|
|
List,
|
|
|
|
ListHeader,
|
|
|
|
ListItem,
|
|
|
|
ListItemCell,
|
|
|
|
PageTab,
|
|
|
|
PageTabs,
|
|
|
|
SearchIcon,
|
|
|
|
} from "@saleor/macaw-ui";
|
2023-01-20 12:51:46 +00:00
|
|
|
import React, { useEffect, useMemo, useState } from "react";
|
2022-11-17 12:48:50 +00:00
|
|
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
|
|
|
|
|
|
import TaxInput from "../../components/TaxInput";
|
2023-01-20 12:51:46 +00:00
|
|
|
import { TaxPagination } from "../../components/TaxPagination";
|
2022-11-17 12:48:50 +00:00
|
|
|
import TaxClassesForm from "./form";
|
|
|
|
import { useStyles } from "./styles";
|
|
|
|
import TaxClassesMenu from "./TaxClassesMenu";
|
|
|
|
|
|
|
|
interface TaxClassesPageProps {
|
|
|
|
taxClasses: TaxClassFragment[] | undefined;
|
|
|
|
selectedTaxClassId: string;
|
|
|
|
handleTabChange: (tab: string) => void;
|
|
|
|
savebarState: ConfirmButtonTransitionState;
|
|
|
|
disabled: boolean;
|
|
|
|
onCreateNewButtonClick: () => void;
|
|
|
|
onTaxClassDelete: (id: string) => SubmitPromise;
|
2022-11-30 16:18:44 +00:00
|
|
|
onTaxClassCreate: (data: TaxClassesPageFormData) => SubmitPromise;
|
|
|
|
onTaxClassUpdate: (data: TaxClassesPageFormData) => SubmitPromise;
|
2022-11-17 12:48:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const TaxClassesPage: React.FC<TaxClassesPageProps> = props => {
|
|
|
|
const {
|
|
|
|
taxClasses,
|
|
|
|
selectedTaxClassId,
|
|
|
|
handleTabChange,
|
|
|
|
savebarState,
|
|
|
|
disabled,
|
|
|
|
onCreateNewButtonClick,
|
|
|
|
onTaxClassDelete,
|
|
|
|
onTaxClassCreate,
|
|
|
|
onTaxClassUpdate,
|
|
|
|
} = props;
|
|
|
|
const intl = useIntl();
|
|
|
|
const navigate = useNavigator();
|
|
|
|
const classes = useStyles();
|
|
|
|
|
2023-01-20 12:51:46 +00:00
|
|
|
const [query, setQuery] = useState("");
|
|
|
|
const {
|
|
|
|
rowNumber,
|
|
|
|
currentPage,
|
|
|
|
paginate,
|
|
|
|
restartPagination,
|
|
|
|
changeCurrentPage,
|
|
|
|
changeRowNumber,
|
|
|
|
} = useClientPagination();
|
2022-11-17 12:48:50 +00:00
|
|
|
|
2023-01-20 12:51:46 +00:00
|
|
|
const currentTaxClass = useMemo(
|
2022-11-17 12:48:50 +00:00
|
|
|
() => taxClasses?.find(getById(selectedTaxClassId)),
|
|
|
|
[selectedTaxClassId, taxClasses],
|
|
|
|
);
|
|
|
|
|
|
|
|
const nameInputRef = useAutofocus(currentTaxClass?.id === "new", [
|
|
|
|
currentTaxClass?.id,
|
|
|
|
]);
|
|
|
|
|
2023-01-20 12:51:46 +00:00
|
|
|
useEffect(() => {
|
|
|
|
restartPagination();
|
|
|
|
}, [query, restartPagination]);
|
|
|
|
|
2022-11-17 12:48:50 +00:00
|
|
|
return (
|
|
|
|
<TaxClassesForm
|
|
|
|
taxClass={currentTaxClass}
|
|
|
|
onTaxClassCreate={onTaxClassCreate}
|
|
|
|
onTaxClassUpdate={onTaxClassUpdate}
|
|
|
|
disabled={disabled}
|
|
|
|
>
|
2022-11-30 16:18:44 +00:00
|
|
|
{({ data, validationErrors, handlers, submit, change }) => {
|
2022-11-17 12:48:50 +00:00
|
|
|
const filteredRates = data.updateTaxClassRates.filter(
|
|
|
|
rate => rate.label.search(new RegExp(parseQuery(query), "i")) >= 0,
|
|
|
|
);
|
|
|
|
|
2023-01-25 12:32:30 +00:00
|
|
|
const {
|
|
|
|
data: paginatedRates,
|
|
|
|
hasNextPage,
|
|
|
|
hasPreviousPage,
|
|
|
|
} = paginate(filteredRates);
|
2023-01-20 12:51:46 +00:00
|
|
|
|
2022-11-30 16:18:44 +00:00
|
|
|
const formErrors = getFormErrors(["name"], validationErrors);
|
|
|
|
|
2022-11-17 12:48:50 +00:00
|
|
|
return (
|
|
|
|
<Container>
|
2023-01-11 16:10:04 +00:00
|
|
|
<PageHeader title={<TaxPageTitle />} />
|
2022-11-17 12:48:50 +00:00
|
|
|
<PageTabs value="tax-classes" onChange={handleTabChange}>
|
|
|
|
<PageTab
|
|
|
|
label={intl.formatMessage(taxesMessages.channelsSection)}
|
|
|
|
value="channels"
|
|
|
|
/>
|
|
|
|
<PageTab
|
|
|
|
label={intl.formatMessage(taxesMessages.countriesSection)}
|
|
|
|
value="countries"
|
|
|
|
/>
|
|
|
|
<PageTab
|
|
|
|
label={intl.formatMessage(taxesMessages.taxClassesSection)}
|
|
|
|
value="tax-classes"
|
|
|
|
/>
|
|
|
|
</PageTabs>
|
|
|
|
<VerticalSpacer spacing={2} />
|
|
|
|
<Grid variant="inverted">
|
|
|
|
<TaxClassesMenu
|
|
|
|
taxClasses={taxClasses}
|
|
|
|
selectedTaxClassId={selectedTaxClassId}
|
|
|
|
onTaxClassDelete={onTaxClassDelete}
|
|
|
|
onCreateNew={onCreateNewButtonClick}
|
|
|
|
/>
|
|
|
|
{taxClasses?.length !== 0 && (
|
|
|
|
<div>
|
|
|
|
<Card>
|
|
|
|
<CardTitle
|
|
|
|
title={intl.formatMessage(
|
|
|
|
taxesMessages.generalInformation,
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
<CardContent>
|
|
|
|
<TextField
|
|
|
|
value={data?.name}
|
|
|
|
onChange={change}
|
|
|
|
name="name"
|
|
|
|
variant="outlined"
|
|
|
|
placeholder={intl.formatMessage(
|
|
|
|
taxesMessages.taxRateName,
|
|
|
|
)}
|
|
|
|
fullWidth
|
|
|
|
inputProps={{ className: classes.namePadding }}
|
|
|
|
inputRef={nameInputRef}
|
2022-11-30 16:18:44 +00:00
|
|
|
error={!!formErrors.name}
|
|
|
|
helperText={getTaxesErrorMessage(formErrors.name, intl)}
|
2022-11-17 12:48:50 +00:00
|
|
|
/>
|
|
|
|
</CardContent>
|
|
|
|
</Card>
|
|
|
|
<VerticalSpacer spacing={3} />
|
|
|
|
<Card>
|
|
|
|
<CardTitle
|
|
|
|
title={intl.formatMessage(taxesMessages.taxClassRates)}
|
|
|
|
/>
|
|
|
|
{currentTaxClass?.countries.length === 0 ? (
|
|
|
|
<CardContent className={classes.supportText}>
|
|
|
|
<FormattedMessage
|
|
|
|
{...taxesMessages.noRatesInTaxClass}
|
|
|
|
values={{
|
|
|
|
tab: (
|
|
|
|
<b>
|
|
|
|
{intl.formatMessage(
|
|
|
|
taxesMessages.countriesSection,
|
|
|
|
)}
|
|
|
|
</b>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</CardContent>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<CardContent>
|
|
|
|
<TextField
|
|
|
|
value={query}
|
|
|
|
variant="outlined"
|
|
|
|
onChange={e => setQuery(e.target.value)}
|
|
|
|
placeholder={intl.formatMessage(
|
|
|
|
taxesMessages.searchTaxClasses,
|
|
|
|
)}
|
|
|
|
fullWidth
|
|
|
|
InputProps={{
|
|
|
|
startAdornment: (
|
|
|
|
<InputAdornment position="start">
|
|
|
|
<SearchIcon />
|
|
|
|
</InputAdornment>
|
|
|
|
),
|
|
|
|
}}
|
|
|
|
inputProps={{ className: classes.searchPadding }}
|
|
|
|
/>
|
|
|
|
</CardContent>
|
|
|
|
<List gridTemplate={["5fr 2fr"]}>
|
|
|
|
<ListHeader>
|
|
|
|
<ListItem>
|
|
|
|
<ListItemCell>
|
|
|
|
<FormattedMessage
|
|
|
|
{...taxesMessages.countryNameHeader}
|
|
|
|
/>
|
|
|
|
</ListItemCell>
|
|
|
|
<ListItemCell className={classes.right}>
|
|
|
|
<FormattedMessage
|
|
|
|
{...taxesMessages.taxRateHeader}
|
|
|
|
/>
|
|
|
|
</ListItemCell>
|
|
|
|
</ListItem>
|
|
|
|
</ListHeader>
|
|
|
|
<Divider />
|
2023-01-20 12:51:46 +00:00
|
|
|
{paginatedRates?.map(
|
2022-11-17 12:48:50 +00:00
|
|
|
(countryRate, countryRateIndex) => (
|
|
|
|
<React.Fragment key={countryRate.id}>
|
|
|
|
<ListItem
|
|
|
|
hover={false}
|
|
|
|
className={classes.noDivider}
|
|
|
|
>
|
|
|
|
<ListItemCell>
|
|
|
|
{countryRate.label}
|
|
|
|
</ListItemCell>
|
|
|
|
<ListItemCell>
|
|
|
|
<TaxInput
|
|
|
|
value={countryRate.value}
|
|
|
|
change={e =>
|
|
|
|
handlers.handleRateChange(
|
|
|
|
countryRate.id,
|
|
|
|
e.target.value,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</ListItemCell>
|
|
|
|
</ListItem>
|
|
|
|
{!isLastElement(
|
|
|
|
filteredRates,
|
|
|
|
countryRateIndex,
|
|
|
|
) && <Divider />}
|
|
|
|
</React.Fragment>
|
|
|
|
),
|
|
|
|
) ?? (
|
|
|
|
<>
|
|
|
|
<Skeleton />
|
|
|
|
<VerticalSpacer />
|
|
|
|
</>
|
|
|
|
)}
|
2023-01-20 12:51:46 +00:00
|
|
|
|
|
|
|
<TaxPagination
|
|
|
|
rowNumber={rowNumber}
|
|
|
|
setRowNumber={changeRowNumber}
|
|
|
|
hasNextPage={hasNextPage}
|
|
|
|
hasPrevPage={hasPreviousPage}
|
|
|
|
currentPage={currentPage}
|
|
|
|
setCurrentPage={changeCurrentPage}
|
|
|
|
/>
|
2022-11-17 12:48:50 +00:00
|
|
|
</List>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Card>
|
2022-11-30 16:18:44 +00:00
|
|
|
<VerticalSpacer spacing={3} />
|
|
|
|
<Metadata data={data} onChange={handlers.changeMetadata} />
|
2022-11-17 12:48:50 +00:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
</Grid>
|
|
|
|
<Savebar
|
|
|
|
state={savebarState}
|
|
|
|
disabled={disabled}
|
|
|
|
onSubmit={submit}
|
|
|
|
onCancel={() => navigate(configurationMenuUrl)}
|
|
|
|
/>
|
|
|
|
</Container>
|
|
|
|
);
|
|
|
|
}}
|
|
|
|
</TaxClassesForm>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default TaxClassesPage;
|