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;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
font-size: 16px;
}
.form-group input:focus,
@@ -185,6 +185,70 @@ body {
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 {
display: inline-block;
padding: 4px 12px;
@@ -255,7 +319,7 @@ body {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
font-size: 16px;
color: #333;
background-color: #fff;
}

View File

@@ -301,30 +301,32 @@ const Dashboard: React.FC = () => {
<div className="card" style={{ marginTop: '20px' }}>
<h3 style={{ marginBottom: '16px' }}>Payment History</h3>
{payments.length > 0 ? (
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Date</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</tr>
</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>
<div className="table-container">
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Date</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</tr>
))}
</tbody>
</table>
</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>
))}
</tbody>
</table>
</div>
) : (
<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 && (
<div style={{ marginBottom: '20px' }}>
<h4 style={{ marginBottom: '12px' }}>Pending Payments</h4>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Membership</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</tr>
</thead>
<tbody>
{allPayments.filter(p => p.status === 'pending').map(payment => {
const membership = allMemberships.find(m => m.id === payment.membership_id);
return (
<tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{getUserName(payment.user_id)}</td>
<td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td>
<td style={{ padding: '12px' }}>{payment.payment_method}</td>
<td style={{ padding: '12px' }}>
{membership ? `${membership.tier.name} (${membership.status})` : 'N/A'}
</td>
<td style={{ padding: '12px' }}>
<button
className="btn btn-primary"
onClick={() => handleApprovePayment(payment.id, payment.membership_id || undefined)}
style={{ fontSize: '12px', padding: '6px 12px' }}
>
Approve
</button>
</td>
</tr>
);
})}
</tbody>
</table>
<div className="table-container">
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Amount</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Method</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Membership</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</tr>
</thead>
<tbody>
{allPayments.filter(p => p.status === 'pending').map(payment => {
const membership = allMemberships.find(m => m.id === payment.membership_id);
return (
<tr key={payment.id} style={{ borderBottom: '1px solid #eee' }}>
<td style={{ padding: '12px' }}>{getUserName(payment.user_id)}</td>
<td style={{ padding: '12px' }}>£{payment.amount.toFixed(2)}</td>
<td style={{ padding: '12px' }}>{payment.payment_method}</td>
<td style={{ padding: '12px' }}>
{membership ? `${membership.tier.name} (${membership.status})` : 'N/A'}
</td>
<td style={{ padding: '12px' }}>
<button
className="btn btn-primary"
onClick={() => handleApprovePayment(payment.id, payment.membership_id || undefined)}
style={{ fontSize: '12px', padding: '6px 12px' }}
>
Approve
</button>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
)}
@@ -381,30 +385,32 @@ const Dashboard: React.FC = () => {
{allMemberships.filter(m => m.status === 'pending').length > 0 && (
<div>
<h4 style={{ marginBottom: '12px' }}>Pending Memberships</h4>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Tier</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Start Date</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</tr>
</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>
<div className="table-container">
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>User</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Tier</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Start Date</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
</tr>
))}
</tbody>
</table>
</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>
))}
</tbody>
</table>
</div>
</div>
)}
@@ -437,78 +443,80 @@ const Dashboard: React.FC = () => {
/>
</div>
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Name</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Email</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Role</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Joined</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</tr>
</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>
<div className="table-container">
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr style={{ borderBottom: '2px solid #ddd' }}>
<th style={{ padding: '12px', textAlign: 'left' }}>Name</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Email</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Role</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Status</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Joined</th>
<th style={{ padding: '12px', textAlign: 'left' }}>Actions</th>
</tr>
))}
</tbody>
</table>
</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>
))}
</tbody>
</table>
</div>
</div>
)}
</div>

View File

@@ -43,7 +43,7 @@ const Login: React.FC = () => {
};
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={{
flex: '1',
maxWidth: '400px',