Mobile improvements
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user