Skip to content

Commit

Permalink
feat: redirect actions for total no-js usability
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Jan 8, 2022
1 parent b626326 commit 3ca6d24
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 18 deletions.
23 changes: 21 additions & 2 deletions app/components/cart-listitem.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReactNode } from "react";
import { useFetcher } from "remix";
import { useFetcher, useLocation } from "remix";
import cn from "classnames";

import { PickTranslations } from "~/translations.server";
Expand Down Expand Up @@ -27,6 +27,7 @@ export function CartListItem({
"Add item" | "Remove from cart" | "Subtract item" | "Quantity: $1"
>;
}) {
let location = useLocation();
let { Form } = useFetcher();

return (
Expand Down Expand Up @@ -62,8 +63,14 @@ export function CartListItem({
<p className="text-sm">{formattedPrice}</p>
</div>
<div className="flex mt-2">
<Form action="/cart" method="post">
<Form method="post" action="/cart">
<input type="hidden" name="_action" defaultValue="delete" />
<input
key={location.pathname + location.search}
type="hidden"
name="redirect"
defaultValue={location.pathname + location.search}
/>
<input
key={variantId}
type="hidden"
Expand All @@ -86,6 +93,12 @@ export function CartListItem({
</div>
<Form action="/cart" method="post">
<input type="hidden" name="_action" defaultValue="set-quantity" />
<input
key={location.pathname + location.search}
type="hidden"
name="redirect"
defaultValue={location.pathname + location.search}
/>
<input
key={variantId}
type="hidden"
Expand Down Expand Up @@ -113,6 +126,12 @@ export function CartListItem({
</Form>
<Form action="/cart" method="post">
<input type="hidden" name="_action" defaultValue="set-quantity" />
<input
key={location.pathname + location.search}
type="hidden"
name="redirect"
defaultValue={location.pathname + location.search}
/>
<input
key={variantId}
type="hidden"
Expand Down
2 changes: 0 additions & 2 deletions app/components/cart-popover.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { Fragment } from "react";
import { Form } from "remix";
import { Dialog, Transition } from "@headlessui/react";
import cn from "classnames";

import { CartInfo } from "~/models/ecommerce-provider.server";
import { PickTranslations } from "~/translations.server";
Expand Down
13 changes: 7 additions & 6 deletions app/components/product-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ export function ProductDetails({
) : null}
</Form>
) : null}
<Form
replace
method="post"
action={location.pathname + location.search}
className="mt-8"
>
<Form replace method="post" className="mt-8">
<input
key={location.pathname + location.search}
defaultValue={location.pathname + location.search}
type="hidden"
name="redirect"
/>
<input
key={product.selectedVariantId}
defaultValue={product.selectedVariantId}
Expand Down
11 changes: 6 additions & 5 deletions app/containers/cart/cart.server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { json, redirect } from "remix";
import type { ActionFunction, HeadersFunction, LoaderFunction } from "remix";

import commerce from "~/commerce.server";
import type { CartInfo } from "~/models/ecommerce-provider.server";
import { updateCartItem, removeCartItem, getSession } from "~/session.server";
import { getTranslations, PickTranslations } from "~/translations.server";
import commerce from "~/commerce.server";
import type { CartInfo } from "~/models/ecommerce-provider.server";
import { validateRedirect } from "~/utils/redirect.server";

export let headers: HeadersFunction = ({ actionHeaders }) => {
return actionHeaders;
Expand All @@ -17,8 +18,8 @@ export let action: ActionFunction = async ({ request, params }) => {
]);

let formData = new URLSearchParams(body);
let redirectTo = validateRedirect(formData.get("redirect"), "/cart");
let action = formData.get("_action");
console.log(Array.from(formData));

try {
let cart = await session.getCart();
Expand All @@ -45,7 +46,7 @@ export let action: ActionFunction = async ({ request, params }) => {
}

await session.setCart(cart);
return json(null, {
return redirect(redirectTo, {
headers: {
"Set-Cookie": await session.commitSession(),
},
Expand All @@ -54,7 +55,7 @@ export let action: ActionFunction = async ({ request, params }) => {
console.error(error);
}

return null;
return redirect(redirectTo);
};

export type LoaderData = {
Expand Down
11 changes: 8 additions & 3 deletions app/containers/pdp/pdp.server.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { json } from "remix";
import { json, redirect } from "remix";
import type { ActionFunction, HeadersFunction, LoaderFunction } from "remix";

import commerce from "~/commerce.server";
import { addToCart, getSession } from "~/session.server";
import { getTranslations } from "~/translations.server";
import type { PickTranslations } from "~/translations.server";
import type { FullProduct } from "~/models/ecommerce-provider.server";
import { validateRedirect } from "~/utils/redirect.server";

export let headers: HeadersFunction = ({ actionHeaders }) => {
return actionHeaders;
Expand All @@ -17,15 +18,19 @@ export let action: ActionFunction = async ({ request, params }) => {
getSession(request, params),
]);
let formData = new URLSearchParams(body);
let redirectTo = validateRedirect(
formData.get("redirect"),
`/product/${params.slug}`
);
let variantId = formData.get("variantId");
if (!variantId) {
return null;
return redirect(redirectTo);
}

let cart = await session.getCart();
cart = addToCart(cart, variantId, 1);
await session.setCart(cart);
return json(null, {
return redirect(redirectTo, {
headers: {
"Set-Cookie": await session.commitSession(),
},
Expand Down
10 changes: 10 additions & 0 deletions app/utils/redirect.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export function validateRedirect(
redirect: string | null | undefined,
defaultRediret: string
) {
if (redirect?.startsWith("/") && redirect[1] !== "/") {
return redirect;
}

return defaultRediret;
}

0 comments on commit 3ca6d24

Please sign in to comment.