mirror of
https://github.com/Funkoala14/CreatorCenter_OOIN.git
synced 2025-06-07 22:58:14 +08:00
[dev]discovery session detail
This commit is contained in:
parent
099d11ed9f
commit
930c21ff2f
@ -1,17 +1,27 @@
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { Table } from 'react-bootstrap';
|
import { useState } from 'react';
|
||||||
|
import { Button, Modal, Table } from 'react-bootstrap';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { getCategoryClassName } from '../lib/utils';
|
||||||
|
|
||||||
export default function DiscoveryList() {
|
export default function DiscoveryList() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { sessions, error, status } = useSelector((state) => state.discovery);
|
const { sessions, error, status } = useSelector((state) => state.discovery);
|
||||||
|
const [showSessionResultModal, setShowSessionResultModal] = useState(false);
|
||||||
|
const [selectedSession, setSelectedSession] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
// 如果加载失败,显示错误信息
|
// 如果加载失败,显示错误信息
|
||||||
if (status === 'failed') {
|
if (status === 'failed') {
|
||||||
return <div className='alert alert-danger'>{error || '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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleViewSession = (session) => {
|
||||||
|
setSelectedSession(session);
|
||||||
|
setShowSessionResultModal(true);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='discovery-list'>
|
<div className='discovery-list'>
|
||||||
<Table responsive hover className='bg-white shadow-xs rounded overflow-hidden border-1'>
|
<Table responsive hover className='bg-white shadow-xs rounded overflow-hidden border-1'>
|
||||||
@ -39,7 +49,7 @@ export default function DiscoveryList() {
|
|||||||
<td className='text-center'>{session.avg_video_views}</td>
|
<td className='text-center'>{session.avg_video_views}</td>
|
||||||
<td className='text-center'>{session.date_created}</td>
|
<td className='text-center'>{session.date_created}</td>
|
||||||
<td className='text-center'>
|
<td className='text-center'>
|
||||||
<Link to={`/creator/${session.id}`}>View</Link>
|
<Button variant='primary' onClick={() => handleViewSession(session)}>View</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
@ -52,17 +62,25 @@ export default function DiscoveryList() {
|
|||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
|
<SeesionResultModal session={selectedSession} show={showSessionResultModal} onHide={() => setShowSessionResultModal(false)} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function SeesionResultModal({ session }) {
|
function SeesionResultModal({ session, show, onHide }) {
|
||||||
|
if (!show) return null;
|
||||||
|
const { creators } = session || {};
|
||||||
|
console.log(creators);
|
||||||
return (
|
return (
|
||||||
<div className='creator-database-table'>
|
<Modal show={show} onHide={onHide} size={creators.length > 0 ? 'xl' : ''}>
|
||||||
<div className='table-container'>
|
<Modal.Header closeButton>
|
||||||
<Table responsive hover className='bg-white shadow-xs rounded overflow-hidden'>
|
<Modal.Title>Session Result</Modal.Title>
|
||||||
<thead className='sticky-header'>
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
{
|
||||||
|
creators.length > 0 ? (
|
||||||
|
<Table responsive hover className='creator-database-table bg-white shadow-xs rounded overflow-hidden'>
|
||||||
|
<thead className='sticky-header'>
|
||||||
<tr>
|
<tr>
|
||||||
<th className='creator' style={{ width: '180px' }}>
|
<th className='creator' style={{ width: '180px' }}>
|
||||||
Creator
|
Creator
|
||||||
@ -149,9 +167,13 @@ function SeesionResultModal({ session }) {
|
|||||||
</tr>
|
</tr>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
) : (
|
||||||
</div>
|
<div className='text-center py-4'>No creators found in this session.</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
8
src/components/SessionResult.jsx
Normal file
8
src/components/SessionResult.jsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export default function SessionResult() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Session Result</h1>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -38,3 +38,16 @@ export function formatNumber(number, decimals = 0, decimalPoint = '.', thousands
|
|||||||
const n = Number(number).toFixed(decimals);
|
const n = Number(number).toFixed(decimals);
|
||||||
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
|
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getCategoryClassName = (category) => {
|
||||||
|
const categoryMap = {
|
||||||
|
'Phones & Electronics': 'phones',
|
||||||
|
'Womenswear & Underwear': 'women',
|
||||||
|
'Sports & Outdoor': 'sports',
|
||||||
|
'Food & Beverage': 'food',
|
||||||
|
Health: 'health',
|
||||||
|
Kitchenware: 'kitchen',
|
||||||
|
};
|
||||||
|
|
||||||
|
return categoryMap[category] || '';
|
||||||
|
};
|
||||||
|
@ -134,3 +134,4 @@ a {
|
|||||||
box-shadow: 0px 0px 1px #171a1f12, 0px 0px 2px #171a1f1f; /* shadow-xs */
|
box-shadow: 0px 0px 1px #171a1f12, 0px 0px 2px #171a1f1f; /* shadow-xs */
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,38 +5,188 @@
|
|||||||
@import './variables';
|
@import './variables';
|
||||||
|
|
||||||
.breadcrumb {
|
.breadcrumb {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
a {
|
a {
|
||||||
color: var(--bs-body-color) !important;
|
color: var(--bs-body-color) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.function-bar {
|
.function-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
float: right;
|
float: right;
|
||||||
button {
|
button {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-button {
|
.back-button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
display: inline-flex !important;
|
display: inline-flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.back-button {
|
.back-button {
|
||||||
width: max-content;
|
width: max-content;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.creator-database-table {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.creator-cell {
|
||||||
|
.creator-avatar {
|
||||||
|
position: relative;
|
||||||
|
margin-right: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.verified-badge {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #10b981;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
font-size: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.creator-name {
|
||||||
|
font-weight: 700;
|
||||||
|
color: #090909;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-pill {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #495057;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.phones {
|
||||||
|
background-color: rgba(99, 102, 241, 0.1);
|
||||||
|
color: #6366f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.women {
|
||||||
|
background-color: rgba(244, 114, 182, 0.1);
|
||||||
|
color: #f472b6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.sports {
|
||||||
|
background-color: rgba(52, 211, 153, 0.1);
|
||||||
|
color: #34d399;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.food {
|
||||||
|
background-color: rgba(251, 146, 60, 0.1);
|
||||||
|
color: #fb923c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.health {
|
||||||
|
background-color: rgba(56, 189, 248, 0.1);
|
||||||
|
color: #38bdf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.kitchen {
|
||||||
|
background-color: rgba(168, 85, 247, 0.1);
|
||||||
|
color: #a855f7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.level-badge {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&.ecommerce-level {
|
||||||
|
background-color: rgba(99, 102, 241, 0.1);
|
||||||
|
color: #6366f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.exposure-level {
|
||||||
|
background-color: rgba(14, 165, 233, 0.1);
|
||||||
|
color: #0ea5e9;
|
||||||
|
|
||||||
|
&[data-level^='KOC'] {
|
||||||
|
background-color: rgba(52, 211, 153, 0.1);
|
||||||
|
color: #34d399;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-level^='KOL'] {
|
||||||
|
background-color: rgba(251, 113, 133, 0.1);
|
||||||
|
color: #fb7185;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.colored-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
&.blue {
|
||||||
|
background-color: #6366f1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&.tiktok-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.sticky-header {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
background: white;
|
||||||
|
|
||||||
|
th {
|
||||||
|
background: white;
|
||||||
|
border-bottom: 2px solid #dee2e6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user