mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-10-17 03:15:01 +03:00
feat(sponsors): drop the sidebar slot and simplify the Sponsors page
The sidebar no longer carries a sponsor card. The backend stops serving the "sidebar" slot, so a sponsors.json entry that still lists it keeps only its other slots and one listing nothing else is dropped. Its rotation, three-sponsor cap and collapsed-rail logo rendering go with it. The Sponsors page now lists only real sponsors: the "Your brand here" card shows only as the empty state instead of sitting in the grid and repeating the header's Become a sponsor button, and the Available placements section and its slot-occupancy helper are removed. Cards are larger, two per row on wide screens. Unused i18n keys are dropped from every locale.
This commit is contained in:
@@ -29,30 +29,14 @@
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.sponsors-page .sponsors-section-title {
|
||||
margin: 32px 0 12px;
|
||||
color: var(--ant-color-text-secondary);
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.sponsors-yourbrand {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 100%;
|
||||
min-height: 170px;
|
||||
padding: 16px;
|
||||
padding: 40px 24px;
|
||||
border: 1.5px dashed var(--ant-color-border);
|
||||
border-radius: var(--ant-border-radius-lg, 8px);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sponsors-yourbrand.is-large {
|
||||
align-items: center;
|
||||
min-height: 0;
|
||||
padding: 40px 24px;
|
||||
text-align: center;
|
||||
background: var(--bg-card, transparent);
|
||||
}
|
||||
@@ -82,58 +66,6 @@
|
||||
color: var(--ant-color-text-secondary);
|
||||
}
|
||||
|
||||
.sponsors-yourbrand:not(.is-large) .ant-btn {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.sponsors-placement {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
padding: 14px 16px;
|
||||
border: 1px solid var(--ant-color-border-secondary);
|
||||
border-radius: var(--ant-border-radius-lg, 8px);
|
||||
background: var(--bg-card, transparent);
|
||||
}
|
||||
|
||||
.sponsors-placement-icon {
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
font-size: 17px;
|
||||
color: var(--ant-color-primary);
|
||||
background: var(--ant-color-primary-bg);
|
||||
}
|
||||
|
||||
.sponsors-placement-title {
|
||||
font-weight: 600;
|
||||
color: var(--ant-color-text);
|
||||
}
|
||||
|
||||
.sponsors-placement-body {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sponsors-placement-status {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.sponsors-placement-status .ant-tag {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sponsors-placement-desc {
|
||||
font-size: 13px;
|
||||
color: var(--ant-color-text-secondary);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.sponsors-page .content-area {
|
||||
padding: 12px;
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button, Col, ConfigProvider, Layout, Row, Spin, Tag, Typography } from 'antd';
|
||||
import {
|
||||
CrownOutlined,
|
||||
DashboardOutlined,
|
||||
LoginOutlined,
|
||||
MenuUnfoldOutlined,
|
||||
PlusOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Button, Col, ConfigProvider, Layout, Row, Spin, Typography } from 'antd';
|
||||
import { CrownOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
|
||||
import { useTheme } from '@/hooks/useTheme';
|
||||
import AppSidebar from '@/layouts/AppSidebar';
|
||||
import { useSponsorsQuery } from '@/api/queries/useSponsorsQuery';
|
||||
import SponsorCard from '@/components/sponsor/SponsorCard';
|
||||
import { IntlUtil } from '@/utils';
|
||||
import { useDatepicker } from '@/hooks/useDatepicker';
|
||||
import { placementStatus, sponsorsForSlot, type SponsorSlot } from '@/lib/sponsors';
|
||||
import { sponsorsForSlot } from '@/lib/sponsors';
|
||||
import './SponsorsPage.css';
|
||||
|
||||
function BecomeButton({ contact, block }: { contact?: string; block?: boolean }) {
|
||||
@@ -36,10 +27,10 @@ function BecomeButton({ contact, block }: { contact?: string; block?: boolean })
|
||||
);
|
||||
}
|
||||
|
||||
function YourBrandCard({ contact, large }: { contact?: string; large?: boolean }) {
|
||||
function YourBrandCard({ contact }: { contact?: string }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={`sponsors-yourbrand${large ? ' is-large' : ''}`}>
|
||||
<div className="sponsors-yourbrand">
|
||||
<span className="sponsors-yourbrand-icon">
|
||||
<PlusOutlined />
|
||||
</span>
|
||||
@@ -56,34 +47,6 @@ export default function SponsorsPage() {
|
||||
const { data, fetched } = useSponsorsQuery();
|
||||
const sponsors = sponsorsForSlot(data.sponsors, 'page');
|
||||
|
||||
const { datepicker } = useDatepicker();
|
||||
const placements: { slot: SponsorSlot; icon: ReactNode; title: string; desc: string }[] = [
|
||||
{
|
||||
slot: 'dashboard',
|
||||
icon: <DashboardOutlined />,
|
||||
title: t('pages.sponsors.placementDashboard'),
|
||||
desc: t('pages.sponsors.placementDashboardDesc'),
|
||||
},
|
||||
{
|
||||
slot: 'sidebar',
|
||||
icon: <MenuUnfoldOutlined />,
|
||||
title: t('pages.sponsors.placementSidebar'),
|
||||
desc: t('pages.sponsors.placementSidebarDesc'),
|
||||
},
|
||||
{
|
||||
slot: 'login',
|
||||
icon: <LoginOutlined />,
|
||||
title: t('pages.sponsors.placementLogin'),
|
||||
desc: t('pages.sponsors.placementLoginDesc'),
|
||||
},
|
||||
{
|
||||
slot: 'page',
|
||||
icon: <CrownOutlined />,
|
||||
title: t('pages.sponsors.placementPage'),
|
||||
desc: t('pages.sponsors.placementPageDesc'),
|
||||
},
|
||||
];
|
||||
|
||||
const pageClass = useMemo(() => {
|
||||
const classes = ['sponsors-page'];
|
||||
if (isDark) classes.push('is-dark');
|
||||
@@ -110,63 +73,17 @@ export default function SponsorsPage() {
|
||||
|
||||
<Spin spinning={!fetched} delay={200}>
|
||||
{sponsors.length === 0 ? (
|
||||
fetched && <YourBrandCard contact={data.contact} large />
|
||||
fetched && <YourBrandCard contact={data.contact} />
|
||||
) : (
|
||||
<Row gutter={[16, 16]}>
|
||||
{sponsors.map((sponsor) => (
|
||||
<Col key={sponsor.id} xs={24} sm={12} xl={8}>
|
||||
<Col key={sponsor.id} xs={24} lg={12}>
|
||||
<SponsorCard sponsor={sponsor} variant="card" />
|
||||
</Col>
|
||||
))}
|
||||
{data.contact && (
|
||||
<Col xs={24} sm={12} xl={8}>
|
||||
<YourBrandCard contact={data.contact} />
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
)}
|
||||
</Spin>
|
||||
|
||||
<Typography.Title level={5} className="sponsors-section-title">
|
||||
{t('pages.sponsors.placements')}
|
||||
</Typography.Title>
|
||||
<Row gutter={[16, 16]}>
|
||||
{placements.map((p) => {
|
||||
const status = placementStatus(data.sponsors, p.slot);
|
||||
return (
|
||||
<Col key={p.slot} xs={24} sm={12} xl={6}>
|
||||
<div className="sponsors-placement">
|
||||
<span className="sponsors-placement-icon">{p.icon}</span>
|
||||
<div className="sponsors-placement-body">
|
||||
<div className="sponsors-placement-title">{p.title}</div>
|
||||
<div className="sponsors-placement-desc">{p.desc}</div>
|
||||
<div className="sponsors-placement-status">
|
||||
{status.takenUntil ? (
|
||||
<Tag color="orange">
|
||||
{t('pages.sponsors.takenUntil', {
|
||||
date: IntlUtil.formatDate(status.takenUntil, datepicker),
|
||||
})}
|
||||
</Tag>
|
||||
) : (
|
||||
<Tag color="green">{t('pages.sponsors.available')}</Tag>
|
||||
)}
|
||||
{status.count > 0 && !status.takenUntil && (
|
||||
<Tag>
|
||||
{t('pages.sponsors.activeCount', {
|
||||
count:
|
||||
status.capacity && status.capacity > 1
|
||||
? `${status.count}/${status.capacity}`
|
||||
: status.count,
|
||||
})}
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
);
|
||||
})}
|
||||
</Row>
|
||||
</div>
|
||||
</Layout.Content>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user