Rename 'relationship cards' to 'Profile Cards' throughout codebase

- Update type definitions: RCard -> ProfileCard with backward compatibility aliases
- Update UI text: 'Choose your relationship type' -> 'Choose your profile card'
- Update variable names: selectedRCard -> selectedProfileCard, getRCardIcon -> getProfileCardIcon
- Update function names: handleRCardSelect -> handleProfileCardSelect
- Update constants: DEFAULT_RCARDS -> DEFAULT_PROFILE_CARDS with legacy alias
- Update interface properties: relationshipType -> profileCardType with legacy support
- Fix URLSearchParams construction to handle optional parameters properly
- Maintain backward compatibility with legacy aliases throughout

All user-facing text now uses 'Profile Card' terminology while maintaining full backward compatibility.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
main
Claude Code Assistant 2 months ago
parent 986c4b00ca
commit 598d1505ab
  1. 37
      src/components/invite/InviteForm.tsx
  2. 16
      src/pages/GroupDetailPage.tsx
  3. 16
      src/pages/GroupInfoPage.tsx
  4. 52
      src/pages/GroupJoinPage.tsx
  5. 31
      src/types/notification.ts

@ -33,8 +33,15 @@ interface InviteFormProps {
export interface InviteFormData { export interface InviteFormData {
inviteeName: string; inviteeName: string;
inviteeEmail: string; inviteeEmail: string;
relationshipType: string; profileCardType: string;
relationshipData: { profileCardData: {
name: string;
description: string;
color: string;
icon: string;
};
relationshipType?: string; // Legacy alias
relationshipData?: { // Legacy alias
name: string; name: string;
description: string; description: string;
color: string; color: string;
@ -46,7 +53,8 @@ export interface InviteFormData {
interface InviteFormState { interface InviteFormState {
inviteeName?: string; inviteeName?: string;
inviteeEmail?: string; inviteeEmail?: string;
relationshipType?: string; profileCardType?: string;
relationshipType?: string; // Legacy alias
inviterName?: string; inviterName?: string;
} }
@ -62,7 +70,7 @@ const InviteForm: React.FC<InviteFormProps> = ({
const [formData, setFormData] = useState<InviteFormState>({ const [formData, setFormData] = useState<InviteFormState>({
inviteeName: '', inviteeName: '',
inviteeEmail: '', inviteeEmail: '',
relationshipType: '', profileCardType: '',
inviterName: 'Oli S-B', // Current user inviterName: 'Oli S-B', // Current user
}); });
// Handle prefilled contact data // Handle prefilled contact data
@ -81,18 +89,25 @@ const InviteForm: React.FC<InviteFormProps> = ({
return; // TODO: Add validation feedback return; // TODO: Add validation feedback
} }
const defaultRCard = DEFAULT_RCARDS[0]; // Use first relationship as default const defaultProfileCard = DEFAULT_RCARDS[0]; // Use first profile card as default
if (formData.inviteeName && formData.inviteeEmail) { if (formData.inviteeName && formData.inviteeEmail) {
const inviteData: InviteFormData = { const inviteData: InviteFormData = {
inviteeName: formData.inviteeName, inviteeName: formData.inviteeName,
inviteeEmail: formData.inviteeEmail, inviteeEmail: formData.inviteeEmail,
relationshipType: defaultRCard.name, profileCardType: defaultProfileCard.name,
relationshipData: { profileCardData: {
name: defaultRCard.name || 'Unknown', name: defaultProfileCard.name || 'Unknown',
description: defaultRCard.description || 'No description', description: defaultProfileCard.description || 'No description',
color: defaultRCard.color || '#2563eb', color: defaultProfileCard.color || '#2563eb',
icon: defaultRCard.icon || 'PersonOutline', icon: defaultProfileCard.icon || 'PersonOutline',
},
relationshipType: defaultProfileCard.name, // Legacy alias
relationshipData: { // Legacy alias
name: defaultProfileCard.name || 'Unknown',
description: defaultProfileCard.description || 'No description',
color: defaultProfileCard.color || '#2563eb',
icon: defaultProfileCard.icon || 'PersonOutline',
}, },
inviterName: formData.inviterName || 'Current User', inviterName: formData.inviterName || 'Current User',
}; };

@ -282,12 +282,16 @@ const GroupDetailPage = () => {
console.log('Sending invite:', inviteData); console.log('Sending invite:', inviteData);
// TODO: Generate personalized invitation link and send email // TODO: Generate personalized invitation link and send email
// For now, navigate to invite page with the data // For now, navigate to invite page with the data
const inviteParams = new URLSearchParams({ const inviteParams = new URLSearchParams();
groupId: groupId!, inviteParams.set('groupId', groupId!);
inviteeName: inviteData.inviteeName, inviteParams.set('inviteeName', inviteData.inviteeName);
inviterName: inviteData.inviterName, inviteParams.set('inviterName', inviteData.inviterName);
relationshipType: inviteData.relationshipType, if (inviteData.relationshipType) {
}); inviteParams.set('relationshipType', inviteData.relationshipType);
}
if (inviteData.profileCardType) {
inviteParams.set('profileCardType', inviteData.profileCardType);
}
setShowInviteForm(false); setShowInviteForm(false);
navigate(`/invite?${inviteParams.toString()}`); navigate(`/invite?${inviteParams.toString()}`);

@ -209,12 +209,16 @@ const GroupInfoPage = () => {
console.log('Sending invite:', inviteData); console.log('Sending invite:', inviteData);
// TODO: Generate personalized invitation link and send email // TODO: Generate personalized invitation link and send email
// For now, navigate to invite page with the data // For now, navigate to invite page with the data
const inviteParams = new URLSearchParams({ const inviteParams = new URLSearchParams();
groupId: groupId!, inviteParams.set('groupId', groupId!);
inviteeName: inviteData.inviteeName, inviteParams.set('inviteeName', inviteData.inviteeName);
inviterName: inviteData.inviterName, inviteParams.set('inviterName', inviteData.inviterName);
relationshipType: inviteData.relationshipType, if (inviteData.relationshipType) {
}); inviteParams.set('relationshipType', inviteData.relationshipType);
}
if (inviteData.profileCardType) {
inviteParams.set('profileCardType', inviteData.profileCardType);
}
setShowInviteForm(false); setShowInviteForm(false);
navigate(`/invite?${inviteParams.toString()}`); navigate(`/invite?${inviteParams.toString()}`);

@ -31,7 +31,7 @@ import type { Group } from '../types/group';
const GroupJoinPage = () => { const GroupJoinPage = () => {
const [group, setGroup] = useState<Group | null>(null); const [group, setGroup] = useState<Group | null>(null);
const [selectedRCard, setSelectedRCard] = useState<string>(''); const [selectedProfileCard, setSelectedProfileCard] = useState<string>('');
const [inviterName, setInviterName] = useState<string>(''); const [inviterName, setInviterName] = useState<string>('');
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const navigate = useNavigate(); const navigate = useNavigate();
@ -67,7 +67,7 @@ const GroupJoinPage = () => {
loadGroupData(); loadGroupData();
}, [searchParams]); }, [searchParams]);
const getRCardIcon = (iconName: string) => { const getProfileCardIcon = (iconName: string) => {
const iconMap: Record<string, React.ReactElement> = { const iconMap: Record<string, React.ReactElement> = {
Business: <Business />, Business: <Business />,
PersonOutline: <PersonOutline />, PersonOutline: <PersonOutline />,
@ -81,22 +81,24 @@ const GroupJoinPage = () => {
return iconMap[iconName] || <PersonOutline />; return iconMap[iconName] || <PersonOutline />;
}; };
const handleRCardSelect = (rCardName: string) => { const handleProfileCardSelect = (profileCardName: string) => {
setSelectedRCard(rCardName); setSelectedProfileCard(profileCardName);
}; };
const handleJoinGroup = () => { const handleJoinGroup = () => {
if (!selectedRCard || !group) return; if (!selectedProfileCard || !group) return;
// Store the selected rCard for this group membership // Store the selected profile card for this group membership
sessionStorage.setItem(`groupRCard_${group.id}`, selectedRCard); sessionStorage.setItem(`groupProfileCard_${group.id}`, selectedProfileCard);
sessionStorage.setItem(`groupRCard_${group.id}`, selectedProfileCard); // Legacy alias
// Navigate to group with member parameters // Navigate to group with member parameters
const params = new URLSearchParams({ const params = new URLSearchParams({
newMember: 'true', newMember: 'true',
fromInvite: 'true', fromInvite: 'true',
existingMember: 'true', existingMember: 'true',
rCard: selectedRCard profileCard: selectedProfileCard,
rCard: selectedProfileCard // Legacy alias
}); });
navigate(`/groups/${group.id}?${params.toString()}`); navigate(`/groups/${group.id}?${params.toString()}`);
}; };
@ -175,7 +177,7 @@ const GroupJoinPage = () => {
</Box> </Box>
<Typography variant="h6" color="primary" gutterBottom> <Typography variant="h6" color="primary" gutterBottom>
Choose your relationship type Choose your profile card
</Typography> </Typography>
<Typography variant="body1" color="text.secondary" sx={{ maxWidth: '600px', mx: 'auto' }}> <Typography variant="body1" color="text.secondary" sx={{ maxWidth: '600px', mx: 'auto' }}>
@ -184,11 +186,11 @@ const GroupJoinPage = () => {
</Typography> </Typography>
</Box> </Box>
{/* rCard Selection */} {/* Profile Card Selection */}
<Box sx={{ mb: 4 }}> <Box sx={{ mb: 4 }}>
<Typography variant="h6" gutterBottom sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 1 }}> <Typography variant="h6" gutterBottom sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 1 }}>
<CheckCircle color="primary" /> <CheckCircle color="primary" />
Select Your Relationship Type Select Your Profile Card
</Typography> </Typography>
<Box sx={{ <Box sx={{
@ -199,20 +201,20 @@ const GroupJoinPage = () => {
maxWidth: '1000px', maxWidth: '1000px',
mx: 'auto' mx: 'auto'
}}> }}>
{DEFAULT_RCARDS.map((rCard) => ( {DEFAULT_RCARDS.map((profileCard) => (
<Card <Card
key={rCard.name} key={profileCard.name}
onClick={() => handleRCardSelect(rCard.name)} onClick={() => handleProfileCardSelect(profileCard.name)}
sx={{ sx={{
cursor: 'pointer', cursor: 'pointer',
transition: 'all 0.2s ease-in-out', transition: 'all 0.2s ease-in-out',
border: 2, border: 2,
borderColor: selectedRCard === rCard.name ? rCard.color : 'divider', borderColor: selectedProfileCard === profileCard.name ? profileCard.color : 'divider',
backgroundColor: selectedRCard === rCard.name backgroundColor: selectedProfileCard === profileCard.name
? alpha(rCard.color || theme.palette.primary.main, 0.08) ? alpha(profileCard.color || theme.palette.primary.main, 0.08)
: 'background.paper', : 'background.paper',
'&:hover': { '&:hover': {
borderColor: rCard.color, borderColor: profileCard.color,
transform: 'translateY(-2px)', transform: 'translateY(-2px)',
boxShadow: theme.shadows[4], boxShadow: theme.shadows[4],
}, },
@ -221,7 +223,7 @@ const GroupJoinPage = () => {
<CardContent sx={{ p: 3, textAlign: 'center' }}> <CardContent sx={{ p: 3, textAlign: 'center' }}>
<Avatar <Avatar
sx={{ sx={{
bgcolor: rCard.color || theme.palette.primary.main, bgcolor: profileCard.color || theme.palette.primary.main,
width: 48, width: 48,
height: 48, height: 48,
mx: 'auto', mx: 'auto',
@ -229,21 +231,21 @@ const GroupJoinPage = () => {
'& .MuiSvgIcon-root': { fontSize: 28 } '& .MuiSvgIcon-root': { fontSize: 28 }
}} }}
> >
{getRCardIcon(rCard.icon || 'PersonOutline')} {getProfileCardIcon(profileCard.icon || 'PersonOutline')}
</Avatar> </Avatar>
<Typography variant="h6" sx={{ fontWeight: 600, mb: 1 }}> <Typography variant="h6" sx={{ fontWeight: 600, mb: 1 }}>
{rCard.name} {profileCard.name}
</Typography> </Typography>
<Typography variant="body2" color="text.secondary" sx={{ fontSize: '0.875rem' }}> <Typography variant="body2" color="text.secondary" sx={{ fontSize: '0.875rem' }}>
{rCard.description} {profileCard.description}
</Typography> </Typography>
{selectedRCard === rCard.name && ( {selectedProfileCard === profileCard.name && (
<CheckCircle <CheckCircle
sx={{ sx={{
color: rCard.color, color: profileCard.color,
mt: 1, mt: 1,
fontSize: 20 fontSize: 20
}} }}
@ -261,7 +263,7 @@ const GroupJoinPage = () => {
variant="contained" variant="contained"
size="large" size="large"
onClick={handleJoinGroup} onClick={handleJoinGroup}
disabled={!selectedRCard} disabled={!selectedProfileCard}
sx={{ sx={{
px: 4, px: 4,
py: 1.5, py: 1.5,

@ -1,4 +1,4 @@
export interface RCard { export interface ProfileCard {
id: string; id: string;
name: string; name: string;
description?: string; description?: string;
@ -9,6 +9,9 @@ export interface RCard {
updatedAt: Date; updatedAt: Date;
} }
// Legacy alias for backwards compatibility
export interface RCard extends ProfileCard {}
export interface Vouch { export interface Vouch {
id: string; id: string;
fromUserId: string; fromUserId: string;
@ -63,7 +66,8 @@ export interface Notification {
praiseId?: string; praiseId?: string;
groupId?: string; groupId?: string;
messageId?: string; messageId?: string;
rCardId?: string; profileCardId?: string;
rCardId?: string; // Legacy alias
}; };
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
@ -73,7 +77,8 @@ export interface VouchNotification extends Notification {
type: 'vouch'; type: 'vouch';
metadata: { metadata: {
vouchId: string; vouchId: string;
rCardId?: string; profileCardId?: string;
rCardId?: string; // Legacy alias
}; };
} }
@ -81,7 +86,8 @@ export interface PraiseNotification extends Notification {
type: 'praise'; type: 'praise';
metadata: { metadata: {
praiseId: string; praiseId: string;
rCardId?: string; profileCardId?: string;
rCardId?: string; // Legacy alias
}; };
} }
@ -119,13 +125,17 @@ export interface PrivacySettings {
}; };
} }
export interface RCardWithPrivacy extends RCard { export interface ProfileCardWithPrivacy extends ProfileCard {
privacySettings: PrivacySettings; privacySettings: PrivacySettings;
} }
// Legacy alias for backwards compatibility
export interface RCardWithPrivacy extends ProfileCardWithPrivacy {}
export interface ContactPrivacyOverride { export interface ContactPrivacyOverride {
contactId: string; contactId: string;
rCardId: string; profileCardId: string;
rCardId?: string; // Legacy alias
overrides: Partial<PrivacySettings>; overrides: Partial<PrivacySettings>;
createdAt: Date; createdAt: Date;
updatedAt: Date; updatedAt: Date;
@ -149,8 +159,8 @@ export const DEFAULT_PRIVACY_SETTINGS: PrivacySettings = {
}, },
}; };
// Default rCard categories // Default profile card categories
export const DEFAULT_RCARDS: Omit<RCard, 'id' | 'createdAt' | 'updatedAt'>[] = [ export const DEFAULT_PROFILE_CARDS: Omit<ProfileCard, 'id' | 'createdAt' | 'updatedAt'>[] = [
{ {
name: 'Business', name: 'Business',
description: 'Professional business contacts and partnerships', description: 'Professional business contacts and partnerships',
@ -207,4 +217,7 @@ export const DEFAULT_RCARDS: Omit<RCard, 'id' | 'createdAt' | 'updatedAt'>[] = [
icon: 'Public', icon: 'Public',
isDefault: true, isDefault: true,
}, },
]; ];
// Legacy alias for backwards compatibility
export const DEFAULT_RCARDS = DEFAULT_PROFILE_CARDS;
Loading…
Cancel
Save