add column for email expiry date
Members > Invite member says invite Staff in dialog resend email button Update form member form to say member and not staff review application function manual payment functionality basic implementation of theme actions dropdown
This commit is contained in:
172
src/components/ViewRegistrationDialog.js
Normal file
172
src/components/ViewRegistrationDialog.js
Normal file
@@ -0,0 +1,172 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from './ui/dialog';
|
||||
import { Button } from './ui/button';
|
||||
import { Card } from './ui/card';
|
||||
import { User, Mail, Phone, Calendar, UserCheck, Clock, FileText } from 'lucide-react';
|
||||
import StatusBadge from './StatusBadge';
|
||||
|
||||
const ViewRegistrationDialog = ({ open, onOpenChange, user }) => {
|
||||
if (!user) return null;
|
||||
|
||||
const formatDate = (dateString) => {
|
||||
if (!dateString) return '—';
|
||||
return new Date(dateString).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
});
|
||||
};
|
||||
|
||||
const formatDateTime = (dateString) => {
|
||||
if (!dateString) return '—';
|
||||
return new Date(dateString).toLocaleString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
const formatPhoneNumber = (phone) => {
|
||||
if (!phone) return '—';
|
||||
const cleaned = phone.replace(/\D/g, '');
|
||||
if (cleaned.length === 10) {
|
||||
return `(${cleaned.slice(0, 3)}) ${cleaned.slice(3, 6)}-${cleaned.slice(6)}`;
|
||||
}
|
||||
return phone;
|
||||
};
|
||||
|
||||
const InfoRow = ({ icon: Icon, label, value }) => (
|
||||
<div className="flex items-start gap-3 py-3 border-b border-[var(--neutral-800)] last:border-b-0">
|
||||
<div className="h-10 w-10 rounded-lg bg-[var(--lavender-400)] flex items-center justify-center flex-shrink-0">
|
||||
<Icon className="h-5 w-5 text-brand-purple" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-sm text-brand-purple" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
{label}
|
||||
</p>
|
||||
<p className="font-medium text-[var(--purple-ink)] break-words" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
{value || '—'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[600px] rounded-2xl max-h-[90vh] overflow-y-auto scrollbar-dashboard">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-2xl text-[var(--purple-ink)] flex items-center gap-2" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
<FileText className="h-6 w-6" />
|
||||
Registration Details
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-brand-purple" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
View the registration information for this member application.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="py-4 space-y-4">
|
||||
{/* User Header Card */}
|
||||
<Card className="p-4 bg-[var(--lavender-400)] border-2 border-[var(--neutral-800)] rounded-xl">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="h-16 w-16 rounded-full bg-[var(--neutral-800)]/20 flex items-center justify-center">
|
||||
<User className="h-8 w-8 text-brand-purple" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-xl font-semibold text-[var(--purple-ink)]" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
{user.first_name} {user.last_name}
|
||||
</p>
|
||||
<p className="text-sm text-brand-purple" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
{user.email}
|
||||
</p>
|
||||
<div className="mt-2">
|
||||
<StatusBadge status={user.status} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Contact Information */}
|
||||
<Card className="p-4 border border-[var(--neutral-800)] rounded-xl">
|
||||
<h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Contact Information
|
||||
</h3>
|
||||
<InfoRow icon={Mail} label="Email Address" value={user.email} />
|
||||
<InfoRow icon={Phone} label="Phone Number" value={formatPhoneNumber(user.phone)} />
|
||||
</Card>
|
||||
|
||||
{/* Registration Details */}
|
||||
<Card className="p-4 border border-[var(--neutral-800)] rounded-xl">
|
||||
<h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Registration Details
|
||||
</h3>
|
||||
<InfoRow icon={Calendar} label="Registration Date" value={formatDate(user.created_at)} />
|
||||
<InfoRow icon={UserCheck} label="Referred By" value={user.referred_by_member_name} />
|
||||
<InfoRow icon={Clock} label="Email Verification Expires" value={formatDateTime(user.email_verification_expires_at)} />
|
||||
</Card>
|
||||
|
||||
{/* Additional Information (if available) */}
|
||||
{(user.address || user.city || user.state || user.zip_code) && (
|
||||
<Card className="p-4 border border-[var(--neutral-800)] rounded-xl">
|
||||
<h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Address
|
||||
</h3>
|
||||
<div className="text-[var(--purple-ink)]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
{user.address && <p>{user.address}</p>}
|
||||
{(user.city || user.state || user.zip_code) && (
|
||||
<p>
|
||||
{[user.city, user.state, user.zip_code].filter(Boolean).join(', ')}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Notes (if available) */}
|
||||
{user.notes && (
|
||||
<Card className="p-4 border border-[var(--neutral-800)] rounded-xl">
|
||||
<h3 className="text-lg font-semibold text-[var(--purple-ink)] mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Notes
|
||||
</h3>
|
||||
<p className="text-[var(--purple-ink)]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
{user.notes}
|
||||
</p>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Rejection Reason (if rejected) */}
|
||||
{user.status === 'rejected' && user.rejection_reason && (
|
||||
<Card className="p-4 border border-red-300 bg-red-50 dark:bg-red-500/10 rounded-xl">
|
||||
<h3 className="text-lg font-semibold text-red-600 mb-3" style={{ fontFamily: "'Inter', sans-serif" }}>
|
||||
Rejection Reason
|
||||
</h3>
|
||||
<p className="text-red-600" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
|
||||
{user.rejection_reason}
|
||||
</p>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => onOpenChange(false)}
|
||||
className="rounded-xl bg-[var(--purple-ink)] hover:bg-[var(--purple-ink)]/90 text-white"
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default ViewRegistrationDialog;
|
||||
Reference in New Issue
Block a user