memo and lazy load
This commit is contained in:
parent
36c2dd98a2
commit
bd6c90ab9d
5 changed files with 268 additions and 206 deletions
|
|
@ -1,184 +1,236 @@
|
|||
project/
|
||||
├── frontend/
|
||||
│ ├── node_modules/
|
||||
│ ├── src/
|
||||
│ │ ├── pages/
|
||||
│ │ │ ├── Admin/
|
||||
│ │ │ │ ├── BrandingPage.jsx
|
||||
│ │ │ │ ├── ReportsPage.jsx
|
||||
│ │ │ │ ├── ProductEditPage.jsx
|
||||
│ │ │ │ ├── OrdersPage.jsx
|
||||
│ │ │ │ ├── EmailTemplatesPage.jsx
|
||||
│ │ │ │ ├── SettingsPage.jsx
|
||||
│ │ │ │ ├── BlogEditPage.jsx
|
||||
│ │ │ │ ├── CategoriesPage.jsx
|
||||
│ │ │ │ ├── CustomersPage.jsx
|
||||
│ │ │ │ ├── CouponsPage.jsx
|
||||
│ │ │ │ ├── ProductReviewsPage.jsx
|
||||
│ │ │ │ ├── BlogPage.jsx
|
||||
│ │ │ │ ├── BlogCommentsPage.jsx
|
||||
│ │ │ │ ├── DashboardPage.jsx
|
||||
│ │ │ │ └── ProductsPage.jsx
|
||||
│ │ │ ├── CheckoutPage.jsx
|
||||
│ │ │ ├── CouponEditPage.jsx
|
||||
│ │ │ ├── ProductsPage.jsx
|
||||
│ │ │ ├── UserOrdersPage.jsx
|
||||
│ │ │ ├── CartPage.jsx
|
||||
│ │ │ ├── ProductDetailPage.jsx
|
||||
│ │ │ ├── BlogDetailPage.jsx
|
||||
│ │ │ ├── BlogPage.jsx
|
||||
│ │ │ ├── CouponRedemptionsPage.jsx
|
||||
│ │ │ ├── HomePage.jsx
|
||||
│ │ │ ├── LoginPage.jsx
|
||||
│ │ │ ├── PaymentSuccessPage.jsx
|
||||
│ │ │ ├── RegisterPage.jsx
|
||||
│ │ │ ├── VerifyPage.jsx
|
||||
│ │ │ ├── NotFoundPage.jsx
|
||||
│ │ │ └── PaymentCancelPage.jsx
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── emailTemplateService.js
|
||||
│ │ │ ├── blogAdminService.js
|
||||
│ │ │ ├── adminService.js
|
||||
│ │ │ ├── couponService.js
|
||||
│ │ │ ├── productService.js
|
||||
│ │ │ ├── productReviewService.js
|
||||
│ │ │ ├── consentService.js (NEW)
|
||||
│ │ │ ├── settingsAdminService.js
|
||||
│ │ │ ├── imageService.js
|
||||
│ │ │ ├── cartService.js
|
||||
│ │ │ ├── categoryAdminService.js
|
||||
│ │ │ ├── authService.js
|
||||
│ │ │ ├── blogService.js
|
||||
│ │ │ └── api.js
|
||||
│ │ ├── components/
|
||||
│ │ │ ├── ProductReviews.jsx
|
||||
│ │ │ ├── OrderStatusDialog.jsx
|
||||
│ │ │ ├── ImageUploader.jsx
|
||||
│ │ │ ├── CookieConsentPopup.jsx
|
||||
│ │ │ ├── CookieSettingsButton.jsx
|
||||
│ │ │ ├── Footer.jsx
|
||||
│ │ │ ├── CouponInput.jsx
|
||||
│ │ │ ├── EmailDialog.jsx
|
||||
│ │ │ ├── StripePaymentForm.jsx
|
||||
│ │ │ ├── ProductImage.jsx
|
||||
│ │ │ ├── ProtectedRoute.jsx
|
||||
│ │ │ ├── Notifications.jsx
|
||||
│ │ │ └── ProductRatingDisplay.jsx
|
||||
│ │ ├── hooks/
|
||||
│ │ │ ├── apiHooks.js
|
||||
│ │ │ ├── blogHooks.js
|
||||
│ │ │ ├── emailTemplateHooks.js
|
||||
│ │ │ ├── adminHooks.js
|
||||
│ │ │ ├── productReviewHooks.js
|
||||
│ │ │ ├── reduxHooks.js
|
||||
│ │ │ ├── couponAdminHooks.js
|
||||
│ │ │ ├── settingsAdminHooks.js
|
||||
│ │ │ ├── categoryAdminHooks.js
|
||||
│ │ │ └── brandingHooks.js
|
||||
│ │ ├── layouts/
|
||||
│ │ │ ├── MainLayout.jsx
|
||||
│ │ │ ├── AdminLayout.jsx
|
||||
│ │ │ └── AuthLayout.jsx
|
||||
│ │ ├── features/
|
||||
│ │ │ ├── ui/
|
||||
│ │ │ │ └── uiSlice.js
|
||||
│ │ │ ├── cart/
|
||||
│ │ │ │ └── cartSlice.js
|
||||
│ │ │ ├── auth/
|
||||
│ │ │ │ └── authSlice.js
|
||||
│ │ │ └── theme/
|
||||
│ │ │ ├── ThemeProvider.jsx
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── utils/
|
||||
│ │ │ └── imageUtils.js
|
||||
│ │ ├── store/
|
||||
│ │ │ └── index.js
|
||||
│ │ ├── context/
|
||||
│ │ │ └── StripeContext.jsx
|
||||
│ │ └── assets/
|
||||
│ │ ├── App.jsx
|
||||
│ │ ├── main.jsx
|
||||
│ │ └── config.js
|
||||
│ └── public/
|
||||
│ ├── favicon.svg
|
||||
│ ├── vite.config.js
|
||||
│ ├── README.md
|
||||
│ ├── Dockerfile
|
||||
│ ├── nginx.conf
|
||||
│ ├── setup-frontend.sh
|
||||
│ ├── index.html
|
||||
│ └── .env
|
||||
/ (root)
|
||||
├── .env
|
||||
├── .gitignore
|
||||
├── Dockerfile
|
||||
├── README.md
|
||||
├── config.js
|
||||
├── docker-compose.yml
|
||||
├── fileStructure.txt
|
||||
├── index.html
|
||||
├── main.jsx
|
||||
├── nginx.conf
|
||||
├── package.json
|
||||
├── setup-frontend.sh
|
||||
├── start.sh
|
||||
├── vite.config.js
|
||||
│
|
||||
├── backend/
|
||||
│ ├── node_modules/
|
||||
│ ├── src/
|
||||
│ │ ├── routes/
|
||||
│ │ │ ├── cart.js
|
||||
│ │ │ ├── couponAdmin.js
|
||||
│ │ │ ├── emailTemplatesAdmin.js
|
||||
│ │ │ ├── productAdmin.js
|
||||
│ │ │ ├── blogAdmin.js
|
||||
│ │ │ ├── orderAdmin.js
|
||||
│ │ │ ├── settingsAdmin.js
|
||||
│ │ │ ├── blog.js
|
||||
│ │ │ ├── auth.js
|
||||
│ │ │ ├── productReviews.js
|
||||
│ │ │ ├── stripePayment.js
|
||||
│ │ │ ├── products.js
|
||||
│ │ │ ├── productReviewsAdmin.js
|
||||
│ │ │ ├── blogCommentsAdmin.js
|
||||
│ │ │ ├── userAdmin.js
|
||||
│ │ │ ├── categoryAdmin.js
|
||||
│ │ │ ├── shipping.js
|
||||
│ │ │ ├── images.js
|
||||
│ │ │ ├── userOrders.js
|
||||
│ │ │ ├── publicSettings.js
|
||||
│ │ │ └── productAdminImages.js
|
||||
│ │ ├── middleware/
|
||||
│ │ │ ├── upload.js
|
||||
│ │ │ ├── adminAuth.js
|
||||
│ │ │ └── auth.js
|
||||
│ │ ├── services/
|
||||
│ │ │ ├── shippingService.js
|
||||
│ │ │ ├── emailService.js
|
||||
│ │ │ └── notificationService.js
|
||||
│ │ ├── models/
|
||||
│ │ │ └── SystemSettings.js
|
||||
│ │ └── db/
|
||||
│ │ ├── index.js
|
||||
│ │ ├── index.js
|
||||
│ │ └── config.js
|
||||
│ └── public/
|
||||
│ ├── uploads/
|
||||
│ │ ├── products/
|
||||
│ │ └── blog/
|
||||
│ ├── package-lock.json
|
||||
│ ├── README.md
|
||||
│ ├── .env
|
||||
│ ├── package.json
|
||||
│ ├── Dockerfile
|
||||
│ └── .gitignore
|
||||
└── db/
|
||||
├── init/
|
||||
│ ├── 18-email-templates.sql
|
||||
│ ├── 01-schema.sql
|
||||
│ ├── 02-seed.sql
|
||||
│ ├── 16-blog-schema.sql
|
||||
│ ├── 15-coupon.sql
|
||||
│ ├── 17-product-reviews.sql
|
||||
│ ├── 19-branding-settings.sql (NEW)
|
||||
│ ├── 04-product-images.sql
|
||||
│ ├── 09-system-settings.sql
|
||||
│ ├── 14-product-notifications.sql
|
||||
│ ├── 10-payment.sql
|
||||
│ ├── 11-notifications.sql
|
||||
│ ├── 12-shipping-orders.sql
|
||||
│ ├── 08-create-email.sql
|
||||
│ ├── 05-admin-role.sql
|
||||
│ ├── 03-api-key.sql
|
||||
│ ├── 07-user-keys.sql
|
||||
│ ├── 13-cart-metadata.sql
|
||||
│ └── 06-product-categories.sql
|
||||
└── test/
|
||||
├── fileStructure.txt
|
||||
├── docker-compose.yml
|
||||
└── .gitignore
|
||||
│ ├── public/
|
||||
│ │ ├── seo-files/
|
||||
│ │ ├── uploads/
|
||||
│ │ ├── robots.txt
|
||||
│ │ └── sitemap.xml
|
||||
│ │
|
||||
│ └── src/
|
||||
│ ├── db/
|
||||
│ │ └── index.js
|
||||
│ │
|
||||
│ ├── middleware/
|
||||
│ │ ├── adminAuth.js
|
||||
│ │ ├── auth.js
|
||||
│ │ ├── seoMiddleware.js
|
||||
│ │ └── upload.js
|
||||
│ │
|
||||
│ ├── models/
|
||||
│ │ └── SystemSettings.js
|
||||
│ │
|
||||
│ ├── routes/
|
||||
│ │ ├── auth.js
|
||||
│ │ ├── blog.js
|
||||
│ │ ├── blogAdmin.js
|
||||
│ │ ├── blogCommentsAdmin.js
|
||||
│ │ ├── cart.js
|
||||
│ │ ├── categoryAdmin.js
|
||||
│ │ ├── couponAdmin.js
|
||||
│ │ ├── emailCampaignsAdmin.js
|
||||
│ │ ├── emailTemplatesAdmin.js
|
||||
│ │ ├── emailTracking.js
|
||||
│ │ ├── images.js
|
||||
│ │ ├── mailingListAdmin.js
|
||||
│ │ ├── orderAdmin.js
|
||||
│ │ ├── productAdmin.js
|
||||
│ │ ├── productAdminImages.js
|
||||
│ │ ├── productReviews.js
|
||||
│ │ ├── productReviewsAdmin.js
|
||||
│ │ ├── products.js
|
||||
│ │ ├── publicSettings.js
|
||||
│ │ ├── settingsAdmin.js
|
||||
│ │ ├── shipping.js
|
||||
│ │ ├── stripePayment.js
|
||||
│ │ ├── subscribers.js
|
||||
│ │ ├── subscribersAdmin.js
|
||||
│ │ ├── userAdmin.js
|
||||
│ │ └── userOrders.js
|
||||
│ │
|
||||
│ ├── services/
|
||||
│ │ ├── cacheService.js
|
||||
│ │ ├── emailService.js
|
||||
│ │ ├── notificationService.js
|
||||
│ │ ├── queueService.js
|
||||
│ │ ├── shippingService.js
|
||||
│ │ ├── sitemapService.js
|
||||
│ │ └── storageService.js
|
||||
│ │
|
||||
│ └── uploads/
|
||||
│ ├── temp/
|
||||
│ ├── config.js
|
||||
│ ├── index.js
|
||||
│ └── worker.js
|
||||
│
|
||||
├── db/
|
||||
│ ├── init/
|
||||
│ │ ├── 01-schema.sql
|
||||
│ │ ├── 02-seed.sql
|
||||
│ │ ├── 03-api-key.sql
|
||||
│ │ ├── 04-product-images.sql
|
||||
│ │ ├── 05-admin-role.sql
|
||||
│ │ ├── 06-product-categories.sql
|
||||
│ │ ├── 07-user-keys.sql
|
||||
│ │ ├── 08-create-email.sql
|
||||
│ │ ├── 09-system-settings.sql
|
||||
│ │ ├── 10-payment.sql
|
||||
│ │ ├── 11-notifications.sql
|
||||
│ │ ├── 12-shipping-orders.sql
|
||||
│ │ ├── 13-cart-metadata.sql
|
||||
│ │ ├── 14-product-notifications.sql
|
||||
│ │ ├── 15-coupon.sql
|
||||
│ │ ├── 16-blog-schema.sql
|
||||
│ │ ├── 17-product-reviews.sql
|
||||
│ │ ├── 18-email-templates.sql
|
||||
│ │ ├── 19-branding-settings.sql
|
||||
│ │ ├── 20-mailinglist.sql
|
||||
│ │ ├── 21-order-refund.sql
|
||||
│ │ └── 22-blog-json.sql
|
||||
│ │
|
||||
│ └── test/
|
||||
│
|
||||
└── frontend/
|
||||
├── node_modules/
|
||||
├── public/
|
||||
│ ├── seo-files/
|
||||
│ └── favicon.svg
|
||||
│
|
||||
└── src/
|
||||
├── assets/
|
||||
├── components/
|
||||
│ ├── CookieConsentPopup.jsx
|
||||
│ ├── CookieSettingsButton.jsx
|
||||
│ ├── CouponInput.jsx
|
||||
│ ├── EmailDialog.jsx
|
||||
│ ├── Footer.jsx
|
||||
│ ├── ImageUploader.jsx
|
||||
│ ├── Notifications.jsx
|
||||
│ ├── OrderStatusDialog.jsx
|
||||
│ ├── ProductImage.jsx
|
||||
│ ├── ProductRatingDisplay.jsx
|
||||
│ ├── ProductReviews.jsx
|
||||
│ ├── ProtectedRoute.jsx
|
||||
│ ├── SEOMetaTags.jsx
|
||||
│ ├── StripePaymentForm.jsx
|
||||
│ └── SubscriptionForm.jsx
|
||||
│
|
||||
├── context/
|
||||
│ └── StripeContext.jsx
|
||||
│
|
||||
├── features/
|
||||
│ ├── auth/
|
||||
│ │ └── authSlice.js
|
||||
│ ├── cart/
|
||||
│ │ └── cartSlice.js
|
||||
│ └── ui/
|
||||
│ └── uiSlice.js
|
||||
│
|
||||
├── hooks/
|
||||
│ ├── adminHooks.js
|
||||
│ ├── apiHooks.js
|
||||
│ ├── blogHooks.js
|
||||
│ ├── brandingHooks.js
|
||||
│ ├── categoryAdminHooks.js
|
||||
│ ├── couponAdminHooks.js
|
||||
│ ├── emailCampaignHooks.js
|
||||
│ ├── emailTemplateHooks.js
|
||||
│ ├── productAdminHooks.js
|
||||
│ ├── productReviewHooks.js
|
||||
│ ├── reduxHooks.js
|
||||
│ ├── settingsAdminHooks.js
|
||||
│ ├── useProductSeo.js
|
||||
│ ├── useSeoMeta.js
|
||||
│ └── useSeoUrl.js
|
||||
│
|
||||
├── layouts/
|
||||
│ ├── AdminLayout.jsx
|
||||
│ ├── AuthLayout.jsx
|
||||
│ └── MainLayout.jsx
|
||||
│
|
||||
├── pages/
|
||||
│ ├── Admin/
|
||||
│ │ ├── BlogCommentsPage.jsx
|
||||
│ │ ├── BlogEditPage.jsx
|
||||
│ │ ├── BlogPage.jsx
|
||||
│ │ ├── BlogPreviewPage.jsx
|
||||
│ │ ├── BrandingPage.jsx
|
||||
│ │ ├── CampaignAnalyticsPage.jsx
|
||||
│ │ ├── CampaignSendPage.jsx
|
||||
│ │ ├── CategoriesPage.jsx
|
||||
│ │ ├── CouponsPage.jsx
|
||||
│ │ ├── CustomersPage.jsx
|
||||
│ │ ├── DashboardPage.jsx
|
||||
│ │ ├── EmailCampaignEditorPage.jsx
|
||||
│ │ ├── EmailCampaignsPage.jsx
|
||||
│ │ ├── EmailTemplatesPage.jsx
|
||||
│ │ ├── MailingListsPage.jsx
|
||||
│ │ ├── OrdersPage.jsx
|
||||
│ │ ├── ProductEditPage.jsx
|
||||
│ │ ├── ProductReviewsPage.jsx
|
||||
│ │ ├── ProductsPage.jsx
|
||||
│ │ ├── ReportsPage.jsx
|
||||
│ │ ├── SettingsPage.jsx
|
||||
│ │ └── SubscribersPage.jsx
|
||||
│ │
|
||||
│ ├── BlogDetailPage.jsx
|
||||
│ ├── BlogPage.jsx
|
||||
│ ├── CartPage.jsx
|
||||
│ ├── CheckoutPage.jsx
|
||||
│ ├── CouponEditPage.jsx
|
||||
│ ├── CouponRedemptionsPage.jsx
|
||||
│ ├── HomePage.jsx
|
||||
│ ├── LoginPage.jsx
|
||||
│ ├── NotFoundPage.jsx
|
||||
│ ├── PaymentCancelPage.jsx
|
||||
│ ├── PaymentSuccessPage.jsx
|
||||
│ ├── ProductDetailPage.jsx
|
||||
│ ├── ProductsPage.jsx
|
||||
│ ├── RegisterPage.jsx
|
||||
│ ├── SubscriptionConfirmPage.jsx
|
||||
│ ├── SubscriptionPreferencesPage.jsx
|
||||
│ ├── UnsubscribePage.jsx
|
||||
│ ├── UserOrdersPage.jsx
|
||||
│ └── VerifyPage.jsx
|
||||
│
|
||||
├── services/
|
||||
│ ├── adminService.js
|
||||
│ ├── api.js
|
||||
│ ├── authService.js
|
||||
│ ├── blogAdminService.js
|
||||
│ ├── blogService.js
|
||||
│ ├── cartService.js
|
||||
│ ├── categoryAdminService.js
|
||||
│ ├── consentService.js
|
||||
│ ├── couponService.js
|
||||
│ ├── emailTemplateService.js
|
||||
│ ├── imageService.js
|
||||
│ ├── productReviewsService.js
|
||||
│ ├── productService.js
|
||||
│ └── settingsAdminService.js
|
||||
│
|
||||
├── store/
|
||||
│ └── index.js
|
||||
│
|
||||
├── theme/
|
||||
│ ├── index.js
|
||||
│ └── ThemeProvider.jsx
|
||||
│
|
||||
└── utils/
|
||||
├── imageUtils.js
|
||||
└── App.jsx
|
||||
|
|
@ -140,8 +140,16 @@ function App() {
|
|||
<UserOrdersPage />
|
||||
</ProtectedRoute>
|
||||
} />
|
||||
<Route index element={<HomePage />} />
|
||||
<Route path="products" element={<ProductsPage />} />
|
||||
<Route index element={
|
||||
<Suspense fallback={<LoadingComponent />}>
|
||||
<HomePage />
|
||||
</Suspense>
|
||||
} />
|
||||
<Route path="products" element={
|
||||
<Suspense fallback={<LoadingComponent />}>
|
||||
<ProductsPage />
|
||||
</Suspense>
|
||||
} />
|
||||
<Route path="products/:id" element={<ProductDetailPage />} />
|
||||
<Route path="confirm-subscription" element={<SubscriptionConfirmPage />} />
|
||||
<Route path="unsubscribe" element={<UnsubscribePage />} />
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react';
|
||||
import React, { useState, memo } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import imageUtils from '@utils/imageUtils';
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import imageUtils from '@utils/imageUtils';
|
|||
* @param {string} props.placeholderImage - Placeholder image to use when no image is available
|
||||
* @returns {JSX.Element} - ProductImage component
|
||||
*/
|
||||
const ProductImage = ({
|
||||
const ProductImage = memo(({
|
||||
images,
|
||||
alt = 'Product image',
|
||||
sx = {},
|
||||
|
|
@ -20,7 +20,6 @@ const ProductImage = ({
|
|||
}) => {
|
||||
const [imageError, setImageError] = useState(false);
|
||||
|
||||
// Determine which image to use
|
||||
let imageSrc = placeholderImage;
|
||||
|
||||
// Handle different types of image inputs
|
||||
|
|
@ -52,6 +51,7 @@ const ProductImage = ({
|
|||
src={imageError ? placeholderImage : imageSrc}
|
||||
alt={alt}
|
||||
onError={handleError}
|
||||
loading="lazy"
|
||||
sx={{
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
|
|
@ -62,6 +62,6 @@ const ProductImage = ({
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
})
|
||||
|
||||
export default ProductImage;
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import React, { memo } from 'react';
|
||||
import { Box, Typography, Rating } from '@mui/material';
|
||||
|
||||
/**
|
||||
* Component to display product rating in a compact format
|
||||
*/
|
||||
const ProductRatingDisplay = ({ rating, reviewCount, showEmpty = false }) => {
|
||||
const ProductRatingDisplay = memo(({ rating, reviewCount, showEmpty = false }) => {
|
||||
if (!rating && !reviewCount && !showEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -22,6 +22,6 @@ const ProductRatingDisplay = ({ rating, reviewCount, showEmpty = false }) => {
|
|||
</Typography>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
})
|
||||
|
||||
export default ProductRatingDisplay;
|
||||
|
|
@ -29,7 +29,8 @@ const HomePage = () => {
|
|||
const featuredProductsData = products && products.length > 0 ? {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "ItemList",
|
||||
"itemListElement": products.slice(0, 6).map((product, index) => ({
|
||||
"itemListElement": products.slice(0, 6).map((product, index) => {
|
||||
return {
|
||||
"@type": "ListItem",
|
||||
"position": index + 1,
|
||||
"item": {
|
||||
|
|
@ -45,7 +46,8 @@ const HomePage = () => {
|
|||
"priceCurrency": "CAD"
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
})
|
||||
} : null;
|
||||
|
||||
return (
|
||||
|
|
|
|||
Loading…
Reference in a new issue