diff --git a/src/fixtures.ts b/src/fixtures.ts
index ebb678030..3394f4a92 100644
--- a/src/fixtures.ts
+++ b/src/fixtures.ts
@@ -485,3 +485,23 @@ export const adminUserPermissions: User_userPermissions[] = [
name: "Manage customers."
}
];
+
+export const address = {
+ __typename: "Address",
+ city: "Port Danielshire",
+ cityArea: "",
+ companyName: "",
+ country: {
+ __typename: "CountryDisplay",
+ code: "SE",
+ country: "Szwecja"
+ },
+ countryArea: "",
+ firstName: "Elizabeth",
+ id: "QWRkcmVzczoy",
+ lastName: "Vaughn",
+ phone: "",
+ postalCode: "52203",
+ streetAddress1: "419 Ruiz Orchard Apt. 199",
+ streetAddress2: "0238 Cremin Freeway"
+};
diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts
index 48507817e..53faacc0a 100644
--- a/src/types/globalTypes.ts
+++ b/src/types/globalTypes.ts
@@ -1419,6 +1419,25 @@ export interface VoucherSortingInput {
field: VoucherSortField;
}
+export interface WarehouseAddressInput {
+ streetAddress1: string;
+ streetAddress2?: string | null;
+ city: string;
+ cityArea?: string | null;
+ postalCode?: string | null;
+ country: CountryCode;
+ countryArea?: string | null;
+ phone?: string | null;
+}
+
+export interface WarehouseCreateInput {
+ name: string;
+ companyName?: string | null;
+ shippingZones?: (string | null)[] | null;
+ email?: string | null;
+ address: WarehouseAddressInput;
+}
+
export interface WarehouseFilterInput {
search?: string | null;
}
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
new file mode 100644
index 000000000..9f25b855b
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
@@ -0,0 +1,48 @@
+import { storiesOf } from "@storybook/react";
+import React from "react";
+
+import { address, permissions } from "@saleor/fixtures";
+import Decorator from "@saleor/storybook/Decorator";
+import { formError } from "@saleor/storybook/misc";
+import { warehouseList } from "../../fixtures";
+import WarehouseCreatePage, {
+ WarehouseCreatePageProps,
+ WarehouseCreatePageFormData
+} from "./WarehouseCreatePage";
+
+const props: WarehouseCreatePageProps = {
+ disabled: false,
+ errors: [],
+ saveButtonBarState: "default",
+ onBack: () => undefined,
+ onSubmit: () => undefined,
+ warehouse: {
+ ...warehouseList[0],
+ address
+ }
+};
+storiesOf("Views / Warehouses / Create warehouse", module)
+ .addDecorator(Decorator)
+ .add("default", () => )
+ .add("loading", () => (
+
+ ))
+ .add("form errors", () => (
+ ).map(field =>
+ formError(field)
+ )}
+ />
+ ));
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
new file mode 100644
index 000000000..2024cca42
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
@@ -0,0 +1,119 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import Container from "@saleor/components/Container";
+import Form from "@saleor/components/Form";
+import SaveButtonBar from "@saleor/components/SaveButtonBar";
+import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
+import { UserError } from "@saleor/types";
+import Grid from "@saleor/components/Grid";
+import CardSpacer from "@saleor/components/CardSpacer";
+import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
+import { AddressTypeInput } from "@saleor/customers/types";
+import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
+import { mapCountriesToChoices } from "@saleor/utils/maps";
+import useAddressValidation from "@saleor/hooks/useAddressValidation";
+import useStateFromProps from "@saleor/hooks/useStateFromProps";
+import { maybe } from "@saleor/misc";
+import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import WarehouseInfo from "../WarehouseInfo";
+
+export interface WarehouseCreatePageFormData extends AddressTypeInput {
+ name: string;
+}
+export interface WarehouseCreatePageProps {
+ disabled: boolean;
+ errors: UserError[];
+ saveButtonBarState: ConfirmButtonTransitionState;
+ shop: ShopInfo_shop;
+ onBack: () => void;
+ onSubmit: (data: WarehouseCreatePageFormData) => void;
+}
+
+const initialForm: WarehouseCreatePageFormData = {
+ city: "",
+ companyName: "",
+ country: "",
+ countryArea: "",
+ name: "",
+ phone: "",
+ postalCode: "",
+ streetAddress1: "",
+ streetAddress2: ""
+};
+
+const WarehouseCreatePage: React.FC = ({
+ disabled,
+ errors: apiErrors,
+ saveButtonBarState,
+ shop,
+ onBack,
+ onSubmit
+}) => {
+ const intl = useIntl();
+ const [displayCountry, setDisplayCountry] = useStateFromProps(
+ maybe(() => shop.companyAddress.country.code, "")
+ );
+
+ const {
+ errors: validationErrors,
+ submit: handleSubmit
+ } = useAddressValidation(onSubmit);
+
+ return (
+
+ );
+};
+
+WarehouseCreatePage.displayName = "WarehouseCreatePage";
+export default WarehouseCreatePage;
diff --git a/src/warehouses/components/WarehouseCreatePage/index.ts b/src/warehouses/components/WarehouseCreatePage/index.ts
new file mode 100644
index 000000000..b9bd23b20
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseCreatePage";
+export * from "./WarehouseCreatePage";
diff --git a/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
new file mode 100644
index 000000000..56b402e08
--- /dev/null
+++ b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import TextField from "@material-ui/core/TextField";
+import { useIntl } from "react-intl";
+import CardTitle from "@saleor/components/CardTitle";
+import { commonMessages } from "@saleor/intl";
+import { FormChange } from "@saleor/hooks/useForm";
+import { FormErrors } from "@saleor/types";
+
+export interface WarehouseInfoProps {
+ data: Record<"name", string>;
+ disabled: boolean;
+ errors: FormErrors<"name">;
+ onChange: FormChange;
+}
+
+const WarehouseInfo: React.FC = ({
+ data,
+ disabled,
+ errors,
+ onChange
+}) => {
+ const intl = useIntl();
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+WarehouseInfo.displayName = "WarehouseInfo";
+export default WarehouseInfo;
diff --git a/src/warehouses/components/WarehouseInfo/index.ts b/src/warehouses/components/WarehouseInfo/index.ts
new file mode 100644
index 000000000..3296772d7
--- /dev/null
+++ b/src/warehouses/components/WarehouseInfo/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseInfo";
+export * from "./WarehouseInfo";
diff --git a/src/warehouses/index.tsx b/src/warehouses/index.tsx
index 8d06f0040..0b37a9da5 100644
--- a/src/warehouses/index.tsx
+++ b/src/warehouses/index.tsx
@@ -13,11 +13,13 @@ import {
WarehouseListUrlQueryParams,
// warehousePath,
// WarehouseUrlQueryParams,
- WarehouseListUrlSortField
+ WarehouseListUrlSortField,
+ warehouseAddPath
} from "./urls";
// import WarehouseCreateComponent from "./views/WarehouseCreate";
// import WarehouseDetailsComponent from "./views/WarehouseDetails";
import WarehouseListComponent from "./views/WarehouseList";
+import WarehouseCreate from "./views/WarehouseCreate";
const WarehouseList: React.FC = ({ location }) => {
const qs = parseQs(location.search.substr(1));
@@ -29,12 +31,6 @@ const WarehouseList: React.FC = ({ location }) => {
return ;
};
-// const WarehouseCreate: React.FC> = ({ location }) => {
-// const qs = parseQs(location.search.substr(1));
-// const params: WarehouseAddUrlQueryParams = qs;
-// return ;
-// };
-
// const WarehouseDetails: React.FC> = ({
// location,
// match
@@ -57,8 +53,8 @@ export const WarehouseSection: React.FC = () => {
- {/*
- */}
+
+ {/* */}
>
);
diff --git a/src/warehouses/mutations.ts b/src/warehouses/mutations.ts
index fa1da647b..9611cac88 100644
--- a/src/warehouses/mutations.ts
+++ b/src/warehouses/mutations.ts
@@ -1,10 +1,15 @@
import gql from "graphql-tag";
import makeMutation from "@saleor/hooks/makeMutation";
+import {
+ WarehouseCreate,
+ WarehouseCreateVariables
+} from "./types/WarehouseCreate";
import {
WarehouseDelete,
WarehouseDeleteVariables
} from "./types/WarehouseDelete";
+import { warehouseDetailsFragment } from "./queries";
const deleteWarehouse = gql`
mutation WarehouseDelete($id: ID!) {
@@ -20,3 +25,22 @@ export const useWarehouseDelete = makeMutation<
WarehouseDelete,
WarehouseDeleteVariables
>(deleteWarehouse);
+
+const createWarehouse = gql`
+ ${warehouseDetailsFragment}
+ mutation WarehouseCreate($input: WarehouseCreateInput!) {
+ createWarehouse(input: $input) {
+ errors {
+ field
+ message
+ }
+ warehouse {
+ ...WarehouseDetailsFragment
+ }
+ }
+ }
+`;
+export const useWarehouseCreate = makeMutation<
+ WarehouseCreate,
+ WarehouseCreateVariables
+>(createWarehouse);
diff --git a/src/warehouses/queries.ts b/src/warehouses/queries.ts
index 1cfd8b5ac..d75984c68 100644
--- a/src/warehouses/queries.ts
+++ b/src/warehouses/queries.ts
@@ -2,6 +2,7 @@ import gql from "graphql-tag";
import makeQuery from "@saleor/hooks/makeQuery";
import { pageInfoFragment } from "@saleor/queries";
+import { fragmentAddress } from "@saleor/orders/queries";
import { WarehouseList, WarehouseListVariables } from "./types/WarehouseList";
export const warehouseFragment = gql`
@@ -19,6 +20,17 @@ export const warehouseFragment = gql`
}
`;
+export const warehouseDetailsFragment = gql`
+ ${fragmentAddress}
+ ${warehouseFragment}
+ fragment WarehouseDetailsFragment on Warehouse {
+ ...WarehouseFragment
+ address {
+ ...AddressFragment
+ }
+ }
+`;
+
const warehouseList = gql`
${warehouseFragment}
${pageInfoFragment}
diff --git a/src/warehouses/types/WarehouseCreate.ts b/src/warehouses/types/WarehouseCreate.ts
new file mode 100644
index 000000000..5caeb87b9
--- /dev/null
+++ b/src/warehouses/types/WarehouseCreate.ts
@@ -0,0 +1,75 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseCreateInput } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: WarehouseCreate
+// ====================================================
+
+export interface WarehouseCreate_createWarehouse_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseCreate_createWarehouse_warehouse_shippingZones_edges[];
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseCreate_createWarehouse_warehouse_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseCreate_createWarehouse_warehouse_shippingZones;
+ address: WarehouseCreate_createWarehouse_warehouse_address;
+}
+
+export interface WarehouseCreate_createWarehouse {
+ __typename: "WarehouseCreate";
+ errors: WarehouseCreate_createWarehouse_errors[] | null;
+ warehouse: WarehouseCreate_createWarehouse_warehouse | null;
+}
+
+export interface WarehouseCreate {
+ createWarehouse: WarehouseCreate_createWarehouse | null;
+}
+
+export interface WarehouseCreateVariables {
+ input: WarehouseCreateInput;
+}
diff --git a/src/warehouses/types/WarehouseDetailsFragment.ts b/src/warehouses/types/WarehouseDetailsFragment.ts
new file mode 100644
index 000000000..fae00ac31
--- /dev/null
+++ b/src/warehouses/types/WarehouseDetailsFragment.ts
@@ -0,0 +1,53 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL fragment: WarehouseDetailsFragment
+// ====================================================
+
+export interface WarehouseDetailsFragment_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseDetailsFragment_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseDetailsFragment_shippingZones_edges_node;
+}
+
+export interface WarehouseDetailsFragment_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseDetailsFragment_shippingZones_edges[];
+}
+
+export interface WarehouseDetailsFragment_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseDetailsFragment_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseDetailsFragment_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseDetailsFragment {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseDetailsFragment_shippingZones;
+ address: WarehouseDetailsFragment_address;
+}
diff --git a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
new file mode 100644
index 000000000..921a0ee8f
--- /dev/null
+++ b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
@@ -0,0 +1,60 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import WarehouseCreatePage from "@saleor/warehouses/components/WarehouseCreatePage";
+import useNavigator from "@saleor/hooks/useNavigator";
+import { warehouseListUrl, warehouseUrl } from "@saleor/warehouses/urls";
+import { useWarehouseCreate } from "@saleor/warehouses/mutations";
+import { commonMessages } from "@saleor/intl";
+import useNotifier from "@saleor/hooks/useNotifier";
+import { maybe, findValueInEnum, getMutationStatus } from "@saleor/misc";
+import { CountryCode } from "@saleor/types/globalTypes";
+import useShop from "@saleor/hooks/useShop";
+
+const WarehouseCreate: React.FC = () => {
+ const intl = useIntl();
+ const navigate = useNavigator();
+ const notify = useNotifier();
+ const shop = useShop();
+ const [createWarehouse, createWarehouseOpts] = useWarehouseCreate({
+ onCompleted: data => {
+ if (data.createWarehouse.errors.length === 0) {
+ navigate(warehouseUrl(data.createWarehouse.warehouse.id));
+ notify({ text: intl.formatMessage(commonMessages.savedChanges) });
+ }
+ }
+ });
+ const createWarehouseTransitionState = getMutationStatus(createWarehouseOpts);
+
+ return (
+ navigate(warehouseListUrl())}
+ disabled={createWarehouseOpts.loading}
+ errors={maybe(() => createWarehouseOpts.data.createWarehouse.errors, [])}
+ shop={shop}
+ onSubmit={data =>
+ createWarehouse({
+ variables: {
+ input: {
+ address: {
+ city: data.city,
+ cityArea: data.cityArea,
+ country: findValueInEnum(data.country, CountryCode),
+ countryArea: data.countryArea,
+ phone: data.phone,
+ postalCode: data.postalCode,
+ streetAddress1: data.streetAddress1,
+ streetAddress2: data.streetAddress2
+ },
+ name: data.name
+ }
+ }
+ })
+ }
+ saveButtonBarState={createWarehouseTransitionState}
+ />
+ );
+};
+
+WarehouseCreate.displayName = "WarehouseCreate";
+export default WarehouseCreate;
diff --git a/src/warehouses/views/WarehouseCreate/index.ts b/src/warehouses/views/WarehouseCreate/index.ts
new file mode 100644
index 000000000..d73de272c
--- /dev/null
+++ b/src/warehouses/views/WarehouseCreate/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseCreate";
+export * from "./WarehouseCreate";