Skip to content

Commit

Permalink
feature/add stories for fields, add missing checkout form (#103)
Browse files Browse the repository at this point in the history
* add stories for fields

* add missing form fields

* fix errors

* change name for to CheckoutForm
  • Loading branch information
dogfrogfog authored Jul 4, 2024
1 parent bd86312 commit 97d9fcf
Show file tree
Hide file tree
Showing 34 changed files with 968 additions and 324 deletions.
3 changes: 1 addition & 2 deletions src/app/cart/checkout/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import CoreLayout from "@/components/layouts/CoreLayout";
import ConfirmOrderForm from "@/components/forms/OrderDetailsForm";
import ConfirmOrderForm from "@/components/forms/CheckoutForm";

export default async function Page() {
return (
<CoreLayout>
<h1 className="mb-12 text-3xl">form test fields</h1>
<ConfirmOrderForm />
</CoreLayout>
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/cart/page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Suspense } from "react";
import CartProductsList from "@/components/cart/CartProductsList";
import CoreLayout from "@/components/layouts/CoreLayout";
import CartProductsSkeleton from "@/components/skeletons/CartProductsSkeleton";
import { CartProductsSkeleton } from "@/components/ui/Skeleton";
import Button from "@/components/ui/Button";
import { ButtonStyle } from "@/components/ui/Button/styles";
import Link from "next/link";
import ConfirmOrderForm from "@/components/forms/OrderDetailsForm";
import ConfirmOrderForm from "@/components/forms/CheckoutForm";

export const dynamic = "force-dynamic";

Expand Down
4 changes: 2 additions & 2 deletions src/app/catalog/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Catalog from "@/components/Catalog";
import CatalogSection from "@/components/sections/CatalogSection";
import Filters from "@/components/Filters";
import CoreLayout from "@/components/layouts/CoreLayout";
import { CATALOG_LIMIT } from "@/constants";
Expand All @@ -17,7 +17,7 @@ export default async function Page() {
<CoreLayout>
<div>
<Filters />
<Catalog firstPageItems={response.products || []} />
<CatalogSection firstPageItems={response.products || []} />
</div>
</CoreLayout>
);
Expand Down
103 changes: 103 additions & 0 deletions src/components/forms/CheckoutForm/AddressFields.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use client";

import type { Control } from "react-hook-form";
import InputField from "@/components/ui/Form/fields/InputField";
import SelectField from "@/components/ui/Form/fields/SelectField";

type Props = {
loading: boolean;
control: Control<any>;
prefix?: string;
};

export default function AddressFields({ loading, control, prefix }: Props) {
return (
<>
<div className="grid grid-cols-2 gap-6">
<div className="col-span-1">
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.firstName` : "firstName"}
label="first name:"
placeholder="James"
/>
</div>
<div className="col-span-1">
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.lastName` : "lastName"}
label="last name:"
placeholder="Bond"
/>
</div>
</div>
<SelectField
control={control}
loading={loading}
name={prefix ? `${prefix}.country` : "country"}
label="country/region:"
items={[
{ label: "Sweden", value: "sweden" },
{ label: "Norway", value: "norway" },
{ label: "Denmark", value: "denmark" },
{ label: "Finland", value: "finland" },
{ label: "Iceland", value: "iceland" },
{ label: "Ireland", value: "ireland" },
]}
/>

<SelectField
control={control}
loading={loading}
name={prefix ? `${prefix}.state` : "state"}
label="state:"
items={[
{ label: "Sweden", value: "sweden" },
{ label: "Norway", value: "norway" },
{ label: "Denmark", value: "denmark" },
{ label: "Finland", value: "finland" },
{ label: "Iceland", value: "iceland" },
{ label: "Ireland", value: "ireland" },
]}
/>

<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.city` : "city"}
label="city:"
placeholder="London"
/>
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.address` : "address"}
label="streat and houce number:"
placeholder="sjyrniesu 10"
/>
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.additionalAddress` : "additionalAddress"}
label="additional address:"
placeholder=""
/>
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.company` : "company"}
label="company:"
placeholder="Channel"
/>
<InputField
control={control}
loading={loading}
name={prefix ? `${prefix}.postalCode` : "postalCode"}
label="postal code:"
placeholder="37892"
/>
</>
);
}
228 changes: 228 additions & 0 deletions src/components/forms/CheckoutForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
"use client";

import { useState } from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { FormContainer } from "@/components/ui/Form/FormContainer";
import InputField from "@/components/ui/Form/fields/InputField";
import CheckboxField from "@/components/ui/Form/fields/CheckboxField";
import RadioGroupField from "@/components/ui/Form/fields/RadioGroupField";
import AddressFields from "./AddressFields";

