diff --git a/src/components/BrandsList.jsx b/src/components/BrandsList.jsx index 47967c0..fbcb44f 100644 --- a/src/components/BrandsList.jsx +++ b/src/components/BrandsList.jsx @@ -33,14 +33,14 @@ export default function BrandsList({ openBrandDetail }) { Collab. - {brand.collab} + {brand.collab_count} Creators - {brand.creators} + {brand.creators_count} diff --git a/src/components/CampaignList.jsx b/src/components/CampaignList.jsx index 35c1ad3..bb98a2b 100644 --- a/src/components/CampaignList.jsx +++ b/src/components/CampaignList.jsx @@ -3,14 +3,23 @@ import { useEffect } from 'react'; import { useSelector } from 'react-redux'; import { Link } from 'react-router-dom'; import { ChartNoAxesColumnIncreasing, CircleDollarSign, Edit, Eye, Folders, Hash, Layers, Tag, TrendingUp, UserRoundCheck } from 'lucide-react'; - +import Spinning from './Spinning'; export default function CampaignList() { - const { selectedBrand } = useSelector((state) => state.brands); + const { selectedBrand ,status } = useSelector((state) => state.brands); useEffect(() => { console.log(selectedBrand); }, [selectedBrand]); + + if (status === 'loading') { + return ; + } + + if (selectedBrand?.campaigns?.length === 0) { + return
No campaigns found
; + } + return (
{selectedBrand?.campaigns?.length > 0 && diff --git a/src/components/ProductsList.jsx b/src/components/ProductsList.jsx index 36c5e52..43c6bbe 100644 --- a/src/components/ProductsList.jsx +++ b/src/components/ProductsList.jsx @@ -4,23 +4,16 @@ import { useSelector, useDispatch } from 'react-redux'; import { useParams } from 'react-router-dom'; import '../styles/Products.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import Spinning from './Spinning'; export default function ProductsList({ onShowProductDetail }) { const { brandId } = useParams(); - const { brands } = useSelector((state) => state.brands); + const { selectedBrand } = useSelector((state) => state.brands); const [products, setProducts] = useState([]); const [selectedProducts, setSelectedProducts] = useState([]); const [sortField, setSortField] = useState(null); const [sortDirection, setSortDirection] = useState('asc'); - useEffect(() => { - if (brands.length > 0) { - const brand = brands.find((b) => b.id.toString() === brandId); - if (brand && brand.products) { - setProducts(brand.products); - } - } - }, [brands, brandId]); const handleSort = (field) => { if (sortField === field) { @@ -52,6 +45,11 @@ export default function ProductsList({ onShowProductDetail }) { } }; + if (status === 'loading') { + return ; + } + + return (
@@ -60,7 +58,7 @@ export default function ProductsList({ onShowProductDetail }) { @@ -94,14 +92,14 @@ export default function ProductsList({ onShowProductDetail }) { - {products.length === 0 ? ( + {selectedBrand?.products?.length === 0 ? ( ) : ( - products.map((product) => ( + selectedBrand?.products?.map((product) => ( - - + + - + - - + + )) )} diff --git a/src/pages/BrandsDetail.jsx b/src/pages/BrandsDetail.jsx index e8dee57..4333a98 100644 --- a/src/pages/BrandsDetail.jsx +++ b/src/pages/BrandsDetail.jsx @@ -6,7 +6,7 @@ import { useDispatch, useSelector } from 'react-redux'; import { Link, useParams } from 'react-router-dom'; import CampaignList from '../components/CampaignList'; import ProductsList from '../components/ProductsList'; -import { findBrandById } from '../store/slices/brandsSlice'; +import { findBrandById, fetchBrandCampaigns, fetchBrandProducts } from '../store/slices/brandsSlice'; export default function BrandsDetail() { const { id } = useParams(); @@ -16,9 +16,9 @@ export default function BrandsDetail() { useEffect(() => { if (id) { - console.log(id); - dispatch(findBrandById(id)); + dispatch(fetchBrandCampaigns(id)); + dispatch(fetchBrandProducts(id)); } }, [dispatch, id]); @@ -69,31 +69,31 @@ export default function BrandsDetail() { Collab. -
{selectedBrand.collab}
+
{selectedBrand.collab_count}
Creators
-
{selectedBrand.creators}
+
{selectedBrand.creators_count}
-
{selectedBrand.collab}
+
{selectedBrand.creators_count}
Total Collab. Creators
-
{selectedBrand.collab}
+
{selectedBrand.total_gmv_achieved}
Total GMV Achieved
-
{selectedBrand.collab}
+
{selectedBrand.total_views_achieved}
Total Views Achieved
-
{selectedBrand.collab}
+
{selectedBrand.shop_overall_rating}
Shop Overall Rating
diff --git a/src/store/slices/brandsSlice.js b/src/store/slices/brandsSlice.js index 19f2889..cf8e52a 100644 --- a/src/store/slices/brandsSlice.js +++ b/src/store/slices/brandsSlice.js @@ -1,5 +1,5 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; - +import api from '@/services/api'; const mockProducts = [ { id: 1, @@ -108,10 +108,19 @@ const mockBrands = [ export const fetchBrands = createAsyncThunk('brands/fetchBrands', async () => { // const response = await fetch('https://api.example.com/brands'); - await new Promise((resolve) => setTimeout(resolve, 500)); - console.log('fetchBrands'); + const response = await api.get('/brands/'); + return response.data; +}); - return mockBrands; +export const fetchBrandCampaigns = createAsyncThunk('brands/fetchBrandCampaigns', async (brandId) => { + const response = await api.get(`/brands/${brandId}/campaigns/`); + return response.data; +}); + +export const fetchBrandProducts = createAsyncThunk('brands/fetchBrandProducts', async (brandId) => { + const response = await api.get(`/brands/${brandId}/products/`); + console.log(response); + return response.data; }); const initialState = { @@ -161,6 +170,28 @@ const brandsSlice = createSlice({ .addCase(fetchBrands.rejected, (state, action) => { state.status = 'failed'; state.error = action.error.message; + }) + .addCase(fetchBrandCampaigns.pending, (state) => { + state.status = 'loading'; + }) + .addCase(fetchBrandCampaigns.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.selectedBrand.campaigns = action.payload; + }) + .addCase(fetchBrandCampaigns.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message; + }) + .addCase(fetchBrandProducts.pending, (state) => { + state.status = 'loading'; + }) + .addCase(fetchBrandProducts.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.selectedBrand.products = action.payload; + }) + .addCase(fetchBrandProducts.rejected, (state, action) => { + state.status = 'failed'; + state.error = action.error.message; }); }, }); diff --git a/src/styles/Brands.scss b/src/styles/Brands.scss index 66cc522..b4fd9d7 100644 --- a/src/styles/Brands.scss +++ b/src/styles/Brands.scss @@ -8,7 +8,8 @@ gap: 1rem; .brand-card { - width: 325px; + flex: 1; + min-width: 325px; padding: 1.5rem; border-radius: 0.4rem; background-color: white;
0} + checked={selectedProducts.length === selectedBrand?.products?.length && selectedBrand?.products?.length > 0} onChange={handleSelectAll} />
No products found for this brand.
-
{product.commission}
-
Open collab. {product.openCollab}
+
{product.commission_rate}
+
Open collab. {product.open_collab}
{product.availableSamples}{product.price}{product.available_samples}{product.sales_price_min} - {product.sales_price_max} {product.stock}{product.sold}{product.items_sold} -
{product.rating}
-
{product.reviews} Reviews
+
{product.product_rating}
+
{product.reviews_count} Reviews
{product.collabCreators}{product.tiktokShop && }{product.collab_creators}{product.tiktok_shop && }