[dev]brands search

This commit is contained in:
susie-laptop 2025-05-28 19:23:13 -04:00
parent 1a51aff75b
commit 3492e16c40
9 changed files with 50 additions and 12 deletions

View File

@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import { Button, Form, Modal } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { fetchCampaigns } from '../store/slices/brandsSlice';
import SpinningComponent from './Spinning';
import SpinningComponent from './SpinningComponent';
import { addCreatorsToCampaign } from '../store/slices/creatorsSlice';
export default function AddToCampaign({ show, onHide }) {

View File

@ -3,15 +3,26 @@ import { useSelector, useDispatch } from 'react-redux';
import { fetchBrands } from '../store/slices/brandsSlice';
import { Card } from 'react-bootstrap';
import { Folders, Hash, Link, Users } from 'lucide-react';
import SpinningComponent from './SpinningComponent';
export default function BrandsList({ openBrandDetail }) {
const brands = useSelector((state) => state.brands.brands);
const { brands, status, error } = useSelector((state) => state.brands);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchBrands());
}, [dispatch]);
if (status === 'loading') {
return <SpinningComponent />;
}
//
if (status === 'failed') {
return <div className='alert alert-danger'>{error || 'Failed to load brands. Please try again later.'}</div>;
}
return (
<div className='brands-list'>
{brands?.length > 0 && brands.map((brand) => (

View File

@ -3,7 +3,7 @@ import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { Link, useParams } from 'react-router-dom';
import { ChartNoAxesColumnIncreasing, CircleDollarSign, Edit, Eye, Folders, Hash, Layers, Tag, TrendingUp, UserRoundCheck } from 'lucide-react';
import Spinning from './Spinning';
import Spinning from './SpinningComponent';
export default function CampaignList() {
const { selectedBrand ,status } = useSelector((state) => state.brands);

View File

@ -3,9 +3,9 @@ import { Table, Form, Button, Modal } from 'react-bootstrap';
import { useSelector, useDispatch } from 'react-redux';
import '../styles/Products.scss';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Spinning from './Spinning';
import Spinning from './SpinningComponent';
import { Plus } from 'lucide-react';
import SpinningComponent from './Spinning';
import SpinningComponent from './SpinningComponent';
import { addProductToCampaign } from '../store/slices/productSlice';
export default function ProductsList({ products, onShowProductDetail, type = 'default' }) {

View File

@ -1,7 +1,7 @@
import { Copy, Edit, FileText, LayoutTemplate } from 'lucide-react';
import { Button } from 'react-bootstrap';
import { useSelector } from 'react-redux';
import Spinning from './Spinning';
import Spinning from './SpinningComponent';
export default function TemplateList({ activeTab, openModal, setFormData }) {
const { templates, templatesStatus } = useSelector((state) => state.inbox);

View File

@ -6,27 +6,32 @@ import '../styles/Brands.scss';
import { useNavigate } from 'react-router-dom';
import { Plus } from 'lucide-react';
import { useDispatch, useSelector } from 'react-redux';
import { createBrandThunk, fetchBrands, selectBrand } from '../store/slices/brandsSlice';
import SpinningComponent from '../components/Spinning';
import { createBrandThunk, fetchBrands, searchBrands, selectBrand } from '../store/slices/brandsSlice';
import SpinningComponent from '../components/SpinningComponent';
import { BRAND_SOURCES } from '../lib/constant';
export default function Brands() {
const navigate = useNavigate();
const dispatch = useDispatch();
const [showAddBrandModal, setShowAddBrandModal] = useState(false);
const [searchValue, setSearchValue] = useState('');
useEffect(() => {}, [dispatch]);
const openBrandDetail = async (item) => {
console.log(item);
await dispatch(selectBrand(item));
navigate(`/brands/${item.id}`);
};
const handleSearch = (e) => {
e.preventDefault();
dispatch(searchBrands({ keyword: searchValue }));
};
return (
<React.Fragment>
<div className='function-bar'>
<SearchBar />
<SearchBar onSearch={handleSearch} value={searchValue} onChange={(e) => setSearchValue(e.target.value)} />
<Button onClick={() => setShowAddBrandModal(true)}>
<Plus />
Add Brand
@ -76,7 +81,7 @@ function AddBrandModal({ show, onHide }) {
setCampaignId('');
};
if (status === 'loading') {
if (show && status === 'loading') {
return <SpinningComponent />;
}

View File

@ -17,7 +17,6 @@ import SlidePanel from '../components/SlidePanel';
import ProductDetail, { CampaignsCollabCreators } from '../components/ProductDetail';
import { CAMPAIGN_SERVICES, CREATOR_CATEGORIES, CREATOR_LEVELS, CREATOR_TYPES, GMV_RANGES } from '../lib/constant';
import RangeSlider from '../components/RangeSlider';
import SpinningComponent from '../components/Spinning';
import { setNotificationBarMessage } from '../store/slices/notificationBarSlice';
export default function BrandsDetail() {

View File

@ -120,6 +120,18 @@ export const fetchBrands = createAsyncThunk('brands/fetchBrands', async (_, { re
}
});
export const searchBrands = createAsyncThunk('brands/searchBrands', async (params, { rejectWithValue }) => {
try {
const response = await api.get('/brands/search/', { params });
if (response.code !== 200) {
throw new Error(response.message);
}
return response.data;
} catch (error) {
return rejectWithValue(error.message);
}
});
export const fetchBrandDetail = createAsyncThunk('brands/fetchBrandDetail', async (brandId, { rejectWithValue }) => {
try {
const response = await api.get(`/brands/${brandId}/`);
@ -324,6 +336,17 @@ const brandsSlice = createSlice({
.addCase(createCampaignThunk.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
})
.addCase(searchBrands.pending, (state) => {
state.status = 'loading';
})
.addCase(searchBrands.fulfilled, (state, action) => {
state.status = 'succeeded';
state.brands = action.payload;
})
.addCase(searchBrands.rejected, (state, action) => {
state.status = 'failed';
state.error = action.error.message;
});
},
});