Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Jan 5, 2022
0 parents commit abb3ab5
Show file tree
Hide file tree
Showing 76 changed files with 22,132 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/.cache
/.env
/build
/public/build
/node_modules

/.env.example
/docker-compose.yml
/README.md
/.dockerignore
/.gitignore
/Dockerfile
/fly.toml
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Used to encrypt cookies
ENCRYPTION_KEY="rofl1234"

# Used for swr request-response cache by providers
REDIS_URL="redis://:remixrocks@localhost:6379"

# Credentials for the shopify provider
SHOPIFY_STORE="next-js-store"
SHOPIFY_STOREFRONT_ACCESS_TOKEN="ef7d41c7bf7e1c214074d0d3047bcd7b"
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules

/.cache
/build
/public/build
/app/styles/global.css
.env
51 changes: 51 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
FROM node:17-bullseye-slim as base

# install open ssl for prisma
# RUN apt-get update && apt-get install -y openssl

ENV NODE_ENV=production
ENV PORT=8080

# install all node_modules, including dev
FROM base as deps

RUN mkdir /app/
WORKDIR /app/

# ADD prisma .
ADD patches .
ADD package.json package-lock.json ./
RUN npm install --production=false

# install only production modules
FROM deps as production-deps

WORKDIR /app/

RUN npm prune --production=true

## build the app
FROM deps as build

WORKDIR /app/

ADD . .
RUN npm run build

## copy over assets required to run the app
FROM base

RUN mkdir /app/
WORKDIR /app/

# ADD prisma .

COPY --from=production-deps /app/node_modules /app/node_modules
COPY --from=production-deps /app/package.json /app/package.json
COPY --from=production-deps /app/package-lock.json /app/package-lock.json
COPY --from=build /app/build /app/build
COPY --from=build /app/public /app/public

EXPOSE 8080

CMD ["npm", "start"]
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Welcome to Remix!

- [Remix Docs](https://remix.run/docs)

## Development

From your terminal:

```sh
npm run dev
```

This starts your app in development mode, rebuilding assets on file changes.

## Deployment

First, build your app for production:

```sh
npm run build
```

Then run the app in production mode:

```sh
npm start
```

Now you'll need to pick a host to deploy it to.

### DIY

If you're familiar with deploying node applications, the built-in Remix app server is production-ready.

Make sure to deploy the output of `remix build`

- `build/`
- `public/build/`

### Using a Template

When you ran `npx create-remix@latest` there were a few choices for hosting. You can run that again to create a new project, then copy over your `app/` folder to the new project that's pre-configured for your target server.

```sh
cd ..
# create a new project, and pick a pre-configured host
npx create-remix@latest
cd my-new-remix-app
# remove the new project's app (not the old one!)
rm -rf app
# copy your app over
cp -R ../my-old-remix-app/app app
```
21 changes: 21 additions & 0 deletions app/commerce.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createShopifyProvider } from "./models/ecommerce-providers/shopify.server";
import { createSwrRedisCache } from "./models/request-response-caches/swr-redis-cache.server";

import redisClient from "./redis.server";

if (!process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN) {
throw new Error(
"SHOPIFY_STOREFRONT_ACCESS_TOKEN environment variable is not set"
);
}

let commerceProvider = createShopifyProvider({
shop: process.env.SHOPIFY_STORE!,
storefrontAccessToken: process.env.SHOPIFY_STOREFRONT_ACCESS_TOKEN,
maxAgeSeconds: 60,
cache: createSwrRedisCache({
redisClient,
}),
});

export default commerceProvider;
139 changes: 139 additions & 0 deletions app/components/cart-listitem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import type { ReactNode } from "react";
import { useFetcher } from "remix";
import cn from "classnames";

import { PickTranslations } from "~/translations.server";

import { OptimizedImage } from "./optimized-image";

import { CloseIcon, MinusIcon, PlusIcon } from "./icons";

export function CartListItem({
formattedOptions,
formattedPrice,
image,
quantity,
title,
variantId,
translations,
}: {
formattedOptions: ReactNode;
formattedPrice: ReactNode;
image: string;
quantity: number;
title: ReactNode;
variantId: string;
translations: PickTranslations<
"Add item" | "Remove from cart" | "Subtract item" | "Quantity: $1"
>;
}) {
let { Form } = useFetcher();

return (
<li key={variantId} className="mb-6">
<div className="flex">
<div className="relative block aspect-square w-16 mr-4">
<OptimizedImage
className="absolute inset-0 bg-pink-brand"
src={image}
alt=""
responsive={[
{
size: {
width: 64,
height: 64,
},
},
{
size: {
width: 128,
height: 128,
},
},
]}
/>
</div>
<div className="flex-1 pr-2">
<h2 className="text-lg">{title}</h2>
{formattedOptions ? (
<p className="text-sm text-gray-300">{formattedOptions}</p>
) : null}
</div>
<p className="text-sm">{formattedPrice}</p>
</div>
<div className="flex mt-2">
<Form action="/cart" method="post">
<input type="hidden" name="_action" defaultValue="delete" />
<input
key={variantId}
type="hidden"
defaultValue={variantId}
name="variantId"
/>
<button
type="submit"
className="w-9 h-9 flex items-center justify-center border border-zinc-700 mr-2"
>
<span className="sr-only">{translations["Remove from cart"]}</span>
<CloseIcon className="w-6 h-6" />
</button>
</Form>
<div className="p-1 px-3 border border-zinc-700 flex-1 h-9">
<span className="sr-only">
{translations["Quantity: $1"]?.replace("$1", quantity.toString())}
</span>
<span aria-hidden={true}>{quantity}</span>
</div>
<Form action="/cart" method="post">
<input type="hidden" name="_action" defaultValue="set-quantity" />
<input
key={variantId}
type="hidden"
defaultValue={variantId}
name="variantId"
/>
<input
key={quantity - 1 <= 0 ? 1 : quantity - 1}
type="hidden"
name="quantity"
disabled={quantity - 1 <= 0}
defaultValue={quantity - 1 <= 0 ? 1 : quantity - 1}
/>
<button
type="submit"
disabled={quantity - 1 <= 0}
className={cn(
"w-9 h-9 flex items-center justify-center border border-zinc-700 border-l-0",
quantity - 1 <= 0 && "text-gray-300"
)}
>
<span className="sr-only">{translations["Subtract item"]}</span>
<MinusIcon className="w-6 h-6" />
</button>
</Form>
<Form action="/cart" method="post">
<input type="hidden" name="_action" defaultValue="set-quantity" />
<input
key={variantId}
type="hidden"
defaultValue={variantId}
name="variantId"
/>
<input
key={quantity + 1}
type="hidden"
name="quantity"
defaultValue={quantity + 1}
/>
<button
type="submit"
className="w-9 h-9 flex items-center justify-center border border-zinc-700 border-l-0"
>
<span className="sr-only">{translations["Add item"]}</span>
<PlusIcon className="w-6 h-6" />
</button>
</Form>
</div>
</li>
);
}
Loading

0 comments on commit abb3ab5

Please sign in to comment.