Skip to content

Commit

Permalink
Display offers with product images, #1, #21, closes #35 with speculat…
Browse files Browse the repository at this point in the history
…ive offer imports
  • Loading branch information
fabiancook committed Jun 22, 2023
1 parent ab89632 commit fd16743
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 29 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export interface Expiring {
expiresAt?: string;
}

export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile" | "offer" | "offerFile" | "metrics"
export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile" | "offer" | "offerFile"
export type BaseFileRemoteSourceName = "discord" | BaseFileStoreType;
export type RemoteFileSourceName = BaseFileRemoteSourceName | `${BaseFileRemoteSourceName}_${number}`;

Expand Down Expand Up @@ -371,6 +371,8 @@ export type MaybeNumberString = `${number}` | string;
export interface OfferPrice {
price: MaybeNumberString;
currency: string;
currencyCode?: string;
countryCode?: string;
}

export interface ProductOfferItem {
Expand Down
4 changes: 2 additions & 2 deletions src/data/file/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import {isNumberString, ok} from "../../is";
import {BaseFileRemoteSourceName, RemoteFileSourceName} from "../data";
import {index} from "cheerio/lib/api/traversing";

export const TYPE_BASE_NAMES: BaseFileRemoteSourceName[] = ["product", "inventory"];
const NAMES: BaseFileRemoteSourceName[] = ["discord", ...TYPE_BASE_NAMES, "productFile", "inventoryFile"];
export const TYPE_BASE_NAMES: BaseFileRemoteSourceName[] = ["product", "inventory", "offer"];
const NAMES: BaseFileRemoteSourceName[] = ["discord", ...TYPE_BASE_NAMES, "productFile", "inventoryFile", "offerFile"];
const NAMES_STRINGS: string[] = NAMES;

export type RemoteSourceEnvName = "token" | "origin" | "store" | "name" | "prefix" | "url" | "cacheBust" | "enableFileSource";
Expand Down
2 changes: 1 addition & 1 deletion src/data/file/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {Expiring} from "../expiring";

export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile" | "offer" | "offerFile" | "metrics"
export type BaseFileStoreType = "product" | "inventory" | "productFile" | "inventoryFile" | "offer" | "offerFile"
export type BaseFileRemoteSourceName = "discord" | BaseFileStoreType;
export type RemoteFileSourceName = BaseFileRemoteSourceName | `${BaseFileRemoteSourceName}_${number}`;

Expand Down
8 changes: 8 additions & 0 deletions src/data/offer/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ export const offerData = {
currency: {
type: "string",
nullable: true
},
currencyCode: {
type: "string",
nullable: true
},
countryCode: {
type: "string",
nullable: true
}
},
required: ["status", "items"],
Expand Down
2 changes: 2 additions & 0 deletions src/data/offer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export type MaybeNumberString = `${number}` | string;
export interface OfferPrice {
price: MaybeNumberString;
currency: string;
currencyCode?: string;
countryCode?: string;
}

export interface ProductOfferItem {
Expand Down
14 changes: 7 additions & 7 deletions src/package.readonly.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// File generated by scripts/pre-build.js

export const commit = "702a10693c876b80f9c570ac4204cbb901aefe10";
export const commitShort = "702a106";
export const commit = "ab89632e7ea893d6c516e091c4c27f944c123190";
export const commitShort = "ab89632";
export const commitAuthor = "Fabian Cook";
export const commitEmail = "[email protected]";
export const commitMessage = "1.0.0-alpha.43";
export const commitAt = "2023-06-22T08:44:58.000Z";
export const secondsBetweenCommitAndBuild = 3952.32;
export const minutesBetweenCommitAndBuild = 65.87;
export const timeBetweenCommitAndBuild = "65 minutes and 52 seconds";
export const commitMessage = "1.0.0-alpha.44";
export const commitAt = "2023-06-22T09:51:48.000Z";
export const secondsBetweenCommitAndBuild = 5254.22;
export const minutesBetweenCommitAndBuild = 87.57;
export const timeBetweenCommitAndBuild = "87 minutes and 34 seconds";
// Variables to be replaced after tests
export const secondsBetweenCommitAndTestCompletion = "";
export const minutesBetweenCommitAndTestCompletion = "";
Expand Down
42 changes: 29 additions & 13 deletions src/react/server/paths/product/list.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useData, useInput, useProducts} from "../../data";
import {listProductFiles, File} from "../../../../data";
import {listProductFiles, File, listOffers, Offer} from "../../../../data";
import {isAnonymous} from "../../../../authentication";
import {FastifyRequest} from "fastify";
import {ok} from "../../../../is";
Expand All @@ -13,6 +13,7 @@ export const cache = true;
export interface ProductInfo {
images600: File[]
productImages: Record<string, File>
offers: Offer[];
}

type Params = {
Expand All @@ -39,17 +40,21 @@ export async function handler(): Promise<ProductInfo> {
}
)
)
return { images600, productImages };
const offers = await listOffers({
public: isAnonymous()
})
return { images600, productImages, offers };
}

