Update FE

This commit is contained in:
Koncept Kit
2025-12-08 20:45:40 +07:00
parent d8c1e133ac
commit 1f27c3224b
23 changed files with 438 additions and 438 deletions

View File

@@ -116,7 +116,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
{/* Sidebar */}
<aside
className={`
bg-white border-r border-[#EAE0D5] transition-all duration-300 ease-out
bg-white border-r border-[#ddd8eb] transition-all duration-300 ease-out
${isMobile ? 'fixed inset-y-0 left-0 z-40' : 'relative'}
${isOpen ? 'w-64' : 'w-16'}
${isMobile && !isOpen ? '-translate-x-full' : 'translate-x-0'}
@@ -124,23 +124,23 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
`}
>
{/* Header */}
<div className="flex items-center justify-between p-4 border-b border-[#EAE0D5]">
<div className="flex items-center justify-between p-4 border-b border-[#ddd8eb]">
{isOpen && (
<h2 className="text-xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Admin
</h2>
)}
<button
onClick={onToggle}
className="p-2 rounded-lg hover:bg-[#F2CC8F]/20 transition-colors ml-auto"
className="p-2 rounded-lg hover:bg-[#DDD8EB]/20 transition-colors ml-auto"
aria-label={isOpen ? 'Collapse sidebar' : 'Expand sidebar'}
>
{isMobile ? (
<Menu className="h-5 w-5 text-[#3D405B]" />
<Menu className="h-5 w-5 text-[#422268]" />
) : isOpen ? (
<ChevronLeft className="h-5 w-5 text-[#3D405B]" />
<ChevronLeft className="h-5 w-5 text-[#422268]" />
) : (
<ChevronRight className="h-5 w-5 text-[#3D405B]" />
<ChevronRight className="h-5 w-5 text-[#422268]" />
)}
</button>
</div>
@@ -163,16 +163,16 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
className={`
flex items-center gap-3 px-4 py-3 rounded-lg transition-all relative
${item.disabled
? 'opacity-50 cursor-not-allowed text-[#6B708D]'
? 'opacity-50 cursor-not-allowed text-[#664fa3]'
: active
? 'bg-[#E07A5F]/10 text-[#E07A5F]'
: 'text-[#3D405B] hover:bg-[#F2CC8F]/20'
? 'bg-[#ff9e77]/10 text-[#ff9e77]'
: 'text-[#422268] hover:bg-[#DDD8EB]/20'
}
`}
>
{/* Active border */}
{active && !item.disabled && (
<div className="absolute left-0 top-0 bottom-0 w-1 bg-[#E07A5F] rounded-r" />
<div className="absolute left-0 top-0 bottom-0 w-1 bg-[#ff9e77] rounded-r" />
)}
<Icon className="h-5 w-5 flex-shrink-0" />
@@ -181,12 +181,12 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
<>
<span className="flex-1">{item.name}</span>
{item.disabled && (
<Badge className="bg-[#F2CC8F] text-[#3D405B] text-xs px-2 py-0.5">
<Badge className="bg-[#DDD8EB] text-[#422268] text-xs px-2 py-0.5">
Soon
</Badge>
)}
{item.badge > 0 && !item.disabled && (
<Badge className="bg-[#E07A5F] text-white text-xs px-2 py-0.5">
<Badge className="bg-[#ff9e77] text-white text-xs px-2 py-0.5">
{item.badge}
</Badge>
)}
@@ -195,7 +195,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
{/* Badge when collapsed */}
{!isOpen && item.badge > 0 && !item.disabled && (
<div className="absolute -top-1 -right-1 bg-[#E07A5F] text-white text-xs rounded-full h-5 w-5 flex items-center justify-center font-medium">
<div className="absolute -top-1 -right-1 bg-[#ff9e77] text-white text-xs rounded-full h-5 w-5 flex items-center justify-center font-medium">
{item.badge}
</div>
)}
@@ -203,7 +203,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
{/* Tooltip when collapsed */}
{!isOpen && (
<div className="absolute left-full ml-2 top-1/2 -translate-y-1/2 px-3 py-2 bg-[#3D405B] text-white text-sm rounded-lg opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity whitespace-nowrap z-50">
<div className="absolute left-full ml-2 top-1/2 -translate-y-1/2 px-3 py-2 bg-[#422268] text-white text-sm rounded-lg opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity whitespace-nowrap z-50">
{item.name}
{item.badge > 0 && ` (${item.badge})`}
</div>
@@ -214,18 +214,18 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
</nav>
{/* User Section */}
<div className="border-t border-[#EAE0D5] p-4 space-y-2">
<div className="border-t border-[#ddd8eb] p-4 space-y-2">
{isOpen && user && (
<div className="px-4 py-3 mb-2">
<div className="flex items-center gap-3">
<div className="h-10 w-10 rounded-full bg-[#F2CC8F] flex items-center justify-center text-[#3D405B] font-semibold">
<div className="h-10 w-10 rounded-full bg-[#DDD8EB] flex items-center justify-center text-[#422268] font-semibold">
{user.first_name?.[0]}{user.last_name?.[0]}
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-[#3D405B] truncate">
<p className="text-sm font-medium text-[#422268] truncate" style={{ fontFamily: "'Inter', sans-serif" }}>
{user.first_name} {user.last_name}
</p>
<p className="text-xs text-[#6B708D] capitalize truncate">
<p className="text-xs text-[#664fa3] capitalize truncate" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{user.role}
</p>
</div>
@@ -238,7 +238,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
onClick={handleLogout}
className={`
flex items-center gap-3 px-4 py-3 rounded-lg w-full
text-[#E07A5F] hover:bg-[#E07A5F]/10 transition-colors
text-[#ff9e77] hover:bg-[#ff9e77]/10 transition-colors
${!isOpen && 'justify-center'}
`}
>
@@ -249,7 +249,7 @@ const AdminSidebar = ({ isOpen, onToggle, isMobile }) => {
{/* Logout tooltip when collapsed */}
{!isOpen && (
<div className="relative group">
<div className="absolute left-full ml-2 bottom-0 px-3 py-2 bg-[#3D405B] text-white text-sm rounded-lg opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity whitespace-nowrap z-50">
<div className="absolute left-full ml-2 bottom-0 px-3 py-2 bg-[#422268] text-white text-sm rounded-lg opacity-0 group-hover:opacity-100 pointer-events-none transition-opacity whitespace-nowrap z-50">
Logout
</div>
</div>

View File

@@ -57,19 +57,19 @@ export const AttendanceDialog = ({ event, open, onOpenChange, onSuccess }) => {
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto bg-white">
<DialogHeader>
<DialogTitle className="text-2xl fraunces text-[#3D405B]">
<DialogTitle className="text-2xl text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Mark Attendance: {event?.title}
</DialogTitle>
</DialogHeader>
<div className="space-y-4 mt-4">
{rsvps.length === 0 ? (
<p className="text-center text-[#6B708D] py-8">No RSVPs yet</p>
<p className="text-center text-[#664fa3] py-8" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>No RSVPs yet</p>
) : (
rsvps.map((rsvp) => (
<div
key={rsvp.user_id}
className="flex items-center gap-3 p-4 border-2 border-[#EAE0D5] rounded-xl hover:border-[#E07A5F] transition-colors"
className="flex items-center gap-3 p-4 border-2 border-[#ddd8eb] rounded-xl hover:border-[#664fa3] transition-colors"
>
<Checkbox
checked={attendance[rsvp.user_id] || false}
@@ -79,8 +79,8 @@ export const AttendanceDialog = ({ event, open, onOpenChange, onSuccess }) => {
className="w-5 h-5"
/>
<div className="flex-1">
<p className="font-medium text-[#3D405B]">{rsvp.user_name}</p>
<p className="text-sm text-[#6B708D]">{rsvp.user_email}</p>
<p className="font-medium text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>{rsvp.user_name}</p>
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>{rsvp.user_email}</p>
</div>
{rsvp.attended && (
<span className="text-sm text-[#81B29A] font-medium">
@@ -96,14 +96,14 @@ export const AttendanceDialog = ({ event, open, onOpenChange, onSuccess }) => {
<Button
onClick={handleSave}
disabled={loading}
className="flex-1 bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full"
className="flex-1 bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full"
>
{loading ? 'Saving...' : 'Save Attendance'}
</Button>
<Button
onClick={() => onOpenChange(false)}
variant="outline"
className="flex-1 border-2 border-[#6B708D] text-[#6B708D] hover:bg-[#6B708D] hover:text-white rounded-full"
className="flex-1 border-2 border-[#ddd8eb] text-[#664fa3] hover:bg-white hover:text-[#422268] rounded-full"
>
Cancel
</Button>

View File

@@ -69,14 +69,14 @@ const ChangePasswordDialog = ({ open, onOpenChange }) => {
<DialogContent className="sm:max-w-md bg-white">
<DialogHeader>
<div className="flex items-center gap-2 mb-2">
<div className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-[#FFF3E0]">
<Lock className="h-5 w-5 text-[#E07A5F]" />
<div className="inline-flex items-center justify-center w-10 h-10 rounded-full bg-[#f1eef9]">
<Lock className="h-5 w-5 text-[#ff9e77]" />
</div>
<DialogTitle className="text-2xl font-semibold text-[#3D405B]">
<DialogTitle className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Change Password
</DialogTitle>
</div>
<DialogDescription className="text-[#6B708D]">
<DialogDescription className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Update your password to keep your account secure.
</DialogDescription>
</DialogHeader>
@@ -92,7 +92,7 @@ const ChangePasswordDialog = ({ open, onOpenChange }) => {
value={formData.currentPassword}
onChange={handleInputChange}
placeholder="Enter current password"
className="h-12 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-12 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -106,7 +106,7 @@ const ChangePasswordDialog = ({ open, onOpenChange }) => {
value={formData.newPassword}
onChange={handleInputChange}
placeholder="Enter new password (min. 6 characters)"
className="h-12 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-12 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -120,7 +120,7 @@ const ChangePasswordDialog = ({ open, onOpenChange }) => {
value={formData.confirmPassword}
onChange={handleInputChange}
placeholder="Re-enter new password"
className="h-12 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-12 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -136,7 +136,7 @@ const ChangePasswordDialog = ({ open, onOpenChange }) => {
<Button
type="submit"
disabled={loading}
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-6 disabled:opacity-50"
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6 disabled:opacity-50"
>
{loading ? 'Changing...' : 'Change Password'}
</Button>

View File

@@ -14,12 +14,12 @@ const Navbar = () => {
};
return (
<nav className="bg-white border-b border-[#EAE0D5] sticky top-0 z-50 backdrop-blur-sm bg-white/90">
<nav className="bg-white border-b border-[#ddd8eb] sticky top-0 z-50 backdrop-blur-sm bg-white/90">
<div className="max-w-7xl mx-auto px-6 py-4">
<div className="flex justify-between items-center">
<Link to={user ? "/dashboard" : "/"} className="flex items-center gap-2">
<Users className="h-8 w-8 text-[#E07A5F]" strokeWidth={1.5} />
<span className="text-2xl font-semibold fraunces text-[#3D405B]">Membership</span>
<Users className="h-8 w-8 text-[#ff9e77]" strokeWidth={1.5} />
<span className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>Membership</span>
</Link>
<div className="flex items-center gap-4">
@@ -29,7 +29,7 @@ const Navbar = () => {
<Link to="/admin">
<Button
variant="ghost"
className="text-[#3D405B] hover:text-[#E07A5F] hover:bg-[#F2CC8F]/10"
className="text-[#422268] hover:text-[#ff9e77] hover:bg-[#DDD8EB]/10"
data-testid="admin-nav-button"
>
<LayoutDashboard className="h-4 w-4 mr-2" />
@@ -40,7 +40,7 @@ const Navbar = () => {
<Link to="/events">
<Button
variant="ghost"
className="text-[#3D405B] hover:text-[#E07A5F] hover:bg-[#F2CC8F]/10"
className="text-[#422268] hover:text-[#ff9e77] hover:bg-[#DDD8EB]/10"
data-testid="events-nav-button"
>
Events
@@ -49,7 +49,7 @@ const Navbar = () => {
<Link to="/profile">
<Button
variant="ghost"
className="text-[#3D405B] hover:text-[#E07A5F] hover:bg-[#F2CC8F]/10"
className="text-[#422268] hover:text-[#ff9e77] hover:bg-[#DDD8EB]/10"
data-testid="profile-nav-button"
>
Profile
@@ -57,7 +57,7 @@ const Navbar = () => {
</Link>
<Button
onClick={handleLogout}
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-6"
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6"
data-testid="logout-button"
>
<LogOut className="h-4 w-4 mr-2" />
@@ -69,7 +69,7 @@ const Navbar = () => {
<Link to="/login">
<Button
variant="ghost"
className="text-[#3D405B] hover:text-[#E07A5F] hover:bg-[#F2CC8F]/10"
className="text-[#422268] hover:text-[#ff9e77] hover:bg-[#DDD8EB]/10"
data-testid="login-nav-button"
>
Login
@@ -77,7 +77,7 @@ const Navbar = () => {
</Link>
<Link to="/register">
<Button
className="bg-[#E07A5F] text-white hover:bg-[#D0694E] rounded-full px-6"
className="bg-[#DDD8EB] text-[#422268] hover:bg-white rounded-full px-6"
data-testid="register-nav-button"
>
Join Us

View File

@@ -126,10 +126,10 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[600px] bg-white rounded-2xl">
<DialogHeader>
<DialogTitle className="text-2xl font-semibold fraunces text-[#3D405B]">
<DialogTitle className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Activate Manual Payment
</DialogTitle>
<DialogDescription className="text-[#6B708D]">
<DialogDescription className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Record offline payment for {user.first_name} {user.last_name} ({user.email})
</DialogDescription>
</DialogHeader>
@@ -137,7 +137,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
<form onSubmit={handleSubmit} className="space-y-6 py-4">
{/* Subscription Plan Selection */}
<div className="space-y-2">
<Label htmlFor="plan_id" className="text-[#3D405B] font-medium">
<Label htmlFor="plan_id" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Subscription Plan
</Label>
<Select
@@ -152,7 +152,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
});
}}
>
<SelectTrigger className="rounded-xl border-2 border-[#EAE0D5]">
<SelectTrigger className="rounded-xl border-2 border-[#ddd8eb]">
<SelectValue placeholder="Select subscription plan" />
</SelectTrigger>
<SelectContent>
@@ -164,7 +164,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
</SelectContent>
</Select>
{selectedPlan && (
<p className="text-xs text-[#6B708D]">
<p className="text-xs text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{selectedPlan.description || `${selectedPlan.billing_cycle} subscription`}
</p>
)}
@@ -172,7 +172,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
{/* Payment Amount */}
<div className="space-y-2">
<Label htmlFor="amount" className="text-[#3D405B] font-medium">
<Label htmlFor="amount" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Payment Amount ($)
</Label>
<Input
@@ -183,27 +183,27 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
placeholder="Enter amount"
value={formData.amount}
onChange={(e) => setFormData({...formData, amount: e.target.value})}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
required
/>
<p className="text-xs text-[#6B708D]">
<p className="text-xs text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Amount can differ from plan price if offering a discount or partial payment
</p>
</div>
{/* Payment Date */}
<div className="space-y-2">
<Label htmlFor="payment_date" className="text-[#3D405B] font-medium">
<Label htmlFor="payment_date" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Payment Date
</Label>
<div className="relative">
<Calendar className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-[#6B708D]" />
<Calendar className="absolute left-4 top-1/2 transform -translate-y-1/2 h-5 w-5 text-[#664fa3]" />
<Input
id="payment_date"
type="date"
value={formData.payment_date}
onChange={(e) => setFormData({...formData, payment_date: e.target.value})}
className="pl-12 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="pl-12 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
required
/>
</div>
@@ -211,14 +211,14 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
{/* Payment Method */}
<div className="space-y-2">
<Label htmlFor="payment_method" className="text-[#3D405B] font-medium">
<Label htmlFor="payment_method" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Payment Method
</Label>
<Select
value={formData.payment_method}
onValueChange={(value) => setFormData({...formData, payment_method: value})}
>
<SelectTrigger className="rounded-xl border-2 border-[#EAE0D5]">
<SelectTrigger className="rounded-xl border-2 border-[#ddd8eb]">
<SelectValue placeholder="Select payment method" />
</SelectTrigger>
<SelectContent>
@@ -232,7 +232,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
{/* Subscription Period */}
<div className="space-y-3">
<Label className="text-[#3D405B] font-medium">Subscription Period</Label>
<Label className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>Subscription Period</Label>
<div className="flex items-center gap-2">
<input
@@ -240,9 +240,9 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
id="use_custom_period"
checked={useCustomPeriod}
onChange={(e) => setUseCustomPeriod(e.target.checked)}
className="rounded border-[#EAE0D5]"
className="rounded border-[#ddd8eb]"
/>
<Label htmlFor="use_custom_period" className="text-sm text-[#6B708D] font-normal cursor-pointer">
<Label htmlFor="use_custom_period" className="text-sm text-[#664fa3] font-normal cursor-pointer" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Use custom dates instead of plan's billing cycle
</Label>
</div>
@@ -250,7 +250,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
{useCustomPeriod ? (
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="custom_period_start" className="text-sm text-[#3D405B]">
<Label htmlFor="custom_period_start" className="text-sm text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Start Date
</Label>
<Input
@@ -258,12 +258,12 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
type="date"
value={formData.custom_period_start}
onChange={(e) => setFormData({...formData, custom_period_start: e.target.value})}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
required={useCustomPeriod}
/>
</div>
<div className="space-y-2">
<Label htmlFor="custom_period_end" className="text-sm text-[#3D405B]">
<Label htmlFor="custom_period_end" className="text-sm text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
End Date
</Label>
<Input
@@ -271,14 +271,14 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
type="date"
value={formData.custom_period_end}
onChange={(e) => setFormData({...formData, custom_period_end: e.target.value})}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
required={useCustomPeriod}
/>
</div>
</div>
) : (
selectedPlan && (
<p className="text-sm text-[#6B708D] bg-[#F2CC8F]/10 p-3 rounded-lg">
<p className="text-sm text-[#664fa3] bg-[#f1eef9] p-3 rounded-lg" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Will use plan's billing cycle: <span className="font-medium">{selectedPlan.billing_cycle}</span>
<br />
Starts today, ends {selectedPlan.billing_cycle === 'monthly' ? '30 days' :
@@ -292,7 +292,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
{/* Notes */}
<div className="space-y-2">
<Label htmlFor="notes" className="text-[#3D405B] font-medium">
<Label htmlFor="notes" className="text-[#422268] font-medium" style={{ fontFamily: "'Inter', sans-serif" }}>
Notes (Optional)
</Label>
<Textarea
@@ -300,7 +300,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
placeholder="Additional notes about the payment..."
value={formData.notes}
onChange={(e) => setFormData({...formData, notes: e.target.value})}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F] min-h-[100px]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3] min-h-[100px]"
/>
</div>
@@ -309,7 +309,7 @@ const PaymentActivationDialog = ({ open, onOpenChange, user, onSuccess }) => {
type="button"
variant="outline"
onClick={() => onOpenChange(false)}
className="rounded-full border-2 border-[#EAE0D5]"
className="rounded-full border-2 border-[#ddd8eb]"
>
Cancel
</Button>

View File

@@ -94,10 +94,10 @@ const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => {
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[600px]">
<DialogHeader>
<DialogTitle className="fraunces text-2xl">
<DialogTitle className="text-2xl text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
{plan ? 'Edit Plan' : 'Create New Plan'}
</DialogTitle>
<DialogDescription>
<DialogDescription className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{plan ? 'Update plan details below' : 'Enter plan details to create a new subscription plan'}
</DialogDescription>
</DialogHeader>
@@ -175,7 +175,7 @@ const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => {
placeholder="price_xxxxxxxxxxxxx"
className="mt-2 font-mono text-sm"
/>
<p className="text-sm text-[#6B708D] mt-1">
<p className="text-sm text-[#664fa3] mt-1" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Optional. Leave empty for manual/test plans.
</p>
</div>
@@ -184,7 +184,7 @@ const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => {
<div className="flex items-center justify-between">
<div>
<Label htmlFor="active">Active Status</Label>
<p className="text-sm text-[#6B708D]">
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Inactive plans won't appear for new subscriptions
</p>
</div>
@@ -196,7 +196,7 @@ const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => {
onChange={(e) => setFormData({ ...formData, active: e.target.checked })}
className="sr-only peer"
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-[#E07A5F]/20 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#81B29A]"></div>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-[#664fa3]/20 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-[#81B29A]"></div>
</label>
</div>
@@ -212,7 +212,7 @@ const PlanDialog = ({ open, onOpenChange, plan, onSuccess }) => {
<Button
type="submit"
disabled={loading}
className="bg-[#E07A5F] hover:bg-[#D0694E]"
className="bg-[#DDD8EB] text-[#422268] hover:bg-white"
>
{loading ? (
<>

View File

@@ -26,7 +26,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
<div className="space-y-8">
{/* Personal Information */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Personal Information
</h2>
@@ -40,7 +40,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.first_name}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="first-name-input"
/>
</div>
@@ -52,7 +52,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.last_name}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="last-name-input"
/>
</div>
@@ -69,7 +69,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.phone}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="phone-input"
/>
</div>
@@ -82,7 +82,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.date_of_birth}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="dob-input"
/>
</div>
@@ -112,7 +112,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.city}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="city-input"
/>
</div>
@@ -124,7 +124,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.state}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="state-input"
/>
</div>
@@ -136,7 +136,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
required
value={formData.zipcode}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="zipcode-input"
/>
</div>
@@ -145,7 +145,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
{/* How Did You Hear About Us */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
How Did You Hear About Us? *
</h2>
<div className="space-y-3">
@@ -167,7 +167,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
{/* Partner Information */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Partner Information (Optional)
</h2>
@@ -179,7 +179,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
name="partner_first_name"
value={formData.partner_first_name}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="partner-first-name-input"
/>
</div>
@@ -190,7 +190,7 @@ const RegistrationStep1 = ({ formData, setFormData, handleInputChange }) => {
name="partner_last_name"
value={formData.partner_last_name}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="partner-last-name-input"
/>
</div>

View File

@@ -33,10 +33,10 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
<div className="space-y-8">
{/* Newsletter Publication Preferences */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Newsletter Publication Preferences *
</h2>
<p className="text-[#6B708D]">
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Please check what information may be published in LOAF Newsletter
</p>
@@ -97,7 +97,7 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
{/* Referral */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Referral
</h2>
<div>
@@ -110,10 +110,10 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
value={formData.referred_by_member_name}
onChange={handleInputChange}
placeholder="Enter member name or email"
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="referral-input"
/>
<p className="text-sm text-[#6B708D] mt-2">
<p className="text-sm text-[#664fa3] mt-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
If referred by a current member, you may skip the event attendance requirement.
</p>
</div>
@@ -121,10 +121,10 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
{/* Volunteer Interests */}
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Volunteer Interests (Optional)
</h2>
<p className="text-[#6B708D]">
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
I may at some time be interested in volunteering with LOAF in the following ways (training is provided)
</p>
@@ -158,7 +158,7 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
I am requesting for scholarship
</Label>
</div>
<p className="text-sm text-[#6B708D]">
<p className="text-sm text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Scholarship information is kept confidential
</p>
@@ -174,7 +174,7 @@ const RegistrationStep2 = ({ formData, setFormData, handleInputChange }) => {
onChange={handleInputChange}
placeholder="Tell us why you're requesting a scholarship..."
rows={4}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
)}

View File

@@ -23,11 +23,11 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
return (
<div className="space-y-6">
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Members Directory
</h2>
<p className="text-[#6B708D]">
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Would you like to be displayed on our private members directory? (optional and you can change the answer later)
</p>
@@ -37,8 +37,8 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
className={`
p-4 rounded-xl border-2 cursor-pointer transition-all
${formData.show_in_directory
? 'border-[#E07A5F] bg-[#E07A5F]/5'
: 'border-[#EAE0D5] hover:border-[#6B708D]'
? 'border-[#ff9e77] bg-[#ff9e77]/5'
: 'border-[#ddd8eb] hover:border-[#664fa3]'
}
`}
onClick={() => setFormData(prev => ({ ...prev, show_in_directory: true }))}
@@ -46,13 +46,13 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
<div className="flex items-center space-x-3">
<div className={`
w-5 h-5 rounded-full border-2 flex items-center justify-center
${formData.show_in_directory ? 'border-[#E07A5F]' : 'border-[#EAE0D5]'}
${formData.show_in_directory ? 'border-[#ff9e77]' : 'border-[#ddd8eb]'}
`}>
{formData.show_in_directory && (
<div className="w-3 h-3 rounded-full bg-[#E07A5F]" />
<div className="w-3 h-3 rounded-full bg-[#ff9e77]" />
)}
</div>
<span className="font-medium text-[#3D405B]">
<span className="font-medium text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Yes, include me in the Members Directory
</span>
</div>
@@ -62,8 +62,8 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
className={`
p-4 rounded-xl border-2 cursor-pointer transition-all
${!formData.show_in_directory
? 'border-[#E07A5F] bg-[#E07A5F]/5'
: 'border-[#EAE0D5] hover:border-[#6B708D]'
? 'border-[#ff9e77] bg-[#ff9e77]/5'
: 'border-[#ddd8eb] hover:border-[#664fa3]'
}
`}
onClick={() => setFormData(prev => ({ ...prev, show_in_directory: false }))}
@@ -71,13 +71,13 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
<div className="flex items-center space-x-3">
<div className={`
w-5 h-5 rounded-full border-2 flex items-center justify-center
${!formData.show_in_directory ? 'border-[#E07A5F]' : 'border-[#EAE0D5]'}
${!formData.show_in_directory ? 'border-[#ff9e77]' : 'border-[#ddd8eb]'}
`}>
{!formData.show_in_directory && (
<div className="w-3 h-3 rounded-full bg-[#E07A5F]" />
<div className="w-3 h-3 rounded-full bg-[#ff9e77]" />
)}
</div>
<span className="font-medium text-[#3D405B]">
<span className="font-medium text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
No, don't include me in the Members Directory
</span>
</div>
@@ -87,8 +87,8 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
{/* Conditional Directory Fields */}
{formData.show_in_directory && (
<div className="space-y-4 mt-6 p-6 bg-[#FDFCF8] rounded-xl border border-[#EAE0D5]">
<p className="text-[#6B708D] text-sm">
<div className="space-y-4 mt-6 p-6 bg-white rounded-xl border border-[#ddd8eb]">
<p className="text-[#664fa3] text-sm" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Below, choose what information you would like include in the Members Only Directory.
(If you ever want to update this information, remember the Directory Section and Account Section are separate)
</p>
@@ -101,7 +101,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
type="email"
value={formData.directory_email}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -114,7 +114,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
onChange={handleInputChange}
placeholder="Tell other members about yourself..."
rows={4}
className="rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -125,7 +125,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
name="directory_address"
value={formData.directory_address}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -137,7 +137,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
type="tel"
value={formData.directory_phone}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -149,7 +149,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
type="date"
value={formData.directory_dob}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
@@ -162,7 +162,7 @@ const RegistrationStep3 = ({ formData, setFormData, handleInputChange }) => {
name="directory_partner_name"
value={formData.directory_partner_name}
onChange={handleInputChange}
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
/>
</div>
</div>

View File

@@ -7,11 +7,11 @@ const RegistrationStep4 = ({ formData, handleInputChange }) => {
return (
<div className="space-y-6">
<div className="space-y-4">
<h2 className="text-2xl font-semibold fraunces text-[#3D405B]">
<h2 className="text-2xl font-semibold text-[#422268]" style={{ fontFamily: "'Inter', sans-serif" }}>
Account Credentials
</h2>
<p className="text-[#6B708D]">
<p className="text-[#664fa3]" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Your email is also your username that you can use to login.
Please note you can only login after your application is approved.
</p>
@@ -28,7 +28,7 @@ const RegistrationStep4 = ({ formData, handleInputChange }) => {
value={formData.email}
onChange={handleInputChange}
placeholder="your.email@example.com"
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="email-input"
/>
</div>
@@ -43,10 +43,10 @@ const RegistrationStep4 = ({ formData, handleInputChange }) => {
value={formData.password}
onChange={handleInputChange}
placeholder="At least 6 characters"
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="password-input"
/>
<p className="text-sm text-[#6B708D] mt-2">
<p className="text-sm text-[#664fa3] mt-2" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Must be at least 6 characters long
</p>
</div>
@@ -60,7 +60,7 @@ const RegistrationStep4 = ({ formData, handleInputChange }) => {
value={formData.confirmPassword}
onChange={handleInputChange}
placeholder="Re-enter your password"
className="h-14 rounded-xl border-2 border-[#EAE0D5] focus:border-[#E07A5F]"
className="h-14 rounded-xl border-2 border-[#ddd8eb] focus:border-[#664fa3]"
data-testid="confirm-password-input"
/>
{formData.confirmPassword && formData.password !== formData.confirmPassword && (

View File

@@ -20,25 +20,25 @@ const RegistrationStepIndicator = ({ currentStep, totalSteps = 4 }) => {
w-12 h-12 rounded-full flex items-center justify-center font-semibold text-lg
transition-all duration-300
${currentStep === step.number
? 'bg-[#E07A5F] text-white scale-110 shadow-lg'
? 'bg-[#ff9e77] text-white scale-110 shadow-lg'
: currentStep > step.number
? 'bg-[#81B29A] text-white'
: 'bg-[#EAE0D5] text-[#6B708D]'
: 'bg-[#ddd8eb] text-[#664fa3]'
}
`}>
{currentStep > step.number ? '✓' : step.number}
</div>
<span className={`
text-sm mt-2 font-medium transition-colors
${currentStep === step.number ? 'text-[#E07A5F]' : 'text-[#6B708D]'}
`}>
${currentStep === step.number ? 'text-[#ff9e77]' : 'text-[#664fa3]'}
`} style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
{step.title}
</span>
</div>
{/* Connecting Line */}
{index < steps.length - 1 && (
<div className="flex-1 h-1 mx-2 relative -top-6 bg-[#EAE0D5]">
<div className="flex-1 h-1 mx-2 relative -top-6 bg-[#ddd8eb]">
<div
className={`
h-full transition-all duration-500
@@ -52,8 +52,8 @@ const RegistrationStepIndicator = ({ currentStep, totalSteps = 4 }) => {
</div>
{/* Step Counter */}
<p className="text-center text-[#6B708D] mt-6 text-lg">
Step <span className="font-semibold text-[#E07A5F]">{currentStep}</span> of {totalSteps}
<p className="text-center text-[#664fa3] mt-6 text-lg" style={{ fontFamily: "'Nunito Sans', sans-serif" }}>
Step <span className="font-semibold text-[#ff9e77]">{currentStep}</span> of {totalSteps}
</p>
</div>
);