mirror of
https://github.com/Funkoala14/CreatorCenter_OOIN.git
synced 2025-06-07 22:58:14 +08:00
[dev]creatorList
This commit is contained in:
parent
443c253014
commit
8dd91b75c8
@ -25,6 +25,7 @@ export default function CreatorList({ path }) {
|
|||||||
hasMore,
|
hasMore,
|
||||||
isLoadingMore,
|
isLoadingMore,
|
||||||
pagination,
|
pagination,
|
||||||
|
error,
|
||||||
} = useSelector((state) => state.creators);
|
} = useSelector((state) => state.creators);
|
||||||
const { sortBy, sortDirection } = useSelector((state) => state.filters);
|
const { sortBy, sortDirection } = useSelector((state) => state.filters);
|
||||||
const observer = useRef();
|
const observer = useRef();
|
||||||
@ -49,7 +50,8 @@ export default function CreatorList({ path }) {
|
|||||||
}, [path, dispatch]);
|
}, [path, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
}, [publicCreators]);
|
console.log(publicCreators, status);
|
||||||
|
}, [publicCreators, status]);
|
||||||
|
|
||||||
// 处理全选/取消全选
|
// 处理全选/取消全选
|
||||||
const handleSelectAll = (e) => {
|
const handleSelectAll = (e) => {
|
||||||
@ -67,11 +69,13 @@ export default function CreatorList({ path }) {
|
|||||||
|
|
||||||
// 处理排序
|
// 处理排序
|
||||||
const handleSort = (field) => {
|
const handleSort = (field) => {
|
||||||
|
return;
|
||||||
dispatch(setSortBy(field));
|
dispatch(setSortBy(field));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 渲染排序图标
|
// 渲染排序图标
|
||||||
const renderSortIcon = (field) => {
|
const renderSortIcon = (field) => {
|
||||||
|
return;
|
||||||
if (sortBy === field) {
|
if (sortBy === field) {
|
||||||
return sortDirection === 'asc' ? <ChevronUp size={14} /> : <ChevronDown size={14} />;
|
return sortDirection === 'asc' ? <ChevronUp size={14} /> : <ChevronDown size={14} />;
|
||||||
}
|
}
|
||||||
@ -93,7 +97,7 @@ export default function CreatorList({ path }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 如果正在加载且没有数据,显示加载中
|
// 如果正在加载且没有数据,显示加载中
|
||||||
if (status === 'loading' && (!publicCreators || publicCreators.length === 0)) {
|
if (status === 'loading' && !isLoadingMore) {
|
||||||
return (
|
return (
|
||||||
<div className='text-center p-5'>
|
<div className='text-center p-5'>
|
||||||
<Spinner animation='border' role='status' variant='primary'>
|
<Spinner animation='border' role='status' variant='primary'>
|
||||||
@ -105,7 +109,7 @@ export default function CreatorList({ path }) {
|
|||||||
|
|
||||||
// 如果加载失败,显示错误信息
|
// 如果加载失败,显示错误信息
|
||||||
if (status === 'failed') {
|
if (status === 'failed') {
|
||||||
return <div className='alert alert-danger'>Failed to load creators. Please try again later.</div>;
|
return <div className='alert alert-danger'>{error || 'Failed to load creators. Please try again later.'}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -117,7 +121,9 @@ export default function CreatorList({ path }) {
|
|||||||
<th className='selector' style={{ width: '40px' }}>
|
<th className='selector' style={{ width: '40px' }}>
|
||||||
<Form.Check
|
<Form.Check
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
checked={selectedCreators.length === publicCreators.length && publicCreators.length > 0}
|
checked={
|
||||||
|
selectedCreators.length === publicCreators.length && publicCreators.length > 0
|
||||||
|
}
|
||||||
onChange={handleSelectAll}
|
onChange={handleSelectAll}
|
||||||
/>
|
/>
|
||||||
</th>
|
</th>
|
||||||
|
@ -10,8 +10,9 @@ import {
|
|||||||
toggleGmvRange,
|
toggleGmvRange,
|
||||||
setViewsRange,
|
setViewsRange,
|
||||||
setPricingRange,
|
setPricingRange,
|
||||||
|
setPlatform,
|
||||||
} from '../store/slices/filtersSlice';
|
} from '../store/slices/filtersSlice';
|
||||||
import { fetchCreators } from '../store/slices/creatorsSlice';
|
import { fetchCreators, resetCreators } from '../store/slices/creatorsSlice';
|
||||||
import '../styles/DatabaseFilter.scss';
|
import '../styles/DatabaseFilter.scss';
|
||||||
|
|
||||||
export default function DatabaseFilter({ path, pageType = 'database' }) {
|
export default function DatabaseFilter({ path, pageType = 'database' }) {
|
||||||
@ -63,23 +64,23 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 本地状态用于表单控制
|
// 本地状态用于表单控制
|
||||||
const [minViews, setMinViews] = useState(filters.viewsRange[0]);
|
const [minViews, setMinViews] = useState(filters.views_range[0]);
|
||||||
const [maxViews, setMaxViews] = useState(filters.viewsRange[1]);
|
const [maxViews, setMaxViews] = useState(filters.views_range[1]);
|
||||||
const [minPricing, setMinPricing] = useState(filters.pricingRange[0]);
|
const [minPricing, setMinPricing] = useState(filters.pricing[0]);
|
||||||
const [maxPricing, setMaxPricing] = useState(filters.pricingRange[1]);
|
const [maxPricing, setMaxPricing] = useState(filters.pricing[1]);
|
||||||
|
|
||||||
// 监听Redux状态变化,更新本地表单状态
|
// 监听Redux状态变化,更新本地表单状态
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMinViews(filters.viewsRange[0]);
|
setMinViews(filters.views_range[0]);
|
||||||
setMaxViews(filters.viewsRange[1]);
|
setMaxViews(filters.views_range[1]);
|
||||||
setMinPricing(filters.pricingRange[0]);
|
setMinPricing(filters.pricing[0]);
|
||||||
setMaxPricing(filters.pricingRange[1]);
|
setMaxPricing(filters.pricing[1]);
|
||||||
}, [filters.viewsRange, filters.pricingRange]);
|
}, [filters.views_range, filters.pricing]);
|
||||||
|
|
||||||
// 组件加载时获取数据
|
// 组件加载时获取数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
dispatch(setPlatform(path));
|
||||||
}, [dispatch, filters, pageType, path]);
|
}, [dispatch, path]);
|
||||||
|
|
||||||
// 处理类别选择
|
// 处理类别选择
|
||||||
const handleCategorySelect = (category) => {
|
const handleCategorySelect = (category) => {
|
||||||
@ -104,6 +105,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
// 处理视图范围更新
|
// 处理视图范围更新
|
||||||
const handleViewsRangeChange = (newRange) => {
|
const handleViewsRangeChange = (newRange) => {
|
||||||
dispatch(setViewsRange(newRange));
|
dispatch(setViewsRange(newRange));
|
||||||
|
resetAndFetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理min input变更
|
// 处理min input变更
|
||||||
@ -120,6 +122,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
|
|
||||||
const handlePricingRangeChange = (newRange) => {
|
const handlePricingRangeChange = (newRange) => {
|
||||||
dispatch(setPricingRange(newRange));
|
dispatch(setPricingRange(newRange));
|
||||||
|
resetAndFetch();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理min pricing input变更
|
// 处理min pricing input变更
|
||||||
@ -145,7 +148,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
const finalValue = Math.min(discreteValue, maxViews);
|
const finalValue = Math.min(discreteValue, maxViews);
|
||||||
|
|
||||||
setMinViews(finalValue);
|
setMinViews(finalValue);
|
||||||
dispatch(setViewsRange([finalValue, filters.viewsRange[1]]));
|
dispatch(setViewsRange([finalValue, filters.views_range[1]]));
|
||||||
} else {
|
} else {
|
||||||
// 找到最接近的离散值
|
// 找到最接近的离散值
|
||||||
const closestIndex = findClosestDiscreteIndex(maxViews);
|
const closestIndex = findClosestDiscreteIndex(maxViews);
|
||||||
@ -155,7 +158,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
const finalValue = Math.max(discreteValue, minViews);
|
const finalValue = Math.max(discreteValue, minViews);
|
||||||
|
|
||||||
setMaxViews(finalValue);
|
setMaxViews(finalValue);
|
||||||
dispatch(setViewsRange([filters.viewsRange[0], finalValue]));
|
dispatch(setViewsRange([filters.views_range[0], finalValue]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -169,7 +172,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
const finalValue = Math.min(discreteValue, maxPricing);
|
const finalValue = Math.min(discreteValue, maxPricing);
|
||||||
|
|
||||||
setMinPricing(finalValue);
|
setMinPricing(finalValue);
|
||||||
dispatch(setPricingRange([finalValue, filters.pricingRange[1]]));
|
dispatch(setPricingRange([finalValue, filters.pricing[1]]));
|
||||||
} else {
|
} else {
|
||||||
const closestIndex = findClosestDiscreteIndex(maxPricing);
|
const closestIndex = findClosestDiscreteIndex(maxPricing);
|
||||||
const discreteValue = discretePricingValues[closestIndex];
|
const discreteValue = discretePricingValues[closestIndex];
|
||||||
@ -178,7 +181,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
const finalValue = Math.max(discreteValue, minPricing);
|
const finalValue = Math.max(discreteValue, minPricing);
|
||||||
|
|
||||||
setMaxPricing(finalValue);
|
setMaxPricing(finalValue);
|
||||||
dispatch(setPricingRange([filters.pricingRange[0], finalValue]));
|
dispatch(setPricingRange([filters.pricing[0], finalValue]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,6 +196,43 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resetAndFetch = () => {
|
||||||
|
dispatch(resetCreators());
|
||||||
|
if (pageType === 'private') {
|
||||||
|
dispatch(fetchPrivateCreators({ page: 1 }));
|
||||||
|
} else {
|
||||||
|
dispatch(fetchCreators({ page: 1 }));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChange = (e) => {
|
||||||
|
const name = e.target.name;
|
||||||
|
const value = e.target.value;
|
||||||
|
switch (name) {
|
||||||
|
case 'category':
|
||||||
|
handleCategorySelect(value);
|
||||||
|
break;
|
||||||
|
case 'e_commerce_level':
|
||||||
|
handleEcommerceRatingSelect(value);
|
||||||
|
break;
|
||||||
|
case 'exposure_level':
|
||||||
|
handleExposureRatingSelect(value);
|
||||||
|
break;
|
||||||
|
case 'gmv_range':
|
||||||
|
handleGmvRangeSelect(value);
|
||||||
|
break;
|
||||||
|
case 'views_range':
|
||||||
|
handleViewsRangeChange(value);
|
||||||
|
break;
|
||||||
|
case 'pricing':
|
||||||
|
handlePricingRangeChange(value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
resetAndFetch();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='shadow-xs mb-4 filter-card'>
|
<div className='shadow-xs mb-4 filter-card'>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
@ -207,7 +247,9 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
key={category}
|
key={category}
|
||||||
variant={filters.category.includes(category) ? 'primary' : 'light'}
|
variant={filters.category.includes(category) ? 'primary' : 'light'}
|
||||||
className='rounded-pill'
|
className='rounded-pill'
|
||||||
onClick={() => handleCategorySelect(category)}
|
onClick={onChange}
|
||||||
|
name='category'
|
||||||
|
value={category}
|
||||||
>
|
>
|
||||||
{category}
|
{category}
|
||||||
</Button>
|
</Button>
|
||||||
@ -222,9 +264,11 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
{ecommerceRatings.map((rating) => (
|
{ecommerceRatings.map((rating) => (
|
||||||
<Button
|
<Button
|
||||||
key={rating}
|
key={rating}
|
||||||
variant={filters.ecommerceRatings.includes(rating) ? 'primary' : 'light'}
|
variant={filters.e_commerce_level.includes(rating) ? 'primary' : 'light'}
|
||||||
className='rounded-pill'
|
className='rounded-pill'
|
||||||
onClick={() => handleEcommerceRatingSelect(rating)}
|
onClick={onChange}
|
||||||
|
name='e_commerce_level'
|
||||||
|
value={rating}
|
||||||
>
|
>
|
||||||
{rating}
|
{rating}
|
||||||
</Button>
|
</Button>
|
||||||
@ -239,9 +283,11 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
{exposureRatings.map((rating) => (
|
{exposureRatings.map((rating) => (
|
||||||
<Button
|
<Button
|
||||||
key={rating}
|
key={rating}
|
||||||
variant={filters.exposureRatings.includes(rating) ? 'primary' : 'light'}
|
variant={filters.exposure_level.includes(rating) ? 'primary' : 'light'}
|
||||||
className='rounded-pill'
|
className='rounded-pill'
|
||||||
onClick={() => handleExposureRatingSelect(rating)}
|
onClick={onChange}
|
||||||
|
name='exposure_level'
|
||||||
|
value={rating}
|
||||||
>
|
>
|
||||||
{rating}
|
{rating}
|
||||||
</Button>
|
</Button>
|
||||||
@ -256,9 +302,11 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
{gmvRanges.map((range) => (
|
{gmvRanges.map((range) => (
|
||||||
<Button
|
<Button
|
||||||
key={range.label}
|
key={range.label}
|
||||||
variant={filters.gmvRanges.includes(range.label) ? 'primary' : 'light'}
|
variant={filters.gmv_range.includes(range.label) ? 'primary' : 'light'}
|
||||||
className='rounded-pill'
|
className='rounded-pill'
|
||||||
onClick={() => handleGmvRangeSelect(range.label)}
|
onClick={onChange}
|
||||||
|
name='gmv_range'
|
||||||
|
value={range.label}
|
||||||
>
|
>
|
||||||
{range.label}
|
{range.label}
|
||||||
</Button>
|
</Button>
|
||||||
@ -273,7 +321,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
<RangeSlider
|
<RangeSlider
|
||||||
min={0}
|
min={0}
|
||||||
max={500000}
|
max={500000}
|
||||||
value={filters.viewsRange}
|
value={filters.views_range}
|
||||||
onChange={handleViewsRangeChange}
|
onChange={handleViewsRangeChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -313,7 +361,7 @@ export default function DatabaseFilter({ path, pageType = 'database' }) {
|
|||||||
<RangeSlider
|
<RangeSlider
|
||||||
min={0}
|
min={0}
|
||||||
max={500000}
|
max={500000}
|
||||||
value={filters.pricingRange}
|
value={filters.pricing}
|
||||||
onChange={handlePricingRangeChange}
|
onChange={handlePricingRangeChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
21
src/components/NotificationBar.jsx
Normal file
21
src/components/NotificationBar.jsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { Check, CircleAlert, Info, X } from 'lucide-react';
|
||||||
|
import { useDispatch } from 'react-redux';
|
||||||
|
|
||||||
|
export default function NotificationBar() {
|
||||||
|
const { message, type, show } = useSelector((state) => state.notificationBar);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`snackbar alert alert-${type} d-flex align-items-center justify-content-between position-fixed top-10 start-50 translate-middle w-50 gap-2`}
|
||||||
|
role='alert'
|
||||||
|
>
|
||||||
|
{type === 'success' && <Check />}
|
||||||
|
{type === 'warning' && <CircleAlert />}
|
||||||
|
{type === 'error' && <X />}
|
||||||
|
{type === 'info' && <Info />}
|
||||||
|
<div className='flex-fill'>{message}</div>
|
||||||
|
<button type='button' className='btn-close flex-end' onClick={handleClose} aria-label='Close'></button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -15,7 +15,7 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
export default function PrivateCreatorList({ path }) {
|
export default function PrivateCreatorList({ path }) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { privateCreators, status, selectedCreators, hasMore, isLoadingMore, pagination } = useSelector(
|
const { privateCreators, status, selectedCreators, hasMore, isLoadingMore, pagination, error } = useSelector(
|
||||||
(state) => state.creators
|
(state) => state.creators
|
||||||
);
|
);
|
||||||
const { sortBy, sortDirection } = useSelector((state) => state.filters);
|
const { sortBy, sortDirection } = useSelector((state) => state.filters);
|
||||||
@ -60,11 +60,13 @@ export default function PrivateCreatorList({ path }) {
|
|||||||
|
|
||||||
// 处理排序
|
// 处理排序
|
||||||
const handleSort = (field) => {
|
const handleSort = (field) => {
|
||||||
|
return;
|
||||||
dispatch(setSortBy(field));
|
dispatch(setSortBy(field));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 渲染排序图标
|
// 渲染排序图标
|
||||||
const renderSortIcon = (field) => {
|
const renderSortIcon = (field) => {
|
||||||
|
return;
|
||||||
if (sortBy === field) {
|
if (sortBy === field) {
|
||||||
return sortDirection === 'asc' ? <ChevronUp size={14} /> : <ChevronDown size={14} />;
|
return sortDirection === 'asc' ? <ChevronUp size={14} /> : <ChevronDown size={14} />;
|
||||||
}
|
}
|
||||||
@ -86,7 +88,7 @@ export default function PrivateCreatorList({ path }) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 如果正在加载且没有数据,显示加载中
|
// 如果正在加载且没有数据,显示加载中
|
||||||
if (status === 'loading' && (!privateCreators || privateCreators.length === 0)) {
|
if (status === 'loading' && !isLoadingMore) {
|
||||||
return (
|
return (
|
||||||
<div className='text-center p-5'>
|
<div className='text-center p-5'>
|
||||||
<Spinner animation='border' role='status' variant='primary'>
|
<Spinner animation='border' role='status' variant='primary'>
|
||||||
@ -98,7 +100,7 @@ export default function PrivateCreatorList({ path }) {
|
|||||||
|
|
||||||
// 如果加载失败,显示错误信息
|
// 如果加载失败,显示错误信息
|
||||||
if (status === 'failed') {
|
if (status === 'failed') {
|
||||||
return <div className='alert alert-danger'>Failed to load creators. Please try again later.</div>;
|
return <div className='alert alert-danger'>{error || 'Failed to load creators. Please try again later.'}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -216,24 +216,47 @@ const initialState = {
|
|||||||
isLoadingMore: false,
|
isLoadingMore: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchCreators = createAsyncThunk('creators/fetchCreators', async ({ path, page = 1 }, { getState }) => {
|
export const fetchCreators = createAsyncThunk(
|
||||||
const state = getState();
|
'creators/fetchCreators',
|
||||||
const filters = state.filters;
|
async ({ page = 1 }, { getState, rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const state = getState();
|
||||||
|
const filters = state.filters;
|
||||||
|
|
||||||
const response = await api.get(`/daren_detail/public/creators`, { params: { page } });
|
const { code, data, message, pagination } = await api.post(
|
||||||
console.log(response);
|
`/daren_detail/public/creators/filter/?page=${page}`,
|
||||||
return response;
|
filters
|
||||||
});
|
);
|
||||||
|
if (code === 200) {
|
||||||
|
return { data, pagination };
|
||||||
|
} else {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return rejectWithValue(error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export const fetchPrivateCreators = createAsyncThunk(
|
export const fetchPrivateCreators = createAsyncThunk(
|
||||||
'creators/fetchPrivateCreators',
|
'creators/fetchPrivateCreators',
|
||||||
async ({ path, page = 1 }, { getState }) => {
|
async ({ page = 1 }, { getState, rejectWithValue, dispatch }) => {
|
||||||
const state = getState();
|
try {
|
||||||
const filters = state.filters;
|
const state = getState();
|
||||||
|
const filters = state.filters;
|
||||||
|
|
||||||
const queryParams = { pool_id: 1, page };
|
const { code, data, message, pagination } = await api.post(
|
||||||
const response = await api.get(`/daren_detail/private/pools/creators`, { params: queryParams });
|
`/daren_detail/private/pools/creators/filter/?page=${page}`,
|
||||||
return response;
|
{ pool_id: 1, filters }
|
||||||
|
);
|
||||||
|
if (code === 200) {
|
||||||
|
return { data, pagination };
|
||||||
|
} else {
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return rejectWithValue(error.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -283,8 +306,8 @@ const creatorsSlice = createSlice({
|
|||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
builder
|
builder
|
||||||
.addCase(fetchCreators.pending, (state) => {
|
.addCase(fetchCreators.pending, (state) => {
|
||||||
|
state.status = 'loading';
|
||||||
if (state.publicCreators.length === 0) {
|
if (state.publicCreators.length === 0) {
|
||||||
state.status = 'loading';
|
|
||||||
} else {
|
} else {
|
||||||
state.isLoadingMore = true;
|
state.isLoadingMore = true;
|
||||||
}
|
}
|
||||||
@ -304,7 +327,7 @@ const creatorsSlice = createSlice({
|
|||||||
.addCase(fetchCreators.rejected, (state, action) => {
|
.addCase(fetchCreators.rejected, (state, action) => {
|
||||||
state.status = 'failed';
|
state.status = 'failed';
|
||||||
state.isLoadingMore = false;
|
state.isLoadingMore = false;
|
||||||
state.error = action.error.message;
|
state.error = action.payload;
|
||||||
})
|
})
|
||||||
.addCase(fetchPrivateCreators.pending, (state) => {
|
.addCase(fetchPrivateCreators.pending, (state) => {
|
||||||
if (state.privateCreators?.length === 0) {
|
if (state.privateCreators?.length === 0) {
|
||||||
@ -330,7 +353,7 @@ const creatorsSlice = createSlice({
|
|||||||
console.log('fetchPrivateCreators.rejected', action);
|
console.log('fetchPrivateCreators.rejected', action);
|
||||||
state.status = 'failed';
|
state.status = 'failed';
|
||||||
state.isLoadingMore = false;
|
state.isLoadingMore = false;
|
||||||
state.error = action.error.message;
|
state.error = action.payload;
|
||||||
})
|
})
|
||||||
.addCase(fetchCreatorDetail.pending, (state) => {
|
.addCase(fetchCreatorDetail.pending, (state) => {
|
||||||
state.status = 'loading';
|
state.status = 'loading';
|
||||||
|
@ -2,13 +2,14 @@ import { createSlice } from '@reduxjs/toolkit';
|
|||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
category: ['Homes Supplies'],
|
category: ['Homes Supplies'],
|
||||||
ecommerceRatings: ['L2', 'L3'],
|
e_commerce_level: ['L2', 'L3'],
|
||||||
exposureRatings: [],
|
exposure_level: [],
|
||||||
gmvRanges: ['$5k - $25k', '$25k - $60k'],
|
gmv_range: ['$5k - $25k', '$25k - $60k'],
|
||||||
viewsRange: [0, 100000],
|
views_range: [0, 100000],
|
||||||
pricingRange: [0, 3000],
|
pricing: [0, 3000],
|
||||||
sortBy: 'followers',
|
sortBy: 'followers',
|
||||||
sortDirection: 'desc',
|
sortDirection: 'desc',
|
||||||
|
platform: '',
|
||||||
};
|
};
|
||||||
const filtersSlice = createSlice({
|
const filtersSlice = createSlice({
|
||||||
name: 'filters',
|
name: 'filters',
|
||||||
@ -24,33 +25,33 @@ const filtersSlice = createSlice({
|
|||||||
},
|
},
|
||||||
toggleEcommerceRating: (state, action) => {
|
toggleEcommerceRating: (state, action) => {
|
||||||
const rating = action.payload;
|
const rating = action.payload;
|
||||||
if (state.ecommerceRatings.includes(rating)) {
|
if (state.e_commerce_level.includes(rating)) {
|
||||||
state.ecommerceRatings = state.ecommerceRatings.filter((r) => r !== rating);
|
state.e_commerce_level = state.e_commerce_level.filter((r) => r !== rating);
|
||||||
} else {
|
} else {
|
||||||
state.ecommerceRatings.push(rating);
|
state.e_commerce_level.push(rating);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleExposureRating: (state, action) => {
|
toggleExposureRating: (state, action) => {
|
||||||
const rating = action.payload;
|
const rating = action.payload;
|
||||||
if (state.exposureRatings.includes(rating)) {
|
if (state.exposure_level.includes(rating)) {
|
||||||
state.exposureRatings = state.exposureRatings.filter((r) => r !== rating);
|
state.exposure_level = state.exposure_level.filter((r) => r !== rating);
|
||||||
} else {
|
} else {
|
||||||
state.exposureRatings.push(rating);
|
state.exposure_level.push(rating);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggleGmvRange: (state, action) => {
|
toggleGmvRange: (state, action) => {
|
||||||
const range = action.payload;
|
const range = action.payload;
|
||||||
if (state.gmvRanges.includes(range)) {
|
if (state.gmv_range.includes(range)) {
|
||||||
state.gmvRanges = state.gmvRanges.filter((r) => r !== range);
|
state.gmv_range = state.gmv_range.filter((r) => r !== range);
|
||||||
} else {
|
} else {
|
||||||
state.gmvRanges.push(range);
|
state.gmv_range.push(range);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setViewsRange: (state, action) => {
|
setViewsRange: (state, action) => {
|
||||||
state.viewsRange = action.payload;
|
state.views_range = action.payload;
|
||||||
},
|
},
|
||||||
setPricingRange: (state, action) => {
|
setPricingRange: (state, action) => {
|
||||||
state.pricingRange = action.payload;
|
state.pricing = action.payload;
|
||||||
},
|
},
|
||||||
setSortBy: (state, action) => {
|
setSortBy: (state, action) => {
|
||||||
// 如果选择了当前已激活的排序项,则切换排序方向
|
// 如果选择了当前已激活的排序项,则切换排序方向
|
||||||
@ -62,6 +63,9 @@ const filtersSlice = createSlice({
|
|||||||
state.sortDirection = 'desc';
|
state.sortDirection = 'desc';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setPlatform: (state, action) => {
|
||||||
|
state.platform = action.payload;
|
||||||
|
},
|
||||||
resetFilters: () => {
|
resetFilters: () => {
|
||||||
return initialState;
|
return initialState;
|
||||||
},
|
},
|
||||||
@ -76,6 +80,7 @@ export const {
|
|||||||
setViewsRange,
|
setViewsRange,
|
||||||
setPricingRange,
|
setPricingRange,
|
||||||
setSortBy,
|
setSortBy,
|
||||||
|
setPlatform,
|
||||||
resetFilters,
|
resetFilters,
|
||||||
} = filtersSlice.actions;
|
} = filtersSlice.actions;
|
||||||
|
|
||||||
|
27
src/store/slices/notificationBarSlice.js
Normal file
27
src/store/slices/notificationBarSlice.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const initialState = {
|
||||||
|
message: '',
|
||||||
|
show: false,
|
||||||
|
type: 'success', // success, warning, error, info
|
||||||
|
};
|
||||||
|
|
||||||
|
const notificationBarSlice = createSlice({
|
||||||
|
name: 'notificationBar',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setNotificationBarMessage: (state, action) => {
|
||||||
|
state.message = action.payload;
|
||||||
|
},
|
||||||
|
setNotificationBarShow: (state, action) => {
|
||||||
|
state.show = action.payload;
|
||||||
|
},
|
||||||
|
resetNotificationBar: (state) => {
|
||||||
|
state.message = '';
|
||||||
|
state.show = false;
|
||||||
|
state.type = 'success';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { setNotificationBarMessage, setNotificationBarShow, resetNotificationBar } = notificationBarSlice.actions;
|
||||||
|
|
||||||
|
export default notificationBarSlice.reducer;
|
Loading…
Reference in New Issue
Block a user