const LINK_CLASS = "text-blue-600 hover:bg-white underline hover:underline-offset-2";

export function ListProducts() {
const products = useProducts();
const { isAnonymous } = useData();
const { images600, productImages } = useInput<ProductInfo>();
const { images600, productImages, offers } = useInput<ProductInfo>();
const sorted = useMemo(() => {
return [...products]
.filter(product => !product.generic)
.sort((a, b) => {
if (productImages[a.productId] && !productImages[b.productId]) {
return -1;
Expand All @@ -66,19 +71,30 @@ export function ListProducts() {
{!isAnonymous ? <a href="/product/create" className={LINK_CLASS}>Create Product</a> : undefined}
<div className="mt-8 grid grid-cols-1 gap-y-12 sm:grid-cols-2 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8">
{sorted.map(product => {
const image = images600.find(file => file.productId === product.productId);
const images = images600.filter(file => file.productId === product.productId);
const productOffer = offers.find(offer => (
offer.items.length === 1 &&
offer.items.find(item => item.type === "product" && item.productId === product.productId)
))
return (
<div key={product.productId}>
<div key={product.productId} className="flex justify-between flex-col">
<div className="relative">
<div className="relative h-72 w-full overflow-hidden rounded-lg">
{
image ? (
<img
src={image.url}
alt={String(image.alt || product.productName)}
className="h-full w-full object-cover object-center"
/>
) : undefined
images.map(
(image, index, array) => (
<img
data-index={index}
data-length={array.length}
loading={index === 0 ? "eager" : "lazy"}
hidden={index !== 0}
key={index}
src={image.url}
alt={String(image.alt || product.productName)}
className="h-full w-full object-cover object-center"
/>
)
)
}
</div>
<div className="relative mt-4">
Expand All @@ -90,7 +106,7 @@ export function ListProducts() {
aria-hidden="true"
className="absolute inset-x-0 bottom-0 h-36 bg-gradient-to-t from-black opacity-50"
/>
<p className="relative text-lg font-semibold text-white">$PRICE</p>
<p className="relative text-lg font-semibold text-white">{productOffer ? `${productOffer.currencyCode ?? "$"}${productOffer.price}` : ""}</p>
</div>
</div>
<div className="mt-6">
Expand Down
36 changes: 31 additions & 5 deletions src/tests/remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,16 @@ import * as dotenv from "dotenv";

dotenv.config();

import {File, getRemoteSourceKey, getRemoteSources, Product, setProduct, TYPE_BASE_NAMES} from "../data";
import {
File,
getRemoteSourceKey,
getRemoteSources,
Offer,
Product,
setOffer,
setProduct,
TYPE_BASE_NAMES
} from "../data";
import {importRemoteSource} from "../remote/import";
import {ok} from "../is";

Expand All @@ -16,16 +25,33 @@ const bases = sources.filter(source => !typed.includes(source));
const imported: File[] = [];

for (const source of bases) {
const file = await importRemoteSource({
source,
json: true,
async handler(input: Product[]) {

let handler;

if (source === "product") {
handler = async function handler(input: Product[]) {
// console.log(input);
for (const product of input) {
await setProduct(product);
}
console.log("Updated products");
return input;
}
} else if (source === "offer") {
handler = async function handler(input: Offer[]) {
// console.log(input);
for (const offer of input) {
await setOffer(offer);
}
console.log("Updated offers");
return input;
}
}
if (!handler) continue;
const file = await importRemoteSource<unknown>({
source,
json: true,
handler
});
console.log(file);
imported.push(file);
Expand Down
1 change: 1 addition & 0 deletions src/view/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
import OpenNetworkServer, {OpenNetworkServerProps, ReactData} from "../react/server";
import { renderToStaticMarkup } from "react-dom/server";
import {
listOffers,
listOrganisations,
listPartners, listProducts,
} from "../data";
Expand Down

0 comments on commit fd16743

Please sign in to comment.