Skip to content

Commit

Permalink
Merge branch 'Weaverse:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
hta218 authored Dec 23, 2024
2 parents 62ec190 + cc589e6 commit bd3afe6
Show file tree
Hide file tree
Showing 56 changed files with 3,811 additions and 2,732 deletions.
17 changes: 9 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ PUBLIC_CUSTOMER_ACCOUNT_API_CLIENT_ID=shp_182e9ed0-270f-473a-be74-e3073f852c39
PUBLIC_CUSTOMER_ACCOUNT_API_URL=https://shopify.com/72804106547
PUBLIC_CHECKOUT_DOMAIN=www.weaverse.dev

## optional
## Optional
PUBLIC_STOREFRONT_ID=1000010106
#PRIVATE_STOREFRONT_API_TOKEN="your-private-storefront-api-token"
# PRIVATE_STOREFRONT_API_TOKEN="your-private-storefront-api-token"

# Weaverse setup
# Weaverse
WEAVERSE_PROJECT_ID=clptu3l4p001sxfsn1u9jzqnm
#WEAVERSE_API_KEY="your-weaverse-api-key"
# WEAVERSE_API_KEY="your-weaverse-api-key"

# Additional services
#PUBLIC_GOOGLE_GTM_ID=G-R1KFYYKE48
#JUDGEME_PRIVATE_API_TOKEN="your-judgeme-private-api-token"
#ALI_REVIEWS_API_KEY="your-ali-reviews-api-key"
# PUBLIC_GOOGLE_GTM_ID=G-R1KFYYKE48
# JUDGEME_PRIVATE_API_TOKEN="your-judgeme-private-api-token"
# ALI_REVIEWS_API_KEY="your-ali-reviews-api-key"

CUSTOM_COLLECTION_BANNER_METAFIELD="custom.collection_banner"
# Custom metafields & metaobjects
METAOBJECT_COLORS_TYPE="colors"
METAOBJECT_COLOR_NAME_KEY="label"
METAOBJECT_COLOR_VALUE_KEY="color"
CUSTOM_COLLECTION_BANNER_METAFIELD="custom.collection_banner"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ node_modules
/playwright-report/
/playwright/.cache/
pnpm-lock.yaml
.DS_Store
34 changes: 21 additions & 13 deletions app/components/account/account-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,37 @@ export function AccountDetails({
}: {
customer: CustomerDetailsFragment;
}) {
const { firstName, lastName, emailAddress, phoneNumber } = customer;
const fullName = `${firstName || ""} ${lastName || ""}`.trim();
let { firstName, lastName, emailAddress, phoneNumber } = customer;
let fullName = `${firstName || ""} ${lastName || ""}`.trim();
return (
<div className="space-y-4">
<div className="font-bold">Account</div>
<div className="p-5 border border-[#B7B7B7] rounded-sm">
<div className="text-body-subtle">Name</div>
<p className="mt-1">{fullName || "N/A"}</p>
<div className="p-5 border border-line-subtle space-y-4">
<div className="space-y-1">
<div className="text-body-subtle">Name</div>
<div>{fullName || "N/A"}</div>
</div>

<div className="mt-4 text-body-subtle">Phone number</div>
<p className="mt-1">{phoneNumber?.phoneNumber ?? "N/A"}</p>
<div className="space-y-1">
<div className=" text-body-subtle">Phone number</div>
<div>{phoneNumber?.phoneNumber ?? "N/A"}</div>
</div>

<div className="mt-4 text-body-subtle">Email address</div>
<p className="mt-1">{emailAddress?.emailAddress ?? "N/A"}</p>
<p className="mt-3">
<div className="space-y-1">
<div className=" text-body-subtle">Email address</div>
<div>{emailAddress?.emailAddress ?? "N/A"}</div>
</div>

<div>
<Link
prefetch="intent"
className="underline font-normal text-body-subtle"
variant="underline"
className="text-body-subtle after:bg-body-subtle"
to="/account/edit"
>
Edit
Edit account details
</Link>
</p>
</div>
</div>
</div>
);
Expand Down
29 changes: 16 additions & 13 deletions app/components/account/address-book.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Form } from "@remix-run/react";
import type { CustomerAddress } from "@shopify/hydrogen/customer-account-api-types";
import type { CustomerDetailsFragment } from "customer-accountapi.generated";
import { Link } from "~/components/link";
import { Text } from "../../modules/text";
import { Button } from "~/components/button";

