wip
This commit is contained in:
parent
34698b7d6f
commit
ed3e9fbc45
11 changed files with 316 additions and 80 deletions
42
src/searches/types/SearchWarehouses.ts
Normal file
42
src/searches/types/SearchWarehouses.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: SearchWarehouses
|
||||
// ====================================================
|
||||
|
||||
export interface SearchWarehouses_search_edges_node {
|
||||
__typename: "Warehouse";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface SearchWarehouses_search_edges {
|
||||
__typename: "WarehouseCountableEdge";
|
||||
node: SearchWarehouses_search_edges_node;
|
||||
}
|
||||
|
||||
export interface SearchWarehouses_search_pageInfo {
|
||||
__typename: "PageInfo";
|
||||
endCursor: string | null;
|
||||
hasNextPage: boolean;
|
||||
hasPreviousPage: boolean;
|
||||
startCursor: string | null;
|
||||
}
|
||||
|
||||
export interface SearchWarehouses_search {
|
||||
__typename: "WarehouseCountableConnection";
|
||||
edges: SearchWarehouses_search_edges[];
|
||||
pageInfo: SearchWarehouses_search_pageInfo;
|
||||
}
|
||||
|
||||
export interface SearchWarehouses {
|
||||
search: SearchWarehouses_search | null;
|
||||
}
|
||||
|
||||
export interface SearchWarehousesVariables {
|
||||
after?: string | null;
|
||||
first: number;
|
||||
query: string;
|
||||
}
|
33
src/searches/useWarehouseSearch.ts
Normal file
33
src/searches/useWarehouseSearch.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import gql from "graphql-tag";
|
||||
|
||||
import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
|
||||
import { pageInfoFragment } from "@saleor/queries";
|
||||
import {
|
||||
SearchWarehouses,
|
||||
SearchWarehousesVariables
|
||||
} from "./types/SearchWarehouses";
|
||||
|
||||
export const searchWarehouses = gql`
|
||||
${pageInfoFragment}
|
||||
query SearchWarehouses($after: String, $first: Int!, $query: String!) {
|
||||
search: warehouses(
|
||||
after: $after
|
||||
first: $first
|
||||
filter: { search: $query }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
...PageInfoFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default makeTopLevelSearch<SearchWarehouses, SearchWarehousesVariables>(
|
||||
searchWarehouses
|
||||
);
|
|
@ -11,14 +11,21 @@ import Grid from "@saleor/components/Grid";
|
|||
import PageHeader from "@saleor/components/PageHeader";
|
||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||
import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment";
|
||||
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
|
||||
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
|
||||
import { maybe, getStringOrPlaceholder } from "../../../misc";
|
||||
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
||||
import { ShippingZoneDetailsFragment } from "../../types/ShippingZoneDetailsFragment";
|
||||
import {
|
||||
ShippingZoneDetailsFragment,
|
||||
ShippingZoneDetailsFragment_warehouses
|
||||
} from "../../types/ShippingZoneDetailsFragment";
|
||||
import ShippingZoneInfo from "../ShippingZoneInfo";
|
||||
import ShippingZoneRates from "../ShippingZoneRates";
|
||||
import ShippingZoneWarehouses from "../ShippingZoneWarehouses";
|
||||
|
||||
export interface FormData {
|
||||
name: string;
|
||||
warehouses: string[];
|
||||
}
|
||||
|
||||
export interface ShippingZoneDetailsPageProps {
|
||||
|
@ -26,6 +33,7 @@ export interface ShippingZoneDetailsPageProps {
|
|||
errors: ShippingErrorFragment[];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
shippingZone: ShippingZoneDetailsFragment;
|
||||
warehouses: ShippingZoneDetailsFragment_warehouses[];
|
||||
onBack: () => void;
|
||||
onCountryAdd: () => void;
|
||||
onCountryRemove: (code: string) => void;
|
||||
|
@ -38,6 +46,15 @@ export interface ShippingZoneDetailsPageProps {
|
|||
onWeightRateEdit: (id: string) => void;
|
||||
}
|
||||
|
||||
function warehouseToChoice(
|
||||
warehouse: Record<"id" | "name", string>
|
||||
): MultiAutocompleteChoiceType {
|
||||
return {
|
||||
label: warehouse.name,
|
||||
value: warehouse.id
|
||||
};
|
||||
}
|
||||
|
||||
const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||
disabled,
|
||||
errors,
|
||||
|
@ -52,90 +69,117 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
|||
onWeightRateAdd,
|
||||
onWeightRateEdit,
|
||||
saveButtonBarState,
|
||||
shippingZone
|
||||
shippingZone,
|
||||
warehouses
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const initialForm: FormData = {
|
||||
name: shippingZone?.name || ""
|
||||
name: shippingZone?.name || "",
|
||||
warehouses: shippingZone?.warehouses.map(warehouse => warehouse.id) || []
|
||||
};
|
||||
const [warehouseDisplayValues, setWarehouseDisplayValues] = React.useState(
|
||||
shippingZone?.warehouses.map(warehouseToChoice)
|
||||
);
|
||||
|
||||
const warehouseChoices = warehouses.map(warehouseToChoice);
|
||||
|
||||
return (
|
||||
<Form initial={initialForm} onSubmit={onSubmit}>
|
||||
{({ change, data, hasChanged, submit }) => (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
<FormattedMessage defaultMessage="Shipping" />
|
||||
</AppHeader>
|
||||
<PageHeader title={getStringOrPlaceholder(shippingZone?.name)} />
|
||||
<Grid>
|
||||
<div>
|
||||
<ShippingZoneInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<CountryList
|
||||
countries={shippingZone?.countries}
|
||||
disabled={disabled}
|
||||
emptyText={maybe(
|
||||
() =>
|
||||
shippingZone.default
|
||||
? intl.formatMessage({
|
||||
defaultMessage:
|
||||
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Currently, there are no countries assigned to this shipping zone"
|
||||
}),
|
||||
"..."
|
||||
)}
|
||||
onCountryAssign={onCountryAdd}
|
||||
onCountryUnassign={onCountryRemove}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Countries"
|
||||
})}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneRates
|
||||
disabled={disabled}
|
||||
onRateAdd={onPriceRateAdd}
|
||||
onRateEdit={onPriceRateEdit}
|
||||
onRateRemove={onRateRemove}
|
||||
rates={maybe(() =>
|
||||
shippingZone.shippingMethods.filter(
|
||||
method => method.type === ShippingMethodTypeEnum.PRICE
|
||||
)
|
||||
)}
|
||||
variant="price"
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneRates
|
||||
disabled={disabled}
|
||||
onRateAdd={onWeightRateAdd}
|
||||
onRateEdit={onWeightRateEdit}
|
||||
onRateRemove={onRateRemove}
|
||||
rates={maybe(() =>
|
||||
shippingZone.shippingMethods.filter(
|
||||
method => method.type === ShippingMethodTypeEnum.WEIGHT
|
||||
)
|
||||
)}
|
||||
variant="weight"
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<SaveButtonBar
|
||||
disabled={disabled || !hasChanged}
|
||||
onCancel={onBack}
|
||||
onDelete={onDelete}
|
||||
onSave={submit}
|
||||
state={saveButtonBarState}
|
||||
/>
|
||||
</Container>
|
||||
)}
|
||||
{({ change, data, hasChanged, submit }) => {
|
||||
const handleWarehouseChange = createMultiAutocompleteSelectHandler(
|
||||
change,
|
||||
setWarehouseDisplayValues,
|
||||
warehouseDisplayValues,
|
||||
warehouseChoices
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<AppHeader onBack={onBack}>
|
||||
<FormattedMessage defaultMessage="Shipping" />
|
||||
</AppHeader>
|
||||
<PageHeader title={shippingZone?.name} />
|
||||
<Grid>
|
||||
<div>
|
||||
<ShippingZoneInfo
|
||||
data={data}
|
||||
disabled={disabled}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<CountryList
|
||||
countries={shippingZone?.countries}
|
||||
disabled={disabled}
|
||||
emptyText={maybe(
|
||||
() =>
|
||||
shippingZone.default
|
||||
? intl.formatMessage({
|
||||
defaultMessage:
|
||||
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||
})
|
||||
: intl.formatMessage({
|
||||
defaultMessage:
|
||||
"Currently, there are no countries assigned to this shipping zone"
|
||||
}),
|
||||
"..."
|
||||
)}
|
||||
onCountryAssign={onCountryAdd}
|
||||
onCountryUnassign={onCountryRemove}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Countries"
|
||||
})}
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneRates
|
||||
disabled={disabled}
|
||||
onRateAdd={onPriceRateAdd}
|
||||
onRateEdit={onPriceRateEdit}
|
||||
onRateRemove={onRateRemove}
|
||||
rates={maybe(() =>
|
||||
shippingZone.shippingMethods.filter(
|
||||
method => method.type === ShippingMethodTypeEnum.PRICE
|
||||
)
|
||||
)}
|
||||
variant="price"
|
||||
/>
|
||||
<CardSpacer />
|
||||
<ShippingZoneRates
|
||||
disabled={disabled}
|
||||
onRateAdd={onWeightRateAdd}
|
||||
onRateEdit={onWeightRateEdit}
|
||||
onRateRemove={onRateRemove}
|
||||
rates={maybe(() =>
|
||||
shippingZone.shippingMethods.filter(
|
||||
method => method.type === ShippingMethodTypeEnum.WEIGHT
|
||||
)
|
||||
)}
|
||||
variant="weight"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<ShippingZoneWarehouses
|
||||
data={data}
|
||||
displayValue={warehouseDisplayValues}
|
||||
hasMore={false}
|
||||
loading={false}
|
||||
onChange={handleWarehouseChange}
|
||||
onFetchMore={() => undefined}
|
||||
warehouses={warehouseChoices}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<SaveButtonBar
|
||||
disabled={disabled || !hasChanged}
|
||||
onCancel={onBack}
|
||||
onDelete={onDelete}
|
||||
onSave={submit}
|
||||
state={saveButtonBarState}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import Card from "@material-ui/core/Card";
|
||||
import CardContent from "@material-ui/core/CardContent";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
|
||||
import CardTitle from "@saleor/components/CardTitle";
|
||||
import { FetchMoreProps } from "@saleor/types";
|
||||
import { FormChange } from "@saleor/hooks/useForm";
|
||||
import MultiAutocompleteSelectField, {
|
||||
MultiAutocompleteChoiceType
|
||||
} from "@saleor/components/MultiAutocompleteSelectField";
|
||||
|
||||
interface ShippingZoneWarehousesFormData {
|
||||
warehouses: string[];
|
||||
}
|
||||
interface ShippingZonewWarehousesProps extends FetchMoreProps {
|
||||
data: ShippingZoneWarehousesFormData;
|
||||
displayValue: MultiAutocompleteChoiceType[];
|
||||
warehouses: MultiAutocompleteChoiceType[];
|
||||
onChange: FormChange;
|
||||
}
|
||||
|
||||
export const ShippingZoneWarehouses: React.FC<ShippingZonewWarehousesProps> = props => {
|
||||
const {
|
||||
data,
|
||||
displayValue,
|
||||
hasMore,
|
||||
loading,
|
||||
onChange,
|
||||
onFetchMore,
|
||||
warehouses
|
||||
} = props;
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Visibility",
|
||||
description: "section header"
|
||||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
<MultiAutocompleteSelectField
|
||||
choices={warehouses}
|
||||
displayValues={displayValue}
|
||||
fetchChoices={() => undefined}
|
||||
hasMore={hasMore}
|
||||
loading={loading}
|
||||
name="warehouse"
|
||||
onChange={onChange}
|
||||
onFetchMore={onFetchMore}
|
||||
value={data.warehouses}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
ShippingZoneWarehouses.displayName = "ShippingZoneWarehouses";
|
||||
export default ShippingZoneWarehouses;
|
2
src/shipping/components/ShippingZoneWarehouses/index.ts
Normal file
2
src/shipping/components/ShippingZoneWarehouses/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export { default } from "./ShippingZoneWarehouses";
|
||||
export * from "./ShippingZoneWarehouses";
|
|
@ -50,6 +50,10 @@ export const shippingZoneDetailsFragment = gql`
|
|||
shippingMethods {
|
||||
...ShippingMethodFragment
|
||||
}
|
||||
warehouses {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -62,6 +62,12 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet
|
|||
type: ShippingMethodTypeEnum | null;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingZone_warehouses {
|
||||
__typename: "Warehouse";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate_shippingZone {
|
||||
__typename: "ShippingZone";
|
||||
id: string;
|
||||
|
@ -69,6 +75,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone {
|
|||
name: string;
|
||||
default: boolean;
|
||||
shippingMethods: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods | null)[] | null;
|
||||
warehouses: (CreateShippingRate_shippingPriceCreate_shippingZone_warehouses | null)[] | null;
|
||||
}
|
||||
|
||||
export interface CreateShippingRate_shippingPriceCreate {
|
||||
|
|
|
@ -62,6 +62,12 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet
|
|||
type: ShippingMethodTypeEnum | null;
|
||||
}
|
||||
|
||||
export interface DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses {
|
||||
__typename: "Warehouse";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface DeleteShippingRate_shippingPriceDelete_shippingZone {
|
||||
__typename: "ShippingZone";
|
||||
id: string;
|
||||
|
@ -69,6 +75,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone {
|
|||
name: string;
|
||||
default: boolean;
|
||||
shippingMethods: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods | null)[] | null;
|
||||
warehouses: (DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses | null)[] | null;
|
||||
}
|
||||
|
||||
export interface DeleteShippingRate_shippingPriceDelete {
|
||||
|
|
|
@ -56,6 +56,12 @@ export interface ShippingZone_shippingZone_shippingMethods {
|
|||
type: ShippingMethodTypeEnum | null;
|
||||
}
|
||||
|
||||
export interface ShippingZone_shippingZone_warehouses {
|
||||
__typename: "Warehouse";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ShippingZone_shippingZone {
|
||||
__typename: "ShippingZone";
|
||||
id: string;
|
||||
|
@ -63,6 +69,7 @@ export interface ShippingZone_shippingZone {
|
|||
name: string;
|
||||
default: boolean;
|
||||
shippingMethods: (ShippingZone_shippingZone_shippingMethods | null)[] | null;
|
||||
warehouses: (ShippingZone_shippingZone_warehouses | null)[] | null;
|
||||
}
|
||||
|
||||
export interface ShippingZone {
|
||||
|
|
|
@ -56,6 +56,12 @@ export interface ShippingZoneDetailsFragment_shippingMethods {
|
|||
type: ShippingMethodTypeEnum | null;
|
||||
}
|
||||
|
||||
export interface ShippingZoneDetailsFragment_warehouses {
|
||||
__typename: "Warehouse";
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ShippingZoneDetailsFragment {
|
||||
__typename: "ShippingZone";
|
||||
id: string;
|
||||
|
@ -63,4 +69,5 @@ export interface ShippingZoneDetailsFragment {
|
|||
name: string;
|
||||
default: boolean;
|
||||
shippingMethods: (ShippingZoneDetailsFragment_shippingMethods | null)[] | null;
|
||||
warehouses: (ShippingZoneDetailsFragment_warehouses | null)[] | null;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ import { useIntl } from "react-intl";
|
|||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
|
||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||
import { useWarehouseUpdate } from "@saleor/warehouses/mutations";
|
||||
import { maybe } from "../../../misc";
|
||||
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
|
||||
import ShippingZoneDetailsPage from "../../components/ShippingZoneDetailsPage";
|
||||
|
@ -33,6 +36,14 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
const navigate = useNavigator();
|
||||
const notify = useNotifier();
|
||||
const intl = useIntl();
|
||||
const [updateWarehouse, updateWarehouseOpts] = useWarehouseUpdate({});
|
||||
|
||||
const {
|
||||
search: searchWarehouses,
|
||||
result: searchWarehousesOpts
|
||||
} = useWarehouseSearch({
|
||||
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||
});
|
||||
|
||||
const closeModal = () => navigate(shippingZoneUrl(id), true);
|
||||
|
||||
|
@ -146,14 +157,19 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
})
|
||||
)
|
||||
}
|
||||
onSubmit={formData =>
|
||||
onSubmit={formData => {
|
||||
ops.shippingZoneUpdate.mutate({
|
||||
id,
|
||||
input: {
|
||||
name: formData.name
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
updateWarehouse({
|
||||
variables: {
|
||||
id: formData.warehouse
|
||||
}
|
||||
});
|
||||
}}
|
||||
onWeightRateAdd={() =>
|
||||
navigate(
|
||||
shippingZoneUrl(id, {
|
||||
|
@ -172,6 +188,13 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
|||
}
|
||||
saveButtonBarState={ops.shippingZoneUpdate.opts.status}
|
||||
shippingZone={maybe(() => data.shippingZone)}
|
||||
warehouses={maybe(
|
||||
() =>
|
||||
searchWarehousesOpts.data.search.edges.map(
|
||||
edge => edge.node
|
||||
),
|
||||
[]
|
||||
)}
|
||||
/>
|
||||
<ShippingZoneDetailsDialogs
|
||||
assignCountryTransitionState={
|
||||
|
|
Loading…
Reference in a new issue