fix: badge detail list styles format
This commit is contained in:
+1
-1
@@ -1743,7 +1743,7 @@ ui:
|
||||
earned_x: Earned x{{ number }}
|
||||
x_awarded: "{{ number }} awarded"
|
||||
can_earn_multiple: You can earn this multiple times.
|
||||
|
||||
earned: Earned
|
||||
|
||||
admin:
|
||||
admin_header:
|
||||
|
||||
@@ -744,6 +744,7 @@ export interface BadgeListItem {
|
||||
earned: boolean;
|
||||
/** 1: bronze 2: silver 3:gold */
|
||||
level: number;
|
||||
earned_count?: number;
|
||||
}
|
||||
|
||||
export interface BadgeListGroupItem {
|
||||
|
||||
@@ -32,23 +32,34 @@ import './index.scss';
|
||||
interface IProps {
|
||||
data: Type.BadgeListItem;
|
||||
showAwardedCount?: boolean;
|
||||
urlSearchParams?: string;
|
||||
badgePillType?: 'earned' | 'count';
|
||||
}
|
||||
|
||||
const Index: FC<IProps> = ({ data, showAwardedCount = false }) => {
|
||||
const Index: FC<IProps> = ({
|
||||
data,
|
||||
badgePillType = 'earned',
|
||||
showAwardedCount = false,
|
||||
urlSearchParams,
|
||||
}) => {
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'badges' });
|
||||
console.log(data);
|
||||
return (
|
||||
<Link className="card text-center badge-card" to={`/badges/${data.id}`}>
|
||||
<Link
|
||||
className="card text-center badge-card"
|
||||
to={`/badges/${data.id}${urlSearchParams ? `?${urlSearchParams}` : ''}`}>
|
||||
<Card.Body>
|
||||
{data.earned && (
|
||||
{data.earned && badgePillType === 'earned' && (
|
||||
<Badge bg="success" className="label">
|
||||
{t('earned')}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
{/* <Badge pill={badgePill} bg="success" className="label">
|
||||
{showEarned ? t('earned') : data.award_count}
|
||||
</Badge> */}
|
||||
{badgePillType === 'count' && Number(data?.earned_count) > 0 && (
|
||||
<Badge pill bg="success" className="label">
|
||||
x{data.earned_count}
|
||||
</Badge>
|
||||
)}
|
||||
{data.icon.startsWith('http') ? (
|
||||
<img src={data.icon} width={96} height={96} alt={data.name} />
|
||||
) : (
|
||||
|
||||
@@ -69,16 +69,16 @@ const Index: FC<IProps> = ({ data }) => {
|
||||
<div className="mt-2">{t('can_earn_multiple')}</div>
|
||||
)}
|
||||
|
||||
{data.award_count > 0 && data.earned_count > 0 && (
|
||||
{(data.award_count > 0 || data.earned_count > 0) && (
|
||||
<div className="small mt-2">
|
||||
{data.award_count > 0 && (
|
||||
<span className="text-secondary">
|
||||
<span className="text-secondary me-2">
|
||||
{t('x_awarded', { number: formatCount(data.award_count) })}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{data.earned_count > 0 && (
|
||||
<Badge bg="success" className="ms-2">
|
||||
<Badge bg="success">
|
||||
{t('earned_x', { number: data.earned_count })}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
@@ -21,20 +21,17 @@ import { memo, FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import classnames from 'classnames';
|
||||
|
||||
import { Avatar } from '@/components';
|
||||
import { formatCount } from '@/utils';
|
||||
|
||||
interface Props {
|
||||
data: any;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const Index: FC<Props> = ({ data, className = '' }) => {
|
||||
const Index: FC<Props> = ({ data }) => {
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'badges' });
|
||||
return (
|
||||
<div className={classnames('d-flex', className)}>
|
||||
<div className="d-flex">
|
||||
{data?.status !== 'deleted' ? (
|
||||
<Link to={`/users/${data?.username}`}>
|
||||
<Avatar
|
||||
@@ -72,19 +69,17 @@ const Index: FC<Props> = ({ data, className = '' }) => {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<div className="small text-secondary d-flex flex-row flex-md-column align-items-center align-items-md-start">
|
||||
<div className="me-1 me-md-0 d-flex align-items-center">
|
||||
{data?.status !== 'deleted' ? (
|
||||
<Link
|
||||
to={`/users/${data?.username}`}
|
||||
className="me-1 text-break name-ellipsis"
|
||||
style={{ maxWidth: '100px' }}>
|
||||
{data?.display_name}
|
||||
</Link>
|
||||
) : (
|
||||
<span className="me-1 text-break">{data?.display_name}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="small text-secondary d-flex flex-column">
|
||||
{data?.status !== 'deleted' ? (
|
||||
<Link
|
||||
to={`/users/${data?.username}`}
|
||||
className="me-1 text-break name-ellipsis"
|
||||
style={{ maxWidth: '100px' }}>
|
||||
{data?.display_name}
|
||||
</Link>
|
||||
) : (
|
||||
<span className="me-1 text-break">{data?.display_name}</span>
|
||||
)}
|
||||
<div className="text-secondary">
|
||||
{formatCount(data?.rank)}{' '}
|
||||
{t('x_reputation', { keyPrefix: 'personal' })}
|
||||
|
||||
@@ -24,10 +24,11 @@ import { CardBadge } from '@/components';
|
||||
|
||||
interface IProps {
|
||||
data: Type.BadgeListItem[];
|
||||
username: string;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
const Index: FC<IProps> = ({ data, visible }) => {
|
||||
const Index: FC<IProps> = ({ data, visible, username }) => {
|
||||
console.log(data);
|
||||
if (!visible) {
|
||||
return null;
|
||||
@@ -35,7 +36,13 @@ const Index: FC<IProps> = ({ data, visible }) => {
|
||||
return (
|
||||
<div className="d-flex flex-wrap" style={{ margin: '-12px' }}>
|
||||
{data.map((item) => {
|
||||
return <CardBadge data={item} />;
|
||||
return (
|
||||
<CardBadge
|
||||
data={item}
|
||||
urlSearchParams={`username=${username}`}
|
||||
badgePillType="count"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -22,16 +22,21 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Row, Col } from 'react-bootstrap';
|
||||
|
||||
// import * as Type from '@/common/interface';
|
||||
// import { CardBadge } from '@/components';
|
||||
import { CardBadge } from '@/components';
|
||||
import { useGetRecentAwardBadges } from '@/services';
|
||||
import TopList from '../TopList';
|
||||
|
||||
interface Props {
|
||||
username: string;
|
||||
visible: boolean;
|
||||
introduction: string;
|
||||
data;
|
||||
}
|
||||
const Index: FC<Props> = ({ visible, introduction, data }) => {
|
||||
const Index: FC<Props> = ({ visible, introduction, data, username }) => {
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'personal' });
|
||||
const { data: recentBadges } = useGetRecentAwardBadges(
|
||||
visible ? username : null,
|
||||
);
|
||||
if (!visible) {
|
||||
return null;
|
||||
}
|
||||
@@ -66,14 +71,22 @@ const Index: FC<Props> = ({ visible, introduction, data }) => {
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div className="mb-5">
|
||||
<h5 className="mb-3">{t('recent_badges')}</h5>
|
||||
{/* <div className="d-flex flex-wrap" style={{ margin: '-12px' }}>
|
||||
{[0, 1, 2, 3, 4, 5, 6].map((item) => {
|
||||
return <CardBadge data={item} badgePill />;
|
||||
})}
|
||||
</div> */}
|
||||
</div>
|
||||
{Number(recentBadges?.count) > 0 && (
|
||||
<div className="mb-5">
|
||||
<h5 className="mb-3">{t('recent_badges')}</h5>
|
||||
<div className="d-flex flex-wrap" style={{ margin: '-12px' }}>
|
||||
{recentBadges?.list?.map((item) => {
|
||||
return (
|
||||
<CardBadge
|
||||
data={item}
|
||||
urlSearchParams={`username=${username}`}
|
||||
badgePillType="count"
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -102,6 +102,7 @@ const Personal: FC = () => {
|
||||
visible={tabName === 'overview'}
|
||||
introduction={userInfo?.bio_html || ''}
|
||||
data={topData}
|
||||
username={username}
|
||||
/>
|
||||
|
||||
<ListHead
|
||||
@@ -119,7 +120,11 @@ const Personal: FC = () => {
|
||||
<Reputation data={list} visible={tabName === 'reputation'} />
|
||||
<Comments data={list} visible={tabName === 'comments'} />
|
||||
<Votes data={list} visible={tabName === 'votes'} />
|
||||
<Badges data={list} visible={tabName === 'badges'} />
|
||||
<Badges
|
||||
data={list}
|
||||
visible={tabName === 'badges'}
|
||||
username={username}
|
||||
/>
|
||||
{!list?.length && !isLoading && <Empty />}
|
||||
|
||||
{count > 0 && (
|
||||
|
||||
@@ -64,3 +64,19 @@ export const useBadgeDetailList = (params: Type.BadgeDetailListReq) => {
|
||||
mutate,
|
||||
};
|
||||
};
|
||||
|
||||
export const useGetRecentAwardBadges = (username) => {
|
||||
const apiUrl = username
|
||||
? `/answer/api/v1/badge/user/awards/recent?username=${username}`
|
||||
: null;
|
||||
const { data, error, mutate } = useSWR<
|
||||
{ count: number; list: Array<Type.BadgeListItem> },
|
||||
Error
|
||||
>(apiUrl, request.instance.get);
|
||||
return {
|
||||
data,
|
||||
isLoading: !data && !error,
|
||||
error,
|
||||
mutate,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user