Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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": "6.2.7",
"version": "6.2.8-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((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