Mobile improvements

This commit is contained in:
James Pattinson
2025-11-12 16:47:21 +00:00
parent 0f74333a22
commit e5fdd0ecb8
3 changed files with 227 additions and 155 deletions

View File

@@ -79,7 +79,7 @@ body {
padding: 10px; padding: 10px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
font-size: 14px; font-size: 16px;
} }
.form-group input:focus, .form-group input:focus,
@@ -185,6 +185,70 @@ body {
margin-top: 20px; margin-top: 20px;
} }
/* Mobile responsive adjustments */
@media (max-width: 768px) {
.dashboard-grid {
grid-template-columns: 1fr;
}
.container {
padding: 10px;
}
.card {
padding: 16px;
}
.navbar {
padding: 12px 16px;
}
.navbar h1 {
font-size: 18px;
}
/* Make tables responsive */
table {
width: 100%;
min-width: 600px; /* Ensure minimum width for readability */
}
.table-container {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
/* Auth pages mobile adjustments */
.auth-container {
flex-direction: column;
padding: 20px;
gap: 20px;
}
.auth-card {
max-width: 100%;
padding: 24px;
}
/* Welcome section mobile adjustments */
.welcome-section {
max-width: 100% !important;
padding: 20px !important;
}
.welcome-section h1 {
font-size: 1.8rem !important;
}
/* Form grid mobile adjustments */
@media (max-width: 768px) {
form[style*="grid-template-columns"] {
grid-template-columns: 1fr !important;
gap: 16px !important;
}
}
}
.status-badge { .status-badge {
display: inline-block; display: inline-block;
padding: 4px 12px; padding: 4px 12px;
@@ -255,7 +319,7 @@ body {
padding: 8px; padding: 8px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
font-size: 14px; font-size: 16px;
color: #333; color: #333;
background-color: #fff; background-color: #fff;
} }

View File

@@ -301,30 +301,32 @@ const Dashboard: React.FC = () => {
<div className="card" style={{ marginTop: '20px' }}> <div className="card" style={{ marginTop: '20px' }}>
<h3 style={{ marginBottom: '16px' }}>Payment History</h3> <h3 style={{ marginBottom: '16px' }}>Payment History</h3>
{payments.length > 0 ? ( {payments.length > 0 ? (
<table style={{ width: '100%', borderCollapse: 'collapse' }}> <div className="table-container">
<thead> <table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tr style={{ borderBottom: '2px solid #ddd' }}> <thead>
<th style={{ padding: '12px', textAlign: 'left' }}>Date</th> <tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th> <th style={{ padding: '12px', textAlign: 'left' }}>Date</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th> <th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th> <th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
</tr> <th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</thead>
<tbody>
{payments.map(payment => (
<tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{payment.payment_date ? formatDate(payment.payment_date) : 'Pending'}</td>
<td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td>
<td style={{ padding: '12px' }}>{payment.payment_method}</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${getStatusClass(payment.status)}`}>
{payment.status.toUpperCase()}
</span>
</td>
</tr> </tr>
))} </thead>
</tbody> <tbody>
</table> {payments.map(payment => (
<tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{payment.payment_date ? formatDate(payment.payment_date) : 'Pending'}</td>
<td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td>
<td style={{ padding: '12px' }}>{payment.payment_method}</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${getStatusClass(payment.status)}`}>
{payment.status.toUpperCase()}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
) : ( ) : (
<p style={{ color: '#666' }}>No payment history available.</p> <p style={{ color: '#666' }}>No payment history available.</p>
)} )}
@@ -339,41 +341,43 @@ const Dashboard: React.FC = () => {
{allPayments.filter(p => p.status === 'pending').length > 0 && ( {allPayments.filter(p => p.status === 'pending').length > 0 && (
<div style={{ marginBottom: '20px' }}> <div style={{ marginBottom: '20px' }}>
<h4 style={{ marginBottom: '12px' }}>Pending Payments</h4> <h4 style={{ marginBottom: '12px' }}>Pending Payments</h4>
<table style={{ width: '100%', borderCollapse: 'collapse' }}> <div className="table-container">
<thead> <table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tr style={{ borderBottom: '2px solid #ddd' }}> <thead>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th> <tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th> <th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th> <th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Membership</th> <th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th> <th style={{ padding: '12px', textAlign: 'left' }}>Membership</th>
</tr> <th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</thead> </tr>
<tbody> </thead>
{allPayments.filter(p => p.status === 'pending').map(payment => { <tbody>
const membership = allMemberships.find(m => m.id === payment.membership_id); {allPayments.filter(p => p.status === 'pending').map(payment => {
return ( const membership = allMemberships.find(m => m.id === payment.membership_id);
<tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}> return (
<td style={{ padding: '12px' }}>{getUserName(payment.user_id)}</td> <tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td> <td style={{ padding: '12px' }}>{getUserName(payment.user_id)}</td>
<td style={{ padding: '12px' }}>{payment.payment_method}</td> <td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td>
<td style={{ padding: '12px' }}> <td style={{ padding: '12px' }}>{payment.payment_method}</td>
{membership ? `${membership.tier.name} (${membership.status})` : 'N/A'} <td style={{ padding: '12px' }}>
</td> {membership ? `${membership.tier.name} (${membership.status})` : 'N/A'}
<td style={{ padding: '12px' }}> </td>
<button <td style={{ padding: '12px' }}>
className="btn btn-primary" <button
onClick={() => handleApprovePayment(payment.id, payment.membership_id || undefined)} className="btn btn-primary"
style={{ fontSize: '12px', padding: '6px 12px' }} onClick={() => handleApprovePayment(payment.id, payment.membership_id || undefined)}
> style={{ fontSize: '12px', padding: '6px 12px' }}
Approve >
</button> Approve
</td> </button>
</tr> </td>
); </tr>
})} );
</tbody> })}
</table> </tbody>
</table>
</div>
</div> </div>
)} )}
@@ -381,30 +385,32 @@ const Dashboard: React.FC = () => {
{allMemberships.filter(m => m.status === 'pending').length > 0 && ( {allMemberships.filter(m => m.status === 'pending').length > 0 && (
<div> <div>
<h4 style={{ marginBottom: '12px' }}>Pending Memberships</h4> <h4 style={{ marginBottom: '12px' }}>Pending Memberships</h4>
<table style={{ width: '100%', borderCollapse: 'collapse' }}> <div className="table-container">
<thead> <table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tr style={{ borderBottom: '2px solid #ddd' }}> <thead>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th> <tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Tier</th> <th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Start Date</th> <th style={{ padding: '12px', textAlign: 'left' }}>Tier</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th> <th style={{ padding: '12px', textAlign: 'left' }}>Start Date</th>
</tr> <th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</thead>
<tbody>
{allMemberships.filter(m => m.status === 'pending').map(membership => (
<tr key={membership.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{getUserName(membership.user_id)}</td>
<td style={{ padding: '12px' }}>{membership.tier.name}</td>
<td style={{ padding: '12px' }}>{formatDate(membership.start_date)}</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${getStatusClass(membership.status)}`}>
{membership.status.toUpperCase()}
</span>
</td>
</tr> </tr>
))} </thead>
</tbody> <tbody>
</table> {allMemberships.filter(m => m.status === 'pending').map(membership => (
<tr key={membership.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{getUserName(membership.user_id)}</td>
<td style={{ padding: '12px' }}>{membership.tier.name}</td>
<td style={{ padding: '12px' }}>{formatDate(membership.start_date)}</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${getStatusClass(membership.status)}`}>
{membership.status.toUpperCase()}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div> </div>
)} )}
@@ -437,78 +443,80 @@ const Dashboard: React.FC = () => {
/> />
</div> </div>
<table style={{ width: '100%', borderCollapse: 'collapse' }}> <div className="table-container">
<thead> <table style={{ width: '100%', borderCollapse: 'collapse' }}>
<tr style={{ borderBottom: '2px solid #ddd' }}> <thead>
<th style={{ padding: '12px', textAlign: 'left' }}>Name</th> <tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Email</th> <th style={{ padding: '12px', textAlign: 'left' }}>Name</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Role</th> <th style={{ padding: '12px', textAlign: 'left' }}>Email</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th> <th style={{ padding: '12px', textAlign: 'left' }}>Role</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Joined</th> <th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th> <th style={{ padding: '12px', textAlign: 'left' }}>Joined</th>
</tr> <th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</thead>
<tbody>
{filteredUsers.map(u => (
<tr
key={u.id}
style={{ borderBottom: '1px solid #eee', cursor: 'pointer' }}
onClick={() => handleUserClick(u)}
>
<td style={{ padding: '12px' }}>{u.first_name} {u.last_name}</td>
<td style={{ padding: '12px' }}>{u.email}</td>
<td style={{ padding: '12px' }}>
<span style={{
backgroundColor: u.role === 'super_admin' ? '#dc3545' :
u.role === 'admin' ? '#ffc107' : '#28a745',
color: u.role === 'member' ? 'white' : 'black',
padding: '4px 8px',
borderRadius: '4px',
fontSize: '12px',
fontWeight: 'bold'
}}>
{u.role.toUpperCase()}
</span>
</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${u.is_active ? 'status-active' : 'status-expired'}`}>
{u.is_active ? 'ACTIVE' : 'INACTIVE'}
</span>
</td>
<td style={{ padding: '12px' }}>{formatDate(u.created_at)}</td>
<td style={{ padding: '12px' }}>
{u.role === 'member' && (
<button
className="btn btn-primary"
onClick={(e) => {
e.stopPropagation(); // Prevent row click
handleUpdateUserRole(u.id, 'admin');
}}
style={{ fontSize: '12px', padding: '4px 8px', marginRight: '4px' }}
>
Make Admin
</button>
)}
{u.role === 'admin' && u.id !== user?.id && (
<button
className="btn btn-secondary"
onClick={(e) => {
e.stopPropagation(); // Prevent row click
handleUpdateUserRole(u.id, 'member');
}}
style={{ fontSize: '12px', padding: '4px 8px' }}
>
Remove Admin
</button>
)}
{u.role === 'super_admin' && (
<span style={{ fontSize: '12px', color: '#666' }}>Super Admin</span>
)}
</td>
</tr> </tr>
))} </thead>
</tbody> <tbody>
</table> {filteredUsers.map(u => (
<tr
key={u.id}
style={{ borderBottom: '1px solid #eee', cursor: 'pointer' }}
onClick={() => handleUserClick(u)}
>
<td style={{ padding: '12px' }}>{u.first_name} {u.last_name}</td>
<td style={{ padding: '12px' }}>{u.email}</td>
<td style={{ padding: '12px' }}>
<span style={{
backgroundColor: u.role === 'super_admin' ? '#dc3545' :
u.role === 'admin' ? '#ffc107' : '#28a745',
color: u.role === 'member' ? 'white' : 'black',
padding: '4px 8px',
borderRadius: '4px',
fontSize: '12px',
fontWeight: 'bold'
}}>
{u.role.toUpperCase()}
</span>
</td>
<td style={{ padding: '12px' }}>
<span className={`status-badge ${u.is_active ? 'status-active' : 'status-expired'}`}>
{u.is_active ? 'ACTIVE' : 'INACTIVE'}
</span>
</td>
<td style={{ padding: '12px' }}>{formatDate(u.created_at)}</td>
<td style={{ padding: '12px' }}>
{u.role === 'member' && (
<button
className="btn btn-primary"
onClick={(e) => {
e.stopPropagation(); // Prevent row click
handleUpdateUserRole(u.id, 'admin');
}}
style={{ fontSize: '12px', padding: '4px 8px', marginRight: '4px' }}
>
Make Admin
</button>
)}
{u.role === 'admin' && u.id !== user?.id && (
<button
className="btn btn-secondary"
onClick={(e) => {
e.stopPropagation(); // Prevent row click
handleUpdateUserRole(u.id, 'member');
}}
style={{ fontSize: '12px', padding: '4px 8px' }}
>
Remove Admin
</button>
)}
{u.role === 'super_admin' && (
<span style={{ fontSize: '12px', color: '#666' }}>Super Admin</span>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div> </div>
)} )}
</div> </div>

View File

@@ -43,7 +43,7 @@ const Login: React.FC = () => {
}; };
return ( return (
<div className="auth-container" style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: '40px', padding: '20px' }}> <div className="auth-container" style={{ gap: '40px', padding: '20px' }}>
<div className="welcome-section" style={{ <div className="welcome-section" style={{
flex: '1', flex: '1',
maxWidth: '400px', maxWidth: '400px',