After having worked creating two stores with Prestashop and Wordpress without programming. This project seemed practical, useful and an interesting experience for a junior developer.
The real interest of my project was not to have a large list of products that would require me a lot of time just to be able to describe and complete them. The idea of this business is simple, collect coffees from small businesses and turn it into a subscription model that allows me to make them known to them, and generate a business of discovery of new gourmet products.
Without a doubt the worst thing has been to start knowing the connection processes with π₯GraphQL, the conventional queries that we had seen did not work here.
The lack of "simple" documentation put me in some trouble to deal with the connection between our Backend and Shopify's StorefrontApi.
Installation and deployment Guide. To install the project you only have to go to the repository https://github.com/AlfonsoValle/CafesElSibarita , clone it and run a yarn run dev.
This project would not have worked without the mentorship of @Boyander as the head of Core Code School's FullStack Bootcamp and my colleague @Systrent, without him and the endless hours of trial and error this website would work much worse.
οΏ½οΈ Routes:
OPTIONS *
GET /especialidades/readSpecialities
HEAD /especialidades/readSpecialities
POST /especialidades/createSpecialities
DELETE /especialidades/deleteSpecialities/:_id
GET /sub
HEAD /sub
HEAD /sub/
GET /sub/single
HEAD /sub/single
GET /sub/checkout01
HEAD /sub/checkout01
GET /sub/checkout02
HEAD /sub/checkout02
ββββπ src/
β ββββπ routes/
β β ββββπ GraphQLApi/
β β β ββββπ AllProducts.ts
β β β ββββπ CheckoutMutationPrime.ts
β β β ββββπ CheckoutMutationSibarita.ts
β β β ββββπ ShopifyApp.ts
β β β ββββπ SingleProduct.ts
β β ββββπ Specialities/
β β ββββπ createSpecialities.ts
β β ββββπ deleteSpecialities.ts
β β ββββπ specialities.ts
β β ββββπ specialitiesApp.ts
β β ββββπ speciality.model.ts
β ββββπ app.ts
β ββββπ config.ts
β ββββπ db.ts
β ββββπ server.ts
ββββπ package.json
ββββπ tsconfig.json
ββββπ yarn.lock
import { FastifyPluginAsync } from "fastify";
import { AllProducts } from "./AllProducts";
import { CheckoutMutationPrime } from "./CheckoutMutationPrime";
import { CheckoutMutationSibarita } from "./CheckoutMutationSibarita";
import { SingleProductQuery } from "./SingleProduct";
export const ShopifyApp: FastifyPluginAsync = async (app) => {
app.register(AllProducts);
app.register(SingleProductQuery);
app.register(CheckoutMutationSibarita);
app.register(CheckoutMutationPrime);
};
import Shopify from "@shopify/shopify-api";
import { FastifyPluginAsync } from "fastify";
import { SHOPIFY_SHOP, STOREFRONT } from "../../config";
export const SingleProductQuery: FastifyPluginAsync = async (app) => {
// app.get('/products', {preValidation: app.authenticate}, async (req, res) => {
app.get<{ Querystring: { handle: string } }>("/single", async (req, res) => {
//Req
// req.body;
const { handle } = req.query;
// Load the access token as per instructions above
const Storefront: string = STOREFRONT;
// Shop from which we're fetching data
const shop: string = SHOPIFY_SHOP;
// StorefrontClient takes in the shop url and the Storefront Access Token for that shop.
const storefrontClient: any = new Shopify.Clients.Storefront(shop, Storefront);
try {
const product: any = await storefrontClient.query({
data: {
query: `query singleProductQuery($handle: String!) {
productByHandle(handle: $handle) {
title
description
updatedAt
priceRange {
minVariantPrice {
amount
}
}
images(first: 1) {
edges {
node {
transformedSrc
altText
}
}
}
variants(first: 1) {
edges {
node {
id
}
}
}
}
}`,
variables: {
handle,
},
},
});
console.log(product.body);
return product.body;
} catch (error) {
console.log(error);
}
});
};
ββββπ components/
β ββββπ Admin/
β β ββββπ Botondeformulario.tsx
β β ββββπ CreateSpeciality.tsx
β β ββββπ DeleteSpeciality.tsx
β β ββββπ EspecialidadCard.tsx
β β ββββπ ListaEspecialidades.tsx
β ββββπ home/
β β ββββπ Footer/
β β β ββββπ Socials.tsx
β β ββββπ Main Banner/
β β β ββββπ MainBanner.tsx
β β β ββββπ Prime.tsx
β β β ββββπ Sibarita.tsx
β β ββββπ Shopify/
β β β ββββπ ShopyCafeCard.tsx
β β β ββββπ ShopySubPrime.tsx
β β β ββββπ ShopySubSibarita.tsx
β β ββββπ Slider/
β β β ββββπ BannerSlider.tsx
β β ββββπ About.tsx
β β ββββπ MainHeadText.tsx
β β ββββπ Section.tsx
β ββββπ layout/
β β ββββπ Footer.tsx
β β ββββπ Header.tsx
β β ββββπ LateralMenu.tsx
β β ββββπ Layout.tsx
β β ββββπ Login.tsx
β β ββββπ Logo.tsx
β β ββββπ MainMenu.tsx
β ββββπ profile/
β β ββββπ ButtonForm.tsx
β β ββββπ CardProfile.tsx
β β ββββπ CrudProfile.tsx
β ββββπ Shared/
β β ββββπ AuthenticatedApp.tsx
β β ββββπ BotonHeader.tsx
β β ββββπ Spinner.tsx
β β ββββπ TokenApp.tsx
β ββββπ Subscriptions/
β β ββββπ CheckoutPrime.tsx
β β ββββπ CheckoutSibarita.tsx
β ββββπ Texts/
β ββββπ AboutUsText.tsx
ββββπ lib/
β ββββπ APIshopify.ts
β ββββπ AuthenticatedFetcher.ts
β ββββπ CurrencyFormat.ts
β ββββπ GetSingleProduct.ts
β ββββπ ProfileApi.ts
β ββββπ ProfileRepo.ts
β ββββπ PublicFetcher.ts
β ββββπ SpecialityRepo.ts
β ββββπ SpecialityToBackend.ts
β ββββπ Tokencontext.ts
ββββπ pages/
β ββββπ editarespecialidades/
β β ββββπ index.tsx
β ββββπ perfil/
β β ββββπ consultarPerfil.tsx
β β ββββπ editarPerfil.tsx
β β ββββπ index.tsx
β ββββπ sobrenosotros/
β β ββββπ index.tsx
β ββββπ subs/
β β ββββπ prime.tsx
β β ββββπ sibarita.tsx
β ββββπ index.tsx
β ββββπ _app.tsx
β ββββπ _document.tsx
ββββπ public/
β ββββπ images/
β ββββπ Fondo23.jpg
β ββββπ Fondo24.jpg
β ββββπ Fondo33.png
β ββββπ Fondo34.png
β ββββπ cafetera.jpg
β ββββπ coffee-bag-svgrepo-com.svg
β ββββπ decorativo.png
β ββββπ facebook.svg
β ββββπ favicon.png
β ββββπ fondocafe.jpg
β ββββπ fondocafebueno.jpg
β ββββπ instagram.svg
β ββββπ logoSibarita.png
β ββββπ twitter.svg
β ββββπ vasosibarita.png
ββββπ types/
β ββββπ emotion.d.ts
ββββπ .babelrc
ββββπ .env
ββββπ .gitignore
ββββπ next-env.d.ts
ββββπ next.config.js
ββββπ package.json
ββββπ postcss.config.js
ββββπ tailwind.config.js
ββββπ tsconfig.json
ββββπ yarn.lock
import { css } from "@emotion/react";
import useSWR from "swr";
import { DeleteSpeciality } from "../../lib/SpecialityRepo";
import { Spinner } from "../Shared/Spinner";
import { EspecialidadCard } from "./EspecialidadCard";
export const ListaEspecialidades: React.FC = () => {
const { data, mutate } = useSWR("/especialidades/readSpecialities", {
refreshInterval: 800,
});
return (
<div className="images-list">
<div
css={css`
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: 100%;
max-height: 300px;
padding: 0px 60px;
gap: 5px;
color: white;
border-radius: 10px;
`}
>
{data?.length > 0 ? (
data.map((item, i) => (
<EspecialidadCard
item={item}
onDelete={async () => {
await DeleteSpeciality(item._id);
mutate();
}}
/>
))
) : (
<Spinner />
)}
</div>
</div>
);
};