import { checkoutSchema, defaultData, CheckoutData } from "./schema";
import InputMaskedField from "@/components/ui/Form/fields/InputMaskedField";

export default function CheckoutForm({
initialData,
}: {
initialData?: CheckoutData;
}) {
const [loading, setLoading] = useState<boolean>(false);

const form = useForm<CheckoutData>({
resolver: zodResolver(checkoutSchema),
defaultValues: initialData || defaultData,
});

const billingAddressIsSameAsAddress = form.watch(
"billingAddressIsSameAsAddress",
);
const paymentMethod = form.watch("paymentMethod");

const onSubmit = async (data: CheckoutData) => {
// "use server";
console.log("data:");
console.log(data);
// try {
// setLoading(true);
// const path = `${spaceId}/${resource}`;
// const apiBaseUrl = `${apiRoutes.spaces}/${path}`;
// const resourceUrl = `${routes.dashboard}/${path}`;

// if (initialData) {
// await axios.patch(`${apiBaseUrl}/${itemId}`, data);
// } else {
// await axios.post(apiBaseUrl, data);
// }

// router.refresh();
// router.push(resourceUrl);
// toast({ title: `Resource ${initialData ? "updated" : "created"}.` });
// } catch (error) {
// toastError(error, "An error occurred while creating the resource.");
// } finally {
// setLoading(false);
// }
};

return (
<FormContainer
form={form}
initialData={initialData}
onSubmit={onSubmit}
loading={loading}
className="space-y-8"
ctaLabel="pay"
footerSide="right"
>
<div className="space-y-4">
<h2 className="mb-8 text-lg">contact</h2>
<InputField
control={form.control}
loading={loading}
name="email"
label="email address:"
type="email"
placeholder="[email protected]"
/>
<InputField
control={form.control}
loading={loading}
type="number"
name="phone"
label="phone number:"
placeholder="James Bond"
/>
<div className="space-y-2">
<CheckboxField
control={form.control}
name="subscribe"
label="email me with news and offers to our newsletter"
/>
<CheckboxField
control={form.control}
name="termsOfService"
label="i accept the privacy policy and terms & conditions"
/>
</div>
</div>

<div className="space-y-4">
<h2 className="mb-8 text-lg">shipping address</h2>
<AddressFields control={form.control} loading={loading} />
</div>

<div className="space-y-4">
<h2 className="mb-8 text-lg">shipping method</h2>
<RadioGroupField
control={form.control}
loading={loading}
name="shippingMethod"
// label="shippingMethod"
items={[
{
label: "dhl standart",
value: "dhl-standart",
},
{
label: "dhl express",
value: "dhl-express",
},
]}
/>
</div>
<div className="space-y-4">
<h2 className="mb-8 text-lg">billing address</h2>
<p className="mb-2 text-sm">
Select the address that matches your card or payment method
</p>
<CheckboxField
control={form.control}
name="billingAddressIsSameAsAddress"
label="Same as shipping address"
/>

{!billingAddressIsSameAsAddress && (
<AddressFields
prefix="billingAddress"
control={form.control}
loading={loading}
/>
)}
</div>

<div className="space-y-4">
<h2 className="mb-8 text-lg">payment</h2>

<RadioGroupField
control={form.control}
loading={loading}
name="paymentMethod"
items={[
{
label: "credit card",
value: "card",
},
{
label: "google pay",
value: "googlePay",
},
{
label: "apple pay",
value: "applePay",
},
{
label: "klarna",
value: "klarna",
},
{
label: "trx usdt",
value: "trxUsdt",
},
{
label: "eth",
value: "eth",
},
]}
/>

{paymentMethod === "card" && (
<>
<InputMaskedField
control={form.control}
name="creditCard.number"
label="card number:"
mask={"dddd dddd dddd dddd"}
placeholder="4242 4242 4242 4242"
/>
<InputField
control={form.control}
name="creditCard.fullName"
label="name on card:"
placeholder="James Bond"
/>
<div className="grid grid-cols-2 gap-6">
<div className="col-span-1">
<InputMaskedField
control={form.control}
name="creditCard.expirationDate"
label="expiration date:"
mask={"__/__"}
placeholder="MM/YY"
/>
</div>
<div className="col-span-1">
<InputMaskedField
control={form.control}
name="creditCard.cvc"
label="security code:"
mask={"___"}
placeholder="123"
/>
</div>
</div>
</>
)}
</div>

<div className="space-y-4">
<h2 className="mb-8 text-lg">remember me</h2>
<CheckboxField
control={form.control}
name="rememberMe"
label="Save my information for a faster checkouts"
/>
</div>
</FormContainer>
);
}
Loading

0 comments on commit 97d9fcf

Please sign in to comment.