export function AccountAddressBook({
customer,
Expand All @@ -14,18 +14,16 @@ export function AccountAddressBook({
return (
<div className="space-y-4">
<div className="font-bold">Address Book</div>
<div>
<div className="space-y-3">
{!addresses?.length && (
<Text className="mb-1" size="fine" width="narrow" as="p">
You haven&apos;t saved any addresses yet.
</Text>
<div>You haven&apos;t saved any addresses yet.</div>
)}
<div className="">
<Link to="address/add" className="mb-5" variant="primary">
<Link to="address/add" className="mb-5" variant="outline">
Add an Address
</Link>
</div>
{Boolean(addresses?.length) && (
{addresses?.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
{customer.defaultAddress && (
<Address address={customer.defaultAddress} defaultAddress />
Expand All @@ -36,7 +34,7 @@ export function AccountAddressBook({
<Address key={address.id} address={address} />
))}
</div>
)}
) : null}
</div>
</div>
);
Expand All @@ -50,10 +48,10 @@ function Address({
defaultAddress?: boolean;
}) {
return (
<div className="p-5 border border-[#B7B7B7] rounded-sm flex flex-col">
<div className="p-5 border border-line-subtle flex flex-col">
{defaultAddress && (
<div className="mb-3 flex flex-row">
<span className="px-3 py-1 text-xs font-medium border text-body-subtle">
<span className="px-3 py-1 text-sm font-medium bg-body-subtle text-body-inverse">
Default
</span>
</div>
Expand All @@ -74,16 +72,21 @@ function Address({
<div className="flex flex-row font-medium mt-6 items-baseline">
<Link
to={`/account/address/${encodeURIComponent(address.id)}`}
className="text-left underline text-body-subtle"
className="text-body-subtle after:bg-body-subtle"
prefetch="intent"
variant="underline"
>
Edit
</Link>
<Form action="address/delete" method="delete">
<input type="hidden" name="addressId" value={address.id} />
<button className="text-left text-body-subtle ml-6 text-sm">
<Button
variant="underline"
className="after:bg-body-subtle text-body-subtle ml-6"
animate={false}
>
Remove
</button>
</Button>
</Form>
</div>
</div>
Expand Down
198 changes: 198 additions & 0 deletions app/components/account/edit-address-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { Check } from "@phosphor-icons/react";
import * as Checkbox from "@radix-ui/react-checkbox";
import * as Dialog from "@radix-ui/react-dialog";
import {
Form,
useActionData,
useNavigation,
useOutletContext,
useParams,
} from "@remix-run/react";
import { flattenConnection } from "@shopify/hydrogen";
import clsx from "clsx";
import { Button } from "~/components/button";
import Link from "~/components/link";
import type { AccountOutletContext } from "~/routes/($locale).account.edit";

export function AccountEditAddressForm() {
let { id: addressId } = useParams();
let isNewAddress = addressId === "add";
let actionData = useActionData<{ formError?: string }>();
let { state } = useNavigation();
let { customer } = useOutletContext<AccountOutletContext>();
let addresses = flattenConnection(customer.addresses);
let defaultAddress = customer.defaultAddress;
/**
* When a refresh happens (or a user visits this link directly), the URL
* is actually stale because it contains a special token. This means the data
* loaded by the parent and passed to the outlet contains a newer, fresher token,
* and we don't find a match. We update the `find` logic to just perform a match
* on the first (permanent) part of the ID.
*/
let normalizedAddress = decodeURIComponent(addressId ?? "").split("?")[0];
let address = addresses.find((address) =>
address.id?.startsWith(normalizedAddress),
);

return (
<div className="space-y-2">
<div className="text-xl py-2.5">
{isNewAddress ? "Add new address" : "Edit address"}
</div>
<Form method="post" className="space-y-3">
<input
type="hidden"
name="addressId"
value={address?.id ?? addressId}
/>
{actionData?.formError && (
<div className="flex items-center justify-center bg-red-100 text-red-900 p-3">
{actionData.formError}
</div>
)}
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="firstName"
name="firstName"
required
type="text"
autoComplete="given-name"
placeholder="First name"
aria-label="First name"
defaultValue={address?.firstName ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="lastName"
name="lastName"
required
type="text"
autoComplete="family-name"
placeholder="Last name"
aria-label="Last name"
defaultValue={address?.lastName ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="company"
name="company"
type="text"
autoComplete="organization"
placeholder="Company"
aria-label="Company"
defaultValue={address?.company ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="address1"
name="address1"
type="text"
autoComplete="address-line1"
placeholder="Address line 1*"
required
aria-label="Address line 1"
defaultValue={address?.address1 ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="address2"
name="address2"
type="text"
autoComplete="address-line2"
placeholder="Address line 2"
aria-label="Address line 2"
defaultValue={address?.address2 ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="city"
name="city"
type="text"
required
autoComplete="address-level2"
placeholder="City"
aria-label="City"
defaultValue={address?.city ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="zoneCode"
name="zoneCode"
type="text"
autoComplete="address-level1"
placeholder="State / Province (zoneCode)"
required
aria-label="State / Province (zoneCode)"
defaultValue={address?.zoneCode ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="zip"
name="zip"
type="text"
autoComplete="postal-code"
placeholder="Zip / Postal Code"
required
aria-label="Zip"
defaultValue={address?.zip ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="territoryCode"
name="territoryCode"
type="text"
autoComplete="country"
placeholder="Country (Territory) Code"
required
aria-label="Country (Territory) Code"
defaultValue={address?.territoryCode ?? ""}
/>
<input
className="appearance-none border border-line p-3 focus:outline-none w-full"
id="phone"
name="phoneNumber"
type="tel"
autoComplete="tel"
placeholder="Phone"
aria-label="Phone"
defaultValue={address?.phoneNumber ?? ""}
/>
<div className="flex items-center gap-2.5">
<Checkbox.Root
name="defaultAddress"
id="defaultAddress"
defaultChecked={defaultAddress?.id === address?.id}
className={clsx(
"w-5 h-5 shrink-0",
"border border-line focus-visible:outline-none",
"disabled:cursor-not-allowed disabled:opacity-50",
)}
>
<Checkbox.Indicator className="flex items-center justify-center text-current">
<Check className="w-4 h-4" weight="regular" />
</Checkbox.Indicator>
</Checkbox.Root>
<label htmlFor="defaultAddress">Set as default address</label>
</div>
<div className="flex gap-6 items-center justify-end">
<Dialog.Close asChild>
<Link
to="/account/address"
className="hover:underline underline-offset-4"
>
Cancel
</Link>
</Dialog.Close>
<Button
className="mb-2"
type="submit"
variant="primary"
disabled={state !== "idle"}
>
{state === "submitting" ? "Saving" : "Save"}
</Button>
</div>
</Form>
</div>
);
}
Loading

0 comments on commit bd3afe6

Please sign in to comment.