feat(ui): add verification badge to UserProfileHeader
Add verification status display with identity-based badge icons to the user profile header component. Also add identity and verification_status fields to UserDTO and UserDetailDTO types. - Add VerificationBadge component with icon display based on identity type - Support for student, teacher, staff, alumni, and external identity types - Add 'none' status to VerificationStatus type for unverified users
This commit is contained in:
@@ -17,7 +17,7 @@ import {
|
|||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
import { MaterialCommunityIcons } from '@expo/vector-icons';
|
||||||
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
import { spacing, fontSizes, borderRadius, useAppColors, type AppColors } from '../../theme';
|
||||||
import { User } from '../../types';
|
import { User, UserIdentity, VerificationStatus } from '../../types';
|
||||||
import Text from '../common/Text';
|
import Text from '../common/Text';
|
||||||
import Avatar from '../common/Avatar';
|
import Avatar from '../common/Avatar';
|
||||||
import { ImageGallery } from '../common';
|
import { ImageGallery } from '../common';
|
||||||
@@ -281,7 +281,10 @@ const UserProfileHeader: React.FC<UserProfileHeaderProps> = ({
|
|||||||
|
|
||||||
{/* 用户名 */}
|
{/* 用户名 */}
|
||||||
<View style={styles.nameSection}>
|
<View style={styles.nameSection}>
|
||||||
|
<View style={styles.nicknameRow}>
|
||||||
<Text style={styles.nickname}>{user.nickname}</Text>
|
<Text style={styles.nickname}>{user.nickname}</Text>
|
||||||
|
<VerificationBadge identity={user.identity} verificationStatus={user.verification_status} />
|
||||||
|
</View>
|
||||||
<Text style={styles.username}>@{user.username}</Text>
|
<Text style={styles.username}>@{user.username}</Text>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
@@ -477,11 +480,16 @@ function createUserProfileHeaderStyles(colors: AppColors) {
|
|||||||
nameSection: {
|
nameSection: {
|
||||||
marginBottom: spacing.sm,
|
marginBottom: spacing.sm,
|
||||||
},
|
},
|
||||||
|
nicknameRow: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: spacing.xs,
|
||||||
|
marginBottom: 2,
|
||||||
|
},
|
||||||
nickname: {
|
nickname: {
|
||||||
fontSize: fontSizes['2xl'],
|
fontSize: fontSizes['2xl'],
|
||||||
fontWeight: '800',
|
fontWeight: '800',
|
||||||
color: colors.text.primary,
|
color: colors.text.primary,
|
||||||
marginBottom: 2,
|
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
fontSize: fontSizes.md,
|
fontSize: fontSizes.md,
|
||||||
@@ -564,5 +572,54 @@ function createUserProfileHeaderStyles(colors: AppColors) {
|
|||||||
|
|
||||||
import { shadows } from '../../theme';
|
import { shadows } from '../../theme';
|
||||||
|
|
||||||
|
// ==================== VerificationBadge ====================
|
||||||
|
|
||||||
|
interface VerificationBadgeProps {
|
||||||
|
identity?: UserIdentity;
|
||||||
|
verificationStatus?: VerificationStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const IDENTITY_CONFIG: Record<
|
||||||
|
UserIdentity,
|
||||||
|
{ label: string; color: string; bg: string }
|
||||||
|
> = {
|
||||||
|
general: { label: '未认证', color: '#9CA3AF', bg: '#F3F4F6' },
|
||||||
|
student: { label: '学生认证', color: '#10B981', bg: '#D1FAE5' },
|
||||||
|
teacher: { label: '教师认证', color: '#3B82F6', bg: '#DBEAFE' },
|
||||||
|
staff: { label: '职工认证', color: '#8B5CF6', bg: '#EDE9FE' },
|
||||||
|
alumni: { label: '校友认证', color: '#F59E0B', bg: '#FEF3C7' },
|
||||||
|
external: { label: '未认证', color: '#9CA3AF', bg: '#F3F4F6' },
|
||||||
|
};
|
||||||
|
|
||||||
|
const VerificationBadge: React.FC<VerificationBadgeProps> = ({
|
||||||
|
identity,
|
||||||
|
verificationStatus,
|
||||||
|
}) => {
|
||||||
|
const colors = useAppColors();
|
||||||
|
|
||||||
|
// 默认值:未认证状态
|
||||||
|
const effectiveIdentity = identity || 'general';
|
||||||
|
const effectiveStatus = verificationStatus || 'none';
|
||||||
|
|
||||||
|
const isApproved = effectiveStatus === 'approved';
|
||||||
|
// none 表示未认证,统一用 general 的未认证样式
|
||||||
|
const displayIdentity = isApproved ? effectiveIdentity : 'general';
|
||||||
|
const config = IDENTITY_CONFIG[displayIdentity] || IDENTITY_CONFIG.general;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={{ width: 22, height: 22, justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
{isApproved ? (
|
||||||
|
<MaterialCommunityIcons name="check-decagram" size={22} color={config.color} />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<MaterialCommunityIcons name="decagram" size={22} color="#9CA3AF" />
|
||||||
|
<MaterialCommunityIcons name="decagram-outline" size={22} color="#9CA3AF" style={{ position: 'absolute' }} />
|
||||||
|
<Text style={{ position: 'absolute', fontSize: 11, fontWeight: '800', color: '#FFFFFF', marginTop: 1 }}>?</Text>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const MemoizedUserProfileHeader = React.memo(UserProfileHeader);
|
const MemoizedUserProfileHeader = React.memo(UserProfileHeader);
|
||||||
export default MemoizedUserProfileHeader;
|
export default MemoizedUserProfileHeader;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ export interface UserDTO {
|
|||||||
created_at: string;
|
created_at: string;
|
||||||
is_following?: boolean;
|
is_following?: boolean;
|
||||||
is_following_me?: boolean;
|
is_following_me?: boolean;
|
||||||
|
identity?: UserIdentity;
|
||||||
|
verification_status?: VerificationStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserDetailDTO {
|
export interface UserDetailDTO {
|
||||||
@@ -43,6 +45,8 @@ export interface UserDetailDTO {
|
|||||||
// 额外字段
|
// 额外字段
|
||||||
is_following?: boolean; // 当前用户是否关注了该用户
|
is_following?: boolean; // 当前用户是否关注了该用户
|
||||||
is_following_me?: boolean; // 该用户是否关注了当前用户
|
is_following_me?: boolean; // 该用户是否关注了当前用户
|
||||||
|
identity?: UserIdentity;
|
||||||
|
verification_status?: VerificationStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Post DTOs ====================
|
// ==================== Post DTOs ====================
|
||||||
@@ -858,7 +862,7 @@ export interface CreateVotePostRequest {
|
|||||||
|
|
||||||
// ==================== Verification DTOs ====================
|
// ==================== Verification DTOs ====================
|
||||||
|
|
||||||
export type VerificationStatus = 'not_submitted' | 'pending' | 'approved' | 'rejected';
|
export type VerificationStatus = 'not_submitted' | 'pending' | 'approved' | 'rejected' | 'none';
|
||||||
export type UserIdentity = 'general' | 'student' | 'teacher' | 'staff' | 'alumni' | 'external';
|
export type UserIdentity = 'general' | 'student' | 'teacher' | 'staff' | 'alumni' | 'external';
|
||||||
|
|
||||||
export interface VerificationStatusDTO {
|
export interface VerificationStatusDTO {
|
||||||
|
|||||||
Reference in New Issue
Block a user