Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extension-section/src/components/ProductCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styles from '../styles/style.css';
export function ProductCard({ product }) {
return (
<div className={styles.product}>
{product.medias.map((media) => (
{product.media?.map((media) => (
<img src={media.url} alt={media.alt} />
))}
<h1>{product.name}</h1>
Expand Down
110 changes: 86 additions & 24 deletions extension-section/src/sections/product-list.jsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,107 @@
import React, { useEffect } from "react";
import { useGlobalStore, useFPI } from "fdk-core/utils"; // Importing hooks from fdk-core utilities
import { Helmet } from "react-helmet-async"; // Importing Helmet for managing changes to the document head
import styles from "../styles/style.css"; // Importing CSS styles
import { ProductCard } from "../components/ProductCard"; // Importing the ProductCard component

import { useGlobalStore, useFPI } from "fdk-core/utils";
import { Helmet } from "react-helmet-async";
import styles from "../styles/style.css";
import { ProductCard } from "../components/ProductCard";
// GraphQL query as a template literal string to fetch products with dynamic variables
const PLP_PRODUCTS = `query products(
$first: Int
$pageNo: Int
$after: String
$pageType: String
) {
products(
first: $first
pageNo: $pageNo
after: $after
pageType: $pageType
) {
page {
current
next_id
has_previous
has_next
item_total
type
size
}
items {
price {
effective {
currency_code
currency_symbol
max
min
}
}
media {
alt
type
url
}
slug
name
}
}
}
`;

export function Component({ props }) {
const fpi = useFPI();
const products = useGlobalStore(fpi.getters.PRODUCTS);
// Functional component definition using destructuring to access props
export function Component({ title = 'Extension Title Default' }) {
const fpi = useFPI(); // Using a custom hook to access functional programming interface
const products = useGlobalStore(fpi.getters.PRODUCTS); // Accessing global store to retrieve products
const productItems = products?.items ?? []; // Nullish coalescing operator to handle undefined products

const productItems = products?.data?.items ?? [];
// useEffect to perform side effects, in this case, data fetching
useEffect(() => {
// Checking if productItems is empty and then executing GraphQL query
if (!productItems.length) {
fpi.catalog.getProducts({});
const payload = {
enableFilter: true, // Enabling filter option in the query
first: 12, // Number of products to fetch
pageNo: 1, // Initial page number
pageType: "number", // Type of pagination
};
fpi.executeGQL(PLP_PRODUCTS, payload);
}
}, []);
}, [productItems.length, fpi]); // Dependency array to limit the execution of useEffect

const title = props?.title?.value ?? 'Extension Title Default'
// Conditionally rendering based on the availability of product items
if (!productItems.length) {
return <h2>No Products Found</h2>; // Display message when no products are found
}

return (
<div>
<Helmet>
<title>{ title }</title>
<title>{title}</title> // Setting the title of the page using Helmet
</Helmet>
<h1>Products List</h1>

{!productItems.length ? (
<h2>No Products</h2>
) : (
<div class={styles.container}>
{productItems.map((product) => (
<ProductCard product={product} key={product.slug} />
))}
</div>
)}
<div className={styles.container}>
{productItems.map((product) => (
<ProductCard product={product} key={product.slug} /> // Rendering ProductCard components for each product
))}
</div>
</div>
);
}

Component.serverFetch = ({ fpi }) => fpi.catalog.getProducts({});
// Server-side fetching logic for server-side rendering (SSR)
Component.serverFetch = ({ fpi }) => {
const payload = {
enableFilter: true,
first: 12,
pageNo: 1,
pageType: "number",
};

fpi.custom.setValue("test-extension", true); // Custom settings for the server-side execution context

return fpi.executeGQL(PLP_PRODUCTS, payload); // Executing GraphQL query on the server
};

// Exporting component settings for potential dynamic UI management or configuration panels
export const settings = {
label: "Product List",
name: "product-list",
Expand All @@ -49,7 +111,7 @@ export const settings = {
label: "Page Title",
type: "text",
default: "Extension Title",
info: "Page Title",
info: "Set the page title for the product list." // Description for the property
},
],
blocks: [],
Expand Down
41 changes: 36 additions & 5 deletions extension-section/src/styles/style.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,38 @@
/* General styles for the product grid */
.product {
color: red;
border: 1px solid red
}
.container {
display: flex;
}
flex-direction: column;
align-items: center;
width: 300px; /* Adjust width as necessary */
padding: 20px;
margin: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 10px;
background-color: #fff;
transition: transform 0.3s ease-in-out;
}

.product img {
width: 100%; /* Makes images responsive */
height: auto;
border-radius: 5px;
margin-bottom: 10px;
}

.product h1 {
font-size: 18px;
color: #333;
margin: 10px 0;
}

.product h2 {
font-size: 14px;
color: #666;
margin-bottom: 10px;
}

/* Hover effect for product card */
.product:hover {
transform: translateY(-5px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.2);
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gofynd/fdk-cli",
"version": "7.0.0",
"version": "7.0.1-beta.2",
"main": "index.js",
"license": "MIT",
"bin": {
Expand Down
13 changes: 10 additions & 3 deletions src/helper/download.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import fs from 'fs-extra';
import { uninterceptedApiClient } from '../lib/api/ApiClient';
export async function downloadFile(url: string, filePath: string) {

export async function downloadFile(url: string, filePath: string): Promise<void> {
// Ensure the file exists before attempting to write to it
fs.ensureFileSync(filePath);

// Create a writable stream to save the downloaded file
const writer = fs.createWriteStream(filePath);

// Fetch the file as a stream
const response = await uninterceptedApiClient.get(url, {
responseType: 'stream',
});

// Pipe the data stream to the file writer
response.data.pipe(writer);

// Return a promise that resolves when the download is finished or rejects if an error occurs
return new Promise<void>((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', reject);
writer.on('finish', () => resolve()); // Ensure resolve is called without any arguments
writer.on('error', error => reject(error)); // Directly pass the error to the reject function
});
}
Loading