@ludiks/react
Version:
Complete React library for Ludiks gamification platform - includes SDK and ready-to-use components
163 lines (162 loc) • 16.5 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useUserProfile } from '../../hooks/useUserProfile';
export function UserProfile({ userId, showCircuits = true, showRewards = true, showMetadata = false, showStreak = true, circuitLimit = 5, variant = 'card', orientation = 'vertical', autoRefresh = false, refreshInterval = 30000, className, colors = {}, }) {
const { profile, loading, error } = useUserProfile({
userId,
autoRefresh,
refreshInterval,
});
const styles = {
primary: colors.primary || '#8b5cf6',
secondary: colors.secondary || '#06d6a0',
success: colors.success || '#10b981',
background: colors.background || '#ffffff',
text: colors.text || '#1f2937',
};
if (loading) {
return (_jsx("div", { style: {
padding: '24px',
animation: 'fadeIn 0.3s ease-in-out'
}, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '16px' }, children: [_jsx("div", { style: { width: '64px', height: '64px', backgroundColor: '#e5e7eb', borderRadius: '50%' } }), _jsxs("div", { style: { flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' }, children: [_jsx("div", { style: { height: '16px', backgroundColor: '#e5e7eb', borderRadius: '4px', width: '75%' } }), _jsx("div", { style: { height: '12px', backgroundColor: '#e5e7eb', borderRadius: '4px', width: '50%' } })] })] }) }));
}
if (error || !profile) {
return (_jsx("div", { style: { padding: '24px', textAlign: 'center', color: '#ef4444' }, children: error || 'Failed to load user profile' }));
}
const getStatusColor = (status) => {
switch (status) {
case 'completed': return styles.success;
case 'in_progress': return styles.primary;
default: return '#9ca3af';
}
};
const getStatusIcon = (status) => {
switch (status) {
case 'completed':
return '✅';
case 'in_progress':
return '⏳';
default:
return '⏸️';
}
};
const renderCircuitProgress = (circuit) => {
const completedSteps = circuit.stepProgressions.filter(s => s.status === 'completed').length;
const totalSteps = circuit.stepProgressions.length;
const progressPercentage = totalSteps > 0 ? (completedSteps / totalSteps) * 100 : 0;
return (_jsxs("div", { style: {
border: '1px solid #e5e7eb',
borderRadius: '8px',
padding: '16px',
marginBottom: '16px',
backgroundColor: 'white'
}, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '12px' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '12px' }, children: [_jsx("div", { style: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '32px',
height: '32px',
borderRadius: '50%',
backgroundColor: getStatusColor(circuit.status),
color: 'white',
fontSize: '16px'
}, children: getStatusIcon(circuit.status) }), _jsxs("div", { children: [_jsx("h4", { style: { fontWeight: '600', color: styles.text, margin: 0 }, children: circuit.name }), _jsxs("p", { style: { fontSize: '14px', color: '#6b7280', margin: '4px 0 0 0', textTransform: 'capitalize' }, children: [circuit.type, " \u2022 ", circuit.status.replace('_', ' ')] })] })] }), _jsxs("div", { style: { textAlign: 'right' }, children: [_jsxs("div", { style: { fontWeight: 'bold', color: styles.primary }, children: [circuit.points, " pts"] }), _jsxs("div", { style: { fontSize: '14px', color: '#6b7280' }, children: [completedSteps, "/", totalSteps, " \u00E9tapes"] })] })] }), _jsxs("div", { style: { marginBottom: '12px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', fontSize: '14px', color: '#6b7280', marginBottom: '4px' }, children: [_jsx("span", { children: "Progression" }), _jsxs("span", { children: [Math.round(progressPercentage), "%"] })] }), _jsx("div", { style: { width: '100%', height: '8px', backgroundColor: '#e5e7eb', borderRadius: '4px', overflow: 'hidden' }, children: _jsx("div", { style: {
height: '100%',
borderRadius: '4px',
backgroundColor: getStatusColor(circuit.status),
width: `${progressPercentage}%`,
transition: 'width 0.3s ease'
} }) })] }), circuit.stepProgressions.length > 0 && (_jsxs("div", { children: [circuit.stepProgressions.slice(0, 3).map((step) => (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '14px', marginBottom: '4px' }, children: [_jsx("div", { style: {
width: '16px',
height: '16px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: step.status === 'completed' ? styles.success : '#e5e7eb',
color: 'white',
fontSize: '10px'
}, children: step.status === 'completed' ? '✓' : '○' }), _jsx("span", { style: {
color: step.status === 'completed' ? '#6b7280' : styles.text,
textDecoration: step.status === 'completed' ? 'line-through' : 'none'
}, children: step.name }), _jsxs("span", { style: { marginLeft: 'auto', fontSize: '12px', color: styles.primary }, children: [step.points, " pts"] })] }, step.id))), circuit.stepProgressions.length > 3 && (_jsxs("div", { style: { fontSize: '12px', color: '#9ca3af', textAlign: 'center', marginTop: '8px' }, children: ["+", circuit.stepProgressions.length - 3, " \u00E9tapes suppl\u00E9mentaires"] }))] }))] }, circuit.id));
};
if (variant === 'minimal') {
return (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '16px', padding: '16px' }, children: [profile.picture ? (_jsx("img", { src: profile.picture, alt: profile.fullName, style: {
width: '48px',
height: '48px',
borderRadius: '50%',
objectFit: 'cover'
} })) : (_jsx("div", { style: {
width: '48px',
height: '48px',
borderRadius: '50%',
background: `linear-gradient(135deg, ${styles.primary} 0%, ${styles.secondary} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontWeight: 'bold',
fontSize: '20px'
}, children: profile.fullName.charAt(0) })), _jsxs("div", { children: [_jsx("h3", { style: { fontWeight: '600', color: styles.text, margin: 0 }, children: profile.fullName }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '16px', fontSize: '14px', color: '#6b7280', marginTop: '4px' }, children: [showStreak && (_jsxs("span", { children: ["\uD83D\uDD25 ", profile.currentStreak, " jours de s\u00E9rie"] })), _jsxs("span", { style: { color: styles.primary }, children: [profile.progressions.reduce((sum, c) => sum + c.points, 0), " pts"] })] })] })] }));
}
const headerContent = (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '16px', marginBottom: '24px' }, children: [profile.picture ? (_jsx("img", { src: profile.picture, alt: profile.fullName, style: {
width: '64px',
height: '64px',
borderRadius: '50%',
border: `2px solid ${styles.primary}`,
objectFit: 'cover'
} })) : (_jsx("div", { style: {
width: '64px',
height: '64px',
borderRadius: '50%',
background: `linear-gradient(135deg, ${styles.primary} 0%, ${styles.secondary} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontWeight: 'bold',
fontSize: '24px',
border: `2px solid ${styles.primary}`
}, children: profile.fullName.charAt(0) })), _jsxs("div", { style: { flex: 1 }, children: [_jsx("h2", { style: { fontSize: '20px', fontWeight: 'bold', color: styles.text, margin: 0 }, children: profile.fullName }), profile.email && (_jsx("p", { style: { color: '#6b7280', margin: '4px 0 0 0' }, children: profile.email })), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '24px', marginTop: '8px' }, children: [showStreak && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [_jsx("span", { style: { color: '#f59e0b' }, children: "\uD83D\uDD25" }), _jsxs("span", { style: { fontWeight: '500' }, children: [profile.currentStreak, " jours"] }), profile.longestStreak > profile.currentStreak && (_jsxs("span", { style: { fontSize: '12px', color: '#9ca3af' }, children: ["(record: ", profile.longestStreak, ")"] }))] })), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [_jsx("span", { style: { color: styles.primary }, children: "\u2B50" }), _jsxs("span", { style: { fontWeight: '500' }, children: [profile.progressions.reduce((sum, c) => sum + c.points, 0), " points"] })] }), showRewards && profile.rewards.length > 0 && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [_jsx("span", { style: { color: styles.secondary }, children: "\uD83C\uDFC6" }), _jsxs("span", { style: { fontWeight: '500' }, children: [profile.rewards.length, " r\u00E9compenses"] })] }))] })] })] }));
if (variant === 'dashboard') {
return (_jsxs("div", { style: {
display: 'grid',
gap: '24px',
gridTemplateColumns: orientation === 'horizontal' ? '1fr 1fr' : '1fr'
}, children: [_jsxs("div", { children: [headerContent, showMetadata && Object.keys(profile.metadata).length > 0 && (_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h3", { style: { fontWeight: '600', color: '#374151', marginBottom: '12px' }, children: "M\u00E9tadonn\u00E9es" }), _jsx("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '8px', fontSize: '14px' }, children: Object.entries(profile.metadata).map(([key, value]) => (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsxs("span", { style: { color: '#6b7280' }, children: [key, ":"] }), _jsx("span", { style: { fontWeight: '500' }, children: String(value) })] }, key))) })] }))] }), showCircuits && profile.progressions.length > 0 && (_jsxs("div", { children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '16px' }, children: [_jsx("h3", { style: { fontWeight: '600', color: styles.text }, children: "Progression des circuits" }), _jsxs("span", { style: { fontSize: '14px', color: '#6b7280' }, children: [profile.progressions.slice(0, circuitLimit).length, " sur ", profile.progressions.length] })] }), _jsx("div", { children: profile.progressions.slice(0, circuitLimit).map(renderCircuitProgress) })] }))] }));
}
// Default: card variant
return (_jsxs("div", { style: {
borderRadius: '12px',
border: '1px solid #e5e7eb',
padding: '24px',
backgroundColor: styles.background,
width: '100%',
maxWidth: '600px'
}, children: [headerContent, showCircuits && profile.progressions.length > 0 && (_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h3", { style: { fontWeight: '600', fontSize: '18px', color: styles.text, marginBottom: '16px' }, children: "Circuits actifs" }), _jsx("div", { children: profile.progressions.slice(0, circuitLimit).map(renderCircuitProgress) }), profile.progressions.length > circuitLimit && (_jsxs("div", { style: { textAlign: 'center', fontSize: '14px', color: '#6b7280', marginTop: '16px' }, children: ["+", profile.progressions.length - circuitLimit, " circuits suppl\u00E9mentaires"] }))] })), showRewards && profile.rewards.length > 0 && (_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h3", { style: { fontWeight: '600', fontSize: '18px', color: styles.text, marginBottom: '16px' }, children: "R\u00E9compenses r\u00E9centes" }), _jsx("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '12px' }, children: profile.rewards.slice(0, 6).map((reward) => (_jsxs("div", { style: {
display: 'flex',
alignItems: 'center',
gap: '12px',
padding: '12px',
backgroundColor: '#f9fafb',
borderRadius: '8px',
border: '1px solid #e5e7eb'
}, children: [_jsx("div", { style: {
width: '32px',
height: '32px',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: styles.secondary,
color: 'white',
fontSize: '16px'
}, children: "\uD83C\uDFC6" }), _jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [_jsx("p", { style: { fontWeight: '500', fontSize: '14px', margin: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: reward.name }), _jsx("p", { style: { fontSize: '12px', color: '#6b7280', margin: '4px 0 0 0', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: reward.circuitName })] })] }, reward.id))) }), profile.rewards.length > 6 && (_jsxs("div", { style: { textAlign: 'center', fontSize: '14px', color: '#6b7280', marginTop: '16px' }, children: ["+", profile.rewards.length - 6, " r\u00E9compenses suppl\u00E9mentaires"] }))] })), showMetadata && Object.keys(profile.metadata).length > 0 && (_jsxs("div", { children: [_jsx("h3", { style: { fontWeight: '600', fontSize: '18px', color: styles.text, marginBottom: '16px' }, children: "M\u00E9tadonn\u00E9es utilisateur" }), _jsx("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '8px', fontSize: '14px' }, children: Object.entries(profile.metadata).map(([key, value]) => (_jsxs("div", { style: {
display: 'flex',
justifyContent: 'space-between',
padding: '8px 12px',
backgroundColor: '#f9fafb',
borderRadius: '6px',
border: '1px solid #e5e7eb'
}, children: [_jsxs("span", { style: { color: '#6b7280' }, children: [key, ":"] }), _jsx("span", { style: { fontWeight: '500', color: '#111827' }, children: String(value) })] }, key))) })] }))] }));
}