Refactor Members Directory and Newsletter Archive styles to use new color palette

- Updated color classes in MembersDirectory.js to use new color variables for borders, backgrounds, and text.
- Enhanced visual consistency by replacing hardcoded colors with Tailwind CSS color utilities.
- Modified NewsletterArchive.js to align with the new design system, ensuring a cohesive look across components.
- Added new color variables in tailwind.config.js for better maintainability and scalability.
This commit is contained in:
2026-01-07 11:36:07 -06:00
parent a93e2aa863
commit 4ba44d8997
79 changed files with 2152 additions and 2033 deletions

View File

@@ -277,7 +277,7 @@ Proceed with activation?`;
if (loading) {
return (
<div className="flex items-center justify-center min-h-screen">
<Loader2 className="h-12 w-12 animate-spin text-[#664fa3]" />
<Loader2 className="h-12 w-12 animate-spin text-muted-foreground" />
</div>
);
}
@@ -286,36 +286,36 @@ Proceed with activation?`;
<div className="space-y-8">
{/* Header */}
<div>
<h1 className="text-3xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<h1 className="text-3xl font-semibold text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
Subscription Management
</h1>
<p className="text-[#664fa3] mt-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-muted-foreground mt-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
View and manage all member subscriptions
</p>
</div>
{/* Stats Cards */}
<div className="grid md:grid-cols-4 gap-6">
<Card className="p-6 bg-white rounded-2xl border-2 border-[#ddd8eb]">
<Card className="p-6 bg-background rounded-2xl border-2 border-chart-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Total Subscriptions
</p>
<p className="text-3xl font-bold text-[#422268] mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
<p className="text-3xl font-bold text-primary mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
{stats.total || 0}
</p>
</div>
<div className="p-3 bg-[#DDD8EB]/20 rounded-full">
<CreditCard className="h-6 w-6 text-[#664fa3]" />
<div className="p-3 bg-chart-6/20 rounded-full">
<CreditCard className="h-6 w-6 text-muted-foreground" />
</div>
</div>
</Card>
<Card className="p-6 bg-white rounded-2xl border-2 border-[#ddd8eb]">
<Card className="p-6 bg-background rounded-2xl border-2 border-chart-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Active Members
</p>
<p className="text-3xl font-bold text-[#81B29A] mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
@@ -328,51 +328,51 @@ Proceed with activation?`;
</div>
</Card>
<Card className="p-6 bg-white rounded-2xl border-2 border-[#ddd8eb]">
<Card className="p-6 bg-background rounded-2xl border-2 border-chart-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Total Revenue
</p>
<p className="text-3xl font-bold text-[#422268] mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
<p className="text-3xl font-bold text-primary mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
{formatPrice(stats.total_revenue || 0)}
</p>
</div>
<div className="p-3 bg-[#DDD8EB]/20 rounded-full">
<DollarSign className="h-6 w-6 text-[#664fa3]" />
<div className="p-3 bg-chart-6/20 rounded-full">
<DollarSign className="h-6 w-6 text-muted-foreground" />
</div>
</div>
</Card>
<Card className="p-6 bg-white rounded-2xl border-2 border-[#ddd8eb]">
<Card className="p-6 bg-background rounded-2xl border-2 border-chart-6">
<div className="flex items-center justify-between">
<div>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Total Donations
</p>
<p className="text-3xl font-bold text-[#ff9e77] mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
<p className="text-3xl font-bold text-accent mt-2" style={{ fontFamily: "'Inter', sans-serif" }}>
{formatPrice(stats.total_donations || 0)}
</p>
</div>
<div className="p-3 bg-[#ff9e77]/10 rounded-full">
<Heart className="h-6 w-6 text-[#ff9e77]" />
<div className="p-3 bg-accent/10 rounded-full">
<Heart className="h-6 w-6 text-accent" />
</div>
</div>
</Card>
</div>
{/* Search & Filter Bar */}
<Card className="p-6 bg-white rounded-2xl border-2 border-[#ddd8eb]">
<Card className="p-6 bg-background rounded-2xl border-2 border-chart-6">
<div className="grid md:grid-cols-3 gap-4">
{/* Search */}
<div className="md:col-span-1">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-[#664fa3]" />
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-muted-foreground" />
<Input
placeholder="Search by name or email..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="pl-10 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
className="pl-10 rounded-xl border-2 border-chart-6 focus:border-muted-foreground"
/>
</div>
</div>
@@ -380,7 +380,7 @@ Proceed with activation?`;
{/* Status Filter */}
<div>
<Select value={statusFilter} onValueChange={setStatusFilter}>
<SelectTrigger className="rounded-xl border-2 border-[#ddd8eb]">
<SelectTrigger className="rounded-xl border-2 border-chart-6">
<SelectValue placeholder="All Statuses" />
</SelectTrigger>
<SelectContent>
@@ -395,7 +395,7 @@ Proceed with activation?`;
{/* Plan Filter */}
<div>
<Select value={planFilter} onValueChange={setPlanFilter}>
<SelectTrigger className="rounded-xl border-2 border-[#ddd8eb]">
<SelectTrigger className="rounded-xl border-2 border-chart-6">
<SelectValue placeholder="All Plans" />
</SelectTrigger>
<SelectContent>
@@ -409,7 +409,7 @@ Proceed with activation?`;
</div>
<div className="mt-4 flex items-center justify-between">
<div className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Showing {filteredSubscriptions.length} of {subscriptions.length} subscriptions
</div>
@@ -425,20 +425,20 @@ Proceed with activation?`;
{exporting ? 'Exporting...' : 'Export'}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56 bg-white rounded-xl border-2 border-[#ddd8eb] shadow-lg">
<DropdownMenuContent align="end" className="w-56 bg-background rounded-xl border-2 border-chart-6 shadow-lg">
<DropdownMenuItem
onClick={() => handleExport('all')}
className="cursor-pointer hover:bg-[#f1eef9] rounded-lg p-3"
className="cursor-pointer hover:bg-muted rounded-lg p-3"
>
<FileDown className="h-4 w-4 mr-2 text-[#664fa3]" />
<span className="text-[#422268]">Export All Subscriptions</span>
<FileDown className="h-4 w-4 mr-2 text-muted-foreground" />
<span className="text-primary">Export All Subscriptions</span>
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => handleExport('current')}
className="cursor-pointer hover:bg-[#f1eef9] rounded-lg p-3"
className="cursor-pointer hover:bg-muted rounded-lg p-3"
>
<FileDown className="h-4 w-4 mr-2 text-[#664fa3]" />
<span className="text-[#422268]">Export Current View</span>
<FileDown className="h-4 w-4 mr-2 text-muted-foreground" />
<span className="text-primary">Export Current View</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
@@ -447,20 +447,20 @@ Proceed with activation?`;
</Card>
{/* Subscriptions Table */}
<Card className="bg-white rounded-2xl border-2 border-[#ddd8eb] overflow-hidden">
<Card className="bg-background rounded-2xl border-2 border-chart-6 overflow-hidden">
{/* Mobile Card View */}
<div className="md:hidden p-4 space-y-4">
{filteredSubscriptions.length > 0 ? (
filteredSubscriptions.map((sub) => (
<Card key={sub.id} className="p-4 border border-[#ddd8eb] bg-[#f9f5ff]/30">
<Card key={sub.id} className="p-4 border border-chart-6 bg-[#f9f5ff]/30">
<div className="space-y-3">
{/* Member Info */}
<div className="flex justify-between items-start border-b border-[#ddd8eb] pb-3">
<div className="flex justify-between items-start border-b border-chart-6 pb-3">
<div className="flex-1">
<p className="font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<p className="font-semibold text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
{sub.user.first_name} {sub.user.last_name}
</p>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<p className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{sub.user.email}
</p>
</div>
@@ -470,13 +470,13 @@ Proceed with activation?`;
{/* Plan & Period */}
<div className="grid grid-cols-2 gap-3 text-sm">
<div>
<p className="text-xs text-[#664fa3] mb-1">Plan</p>
<p className="font-medium text-[#422268]">{sub.plan.name}</p>
<p className="text-xs text-[#664fa3]">{sub.plan.billing_cycle}</p>
<p className="text-xs text-muted-foreground mb-1">Plan</p>
<p className="font-medium text-primary">{sub.plan.name}</p>
<p className="text-xs text-muted-foreground">{sub.plan.billing_cycle}</p>
</div>
<div>
<p className="text-xs text-[#664fa3] mb-1">Period</p>
<p className="text-[#422268]">
<p className="text-xs text-muted-foreground mb-1">Period</p>
<p className="text-primary">
{new Date(sub.current_period_start).toLocaleDateString()} -
{new Date(sub.current_period_end).toLocaleDateString()}
</p>
@@ -484,22 +484,22 @@ Proceed with activation?`;
</div>
{/* Pricing */}
<div className="grid grid-cols-3 gap-2 text-sm bg-white/50 p-3 rounded">
<div className="grid grid-cols-3 gap-2 text-sm bg-background/50 p-3 rounded">
<div>
<p className="text-xs text-[#664fa3] mb-1">Base Fee</p>
<p className="font-medium text-[#422268]">
<p className="text-xs text-muted-foreground mb-1">Base Fee</p>
<p className="font-medium text-primary">
${(sub.base_fee_cents / 100).toFixed(2)}
</p>
</div>
<div>
<p className="text-xs text-[#664fa3] mb-1">Donation</p>
<p className="font-medium text-[#422268]">
<p className="text-xs text-muted-foreground mb-1">Donation</p>
<p className="font-medium text-primary">
${(sub.donation_cents / 100).toFixed(2)}
</p>
</div>
<div>
<p className="text-xs text-[#664fa3] mb-1">Total</p>
<p className="font-semibold text-[#422268]">
<p className="text-xs text-muted-foreground mb-1">Total</p>
<p className="font-semibold text-primary">
${(sub.total_cents / 100).toFixed(2)}
</p>
</div>
@@ -512,7 +512,7 @@ Proceed with activation?`;
size="sm"
variant="outline"
onClick={() => handleEdit(sub)}
className="flex-1 text-[#664fa3] hover:bg-[#DDD8EB]"
className="flex-1 text-muted-foreground hover:bg-chart-6"
>
<Edit className="h-4 w-4 mr-2" />
Edit
@@ -534,7 +534,7 @@ Proceed with activation?`;
</Card>
))
) : (
<div className="p-12 text-center text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div className="p-12 text-center text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
No subscriptions found
</div>
)}
@@ -544,29 +544,29 @@ Proceed with activation?`;
<div className="hidden md:block overflow-x-auto">
<table className="w-full">
<thead>
<tr className="bg-[#DDD8EB]/20 border-b border-[#ddd8eb]">
<th className="text-left p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<tr className="bg-chart-6/20 border-b border-chart-6">
<th className="text-left p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Member
</th>
<th className="text-left p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-left p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Plan
</th>
<th className="text-left p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-left p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Status
</th>
<th className="text-left p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-left p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Period
</th>
<th className="text-right p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-right p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Base Fee
</th>
<th className="text-right p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-right p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Donation
</th>
<th className="text-right p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-right p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Total
</th>
<th className="text-center p-4 text-[#422268] font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
<th className="text-center p-4 text-primary font-semibold" style={{ fontFamily: "'Inter', sans-serif" }}>
Actions
</th>
</tr>
@@ -574,20 +574,20 @@ Proceed with activation?`;
<tbody>
{filteredSubscriptions.length > 0 ? (
filteredSubscriptions.map((sub) => (
<tr key={sub.id} className="border-b border-[#ddd8eb] hover:bg-[#f9f5ff] transition-colors">
<tr key={sub.id} className="border-b border-chart-6 hover:bg-[#f9f5ff] transition-colors">
<td className="p-4">
<div className="font-medium text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<div className="font-medium text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
{sub.user.first_name} {sub.user.last_name}
</div>
<div className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div className="text-sm text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{sub.user.email}
</div>
</td>
<td className="p-4">
<div className="text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div className="text-primary" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{sub.plan.name}
</div>
<div className="text-xs text-[#664fa3]">
<div className="text-xs text-muted-foreground">
{sub.plan.billing_cycle}
</div>
</td>
@@ -597,18 +597,18 @@ Proceed with activation?`;
</Badge>
</td>
<td className="p-4">
<div className="text-sm text-[#422268]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div className="text-sm text-primary" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<div>{formatDate(sub.start_date)}</div>
<div className="text-xs text-[#664fa3]">to {formatDate(sub.end_date)}</div>
<div className="text-xs text-muted-foreground">to {formatDate(sub.end_date)}</div>
</div>
</td>
<td className="p-4 text-right text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<td className="p-4 text-right text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
{formatPrice(sub.base_subscription_cents || 0)}
</td>
<td className="p-4 text-right text-[#ff9e77]" style={{ fontFamily: "'Inter', sans-serif" }}>
<td className="p-4 text-right text-accent" style={{ fontFamily: "'Inter', sans-serif" }}>
{formatPrice(sub.donation_cents || 0)}
</td>
<td className="p-4 text-right font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<td className="p-4 text-right font-semibold text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
{formatPrice(sub.amount_paid_cents || 0)}
</td>
<td className="p-4">
@@ -618,7 +618,7 @@ Proceed with activation?`;
size="sm"
variant="outline"
onClick={() => handleEdit(sub)}
className="text-[#664fa3] hover:bg-[#DDD8EB]"
className="text-muted-foreground hover:bg-chart-6"
>
<Edit className="h-4 w-4" />
</Button>
@@ -639,7 +639,7 @@ Proceed with activation?`;
))
) : (
<tr>
<td colSpan="8" className="p-12 text-center text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<td colSpan="8" className="p-12 text-center text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
No subscriptions found
</td>
</tr>
@@ -651,12 +651,12 @@ Proceed with activation?`;
{/* Edit Subscription Dialog */}
<Dialog open={editDialogOpen} onOpenChange={setEditDialogOpen}>
<DialogContent className="sm:max-w-[500px] bg-white rounded-2xl">
<DialogContent className="sm:max-w-[500px] bg-background rounded-2xl">
<DialogHeader>
<DialogTitle className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
<DialogTitle className="text-2xl font-semibold text-primary" style={{ fontFamily: "'Inter', sans-serif" }}>
Edit Subscription
</DialogTitle>
<DialogDescription className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
<DialogDescription className="text-muted-foreground" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Update subscription status or end date for {selectedSubscription?.user.first_name} {selectedSubscription?.user.last_name}
</DialogDescription>
</DialogHeader>
@@ -664,14 +664,14 @@ Proceed with activation?`;
<div className="space-y-6 py-4">
{/* Status */}
<div className="space-y-2">
<Label htmlFor="status" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
<Label htmlFor="status" className="text-primary font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Status
</Label>
<Select
value={editFormData.status}
onValueChange={(value) => setEditFormData({ ...editFormData, status: value })}
>
<SelectTrigger className="rounded-xl border-2 border-[#ddd8eb]">
<SelectTrigger className="rounded-xl border-2 border-chart-6">
<SelectValue placeholder="Select status" />
</SelectTrigger>
<SelectContent>
@@ -683,13 +683,12 @@ Proceed with activation?`;
{/* Warning Box - Show when status is different */}
{selectedSubscription && editFormData.status !== selectedSubscription.status && (
<div className={`mt-3 p-4 rounded-xl border-2 ${
editFormData.status === 'cancelled'
? 'bg-red-50 border-red-300'
: editFormData.status === 'expired'
<div className={`mt-3 p-4 rounded-xl border-2 ${editFormData.status === 'cancelled'
? 'bg-red-50 border-red-300'
: editFormData.status === 'expired'
? 'bg-orange-50 border-orange-300'
: 'bg-green-50 border-green-300'
}`}>
}`}>
<div className="flex items-start gap-3">
{editFormData.status === 'cancelled' || editFormData.status === 'expired' ? (
<AlertTriangle className="h-5 w-5 text-red-600 flex-shrink-0 mt-0.5" />
@@ -737,17 +736,17 @@ Proceed with activation?`;
{/* End Date */}
<div className="space-y-2">
<Label htmlFor="end_date" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
<Label htmlFor="end_date" className="text-primary font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
End Date
</Label>
<div className="relative">
<Calendar className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-[#664fa3]" />
<Calendar className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-muted-foreground" />
<Input
id="end_date"
type="date"
value={editFormData.end_date}
onChange={(e) => setEditFormData({ ...editFormData, end_date: e.target.value })}
className="pl-12 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
className="pl-12 rounded-xl border-2 border-chart-6 focus:border-muted-foreground"
/>
</div>
</div>
@@ -758,7 +757,7 @@ Proceed with activation?`;
type="button"
variant="outline"
onClick={() => setEditDialogOpen(false)}
className="rounded-full border-2 border-[#ddd8eb]"
className="rounded-full border-2 border-chart-6"
disabled={isUpdating}
>
Cancel