refactor(frontend): consolidate shared styles into centralized style system
- Create comprehensive shared.ts with design tokens and categorized styles: - layoutStyles: main, loader, content variants - cardStyles: card, tableCard, cardHeader - tableStyles: complete table styling - paginationStyles: pagination controls - formStyles: inputs, labels, errors - buttonStyles: primary, secondary, accent, danger variants - badgeStyles: status badges with color variants - bannerStyles: error/success banners - modalStyles: modal overlay and content - toastStyles: toast notifications - utilityStyles: divider, emptyState, etc. - Refactor all page components to use shared styles: - page.tsx (counter) - audit/page.tsx - booking/page.tsx - appointments/page.tsx - profile/page.tsx - invites/page.tsx - admin/invites/page.tsx - admin/availability/page.tsx - Reduce code duplication significantly (each page now has only truly page-specific styles) - Maintain backwards compatibility with sharedStyles export
This commit is contained in:
parent
4d9edd7fd4
commit
81cd34b0e7
9 changed files with 1148 additions and 1173 deletions
|
|
@ -3,7 +3,7 @@
|
|||
import { useEffect, useState, useCallback } from "react";
|
||||
import { Permission } from "../auth-context";
|
||||
import { api } from "../api";
|
||||
import { sharedStyles } from "../styles/shared";
|
||||
import { layoutStyles, cardStyles, tableStyles, paginationStyles } from "../styles/shared";
|
||||
import { Header } from "../components/Header";
|
||||
import { useRequireAuth } from "../hooks/useRequireAuth";
|
||||
import { components } from "../generated/api";
|
||||
|
|
@ -68,8 +68,8 @@ export default function AuditPage() {
|
|||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<main style={styles.main}>
|
||||
<div style={styles.loader}>Loading...</div>
|
||||
<main style={layoutStyles.main}>
|
||||
<div style={layoutStyles.loader}>Loading...</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
@ -79,47 +79,47 @@ export default function AuditPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<main style={styles.main}>
|
||||
<main style={layoutStyles.main}>
|
||||
<Header currentPage="audit" />
|
||||
|
||||
<div style={styles.content}>
|
||||
<div style={layoutStyles.contentScrollable}>
|
||||
<div style={styles.tablesContainer}>
|
||||
{/* Counter Records Table */}
|
||||
<div style={styles.tableCard}>
|
||||
<div style={styles.tableHeader}>
|
||||
<h2 style={styles.tableTitle}>Counter Activity</h2>
|
||||
<span style={styles.totalCount}>{counterData?.total ?? 0} records</span>
|
||||
<div style={cardStyles.tableCard}>
|
||||
<div style={tableStyles.tableHeader}>
|
||||
<h2 style={tableStyles.tableTitle}>Counter Activity</h2>
|
||||
<span style={tableStyles.totalCount}>{counterData?.total ?? 0} records</span>
|
||||
</div>
|
||||
<div style={styles.tableWrapper}>
|
||||
<table style={styles.table}>
|
||||
<div style={tableStyles.tableWrapper}>
|
||||
<table style={tableStyles.table}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={styles.th}>User</th>
|
||||
<th style={styles.th}>Before</th>
|
||||
<th style={styles.th}>After</th>
|
||||
<th style={styles.th}>Date</th>
|
||||
<th style={tableStyles.th}>User</th>
|
||||
<th style={tableStyles.th}>Before</th>
|
||||
<th style={tableStyles.th}>After</th>
|
||||
<th style={tableStyles.th}>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{counterError && (
|
||||
<tr>
|
||||
<td colSpan={4} style={styles.errorRow}>
|
||||
<td colSpan={4} style={tableStyles.errorRow}>
|
||||
{counterError}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{!counterError &&
|
||||
counterData?.records.map((record) => (
|
||||
<tr key={record.id} style={styles.tr}>
|
||||
<td style={styles.td}>{record.user_email}</td>
|
||||
<td style={styles.tdNum}>{record.value_before}</td>
|
||||
<td style={styles.tdNum}>{record.value_after}</td>
|
||||
<td style={styles.tdDate}>{formatDate(record.created_at)}</td>
|
||||
<tr key={record.id} style={tableStyles.tr}>
|
||||
<td style={tableStyles.td}>{record.user_email}</td>
|
||||
<td style={tableStyles.tdNum}>{record.value_before}</td>
|
||||
<td style={tableStyles.tdNum}>{record.value_after}</td>
|
||||
<td style={tableStyles.tdDate}>{formatDate(record.created_at)}</td>
|
||||
</tr>
|
||||
))}
|
||||
{!counterError && (!counterData || counterData.records.length === 0) && (
|
||||
<tr>
|
||||
<td colSpan={4} style={styles.emptyRow}>
|
||||
<td colSpan={4} style={tableStyles.emptyRow}>
|
||||
No records yet
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -128,21 +128,21 @@ export default function AuditPage() {
|
|||
</table>
|
||||
</div>
|
||||
{counterData && counterData.total_pages > 1 && (
|
||||
<div style={styles.pagination}>
|
||||
<div style={paginationStyles.pagination}>
|
||||
<button
|
||||
onClick={() => setCounterPage((p) => Math.max(1, p - 1))}
|
||||
disabled={counterPage === 1}
|
||||
style={styles.pageBtn}
|
||||
style={paginationStyles.pageBtn}
|
||||
>
|
||||
←
|
||||
</button>
|
||||
<span style={styles.pageInfo}>
|
||||
<span style={paginationStyles.pageInfo}>
|
||||
{counterPage} / {counterData.total_pages}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setCounterPage((p) => Math.min(counterData.total_pages, p + 1))}
|
||||
disabled={counterPage === counterData.total_pages}
|
||||
style={styles.pageBtn}
|
||||
style={paginationStyles.pageBtn}
|
||||
>
|
||||
→
|
||||
</button>
|
||||
|
|
@ -151,43 +151,43 @@ export default function AuditPage() {
|
|||
</div>
|
||||
|
||||
{/* Sum Records Table */}
|
||||
<div style={styles.tableCard}>
|
||||
<div style={styles.tableHeader}>
|
||||
<h2 style={styles.tableTitle}>Sum Activity</h2>
|
||||
<span style={styles.totalCount}>{sumData?.total ?? 0} records</span>
|
||||
<div style={cardStyles.tableCard}>
|
||||
<div style={tableStyles.tableHeader}>
|
||||
<h2 style={tableStyles.tableTitle}>Sum Activity</h2>
|
||||
<span style={tableStyles.totalCount}>{sumData?.total ?? 0} records</span>
|
||||
</div>
|
||||
<div style={styles.tableWrapper}>
|
||||
<table style={styles.table}>
|
||||
<div style={tableStyles.tableWrapper}>
|
||||
<table style={tableStyles.table}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={styles.th}>User</th>
|
||||
<th style={styles.th}>A</th>
|
||||
<th style={styles.th}>B</th>
|
||||
<th style={styles.th}>Result</th>
|
||||
<th style={styles.th}>Date</th>
|
||||
<th style={tableStyles.th}>User</th>
|
||||
<th style={tableStyles.th}>A</th>
|
||||
<th style={tableStyles.th}>B</th>
|
||||
<th style={tableStyles.th}>Result</th>
|
||||
<th style={tableStyles.th}>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sumError && (
|
||||
<tr>
|
||||
<td colSpan={5} style={styles.errorRow}>
|
||||
<td colSpan={5} style={tableStyles.errorRow}>
|
||||
{sumError}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
{!sumError &&
|
||||
sumData?.records.map((record) => (
|
||||
<tr key={record.id} style={styles.tr}>
|
||||
<td style={styles.td}>{record.user_email}</td>
|
||||
<td style={styles.tdNum}>{record.a}</td>
|
||||
<td style={styles.tdNum}>{record.b}</td>
|
||||
<tr key={record.id} style={tableStyles.tr}>
|
||||
<td style={tableStyles.td}>{record.user_email}</td>
|
||||
<td style={tableStyles.tdNum}>{record.a}</td>
|
||||
<td style={tableStyles.tdNum}>{record.b}</td>
|
||||
<td style={styles.tdResult}>{record.result}</td>
|
||||
<td style={styles.tdDate}>{formatDate(record.created_at)}</td>
|
||||
<td style={tableStyles.tdDate}>{formatDate(record.created_at)}</td>
|
||||
</tr>
|
||||
))}
|
||||
{!sumError && (!sumData || sumData.records.length === 0) && (
|
||||
<tr>
|
||||
<td colSpan={5} style={styles.emptyRow}>
|
||||
<td colSpan={5} style={tableStyles.emptyRow}>
|
||||
No records yet
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -196,21 +196,21 @@ export default function AuditPage() {
|
|||
</table>
|
||||
</div>
|
||||
{sumData && sumData.total_pages > 1 && (
|
||||
<div style={styles.pagination}>
|
||||
<div style={paginationStyles.pagination}>
|
||||
<button
|
||||
onClick={() => setSumPage((p) => Math.max(1, p - 1))}
|
||||
disabled={sumPage === 1}
|
||||
style={styles.pageBtn}
|
||||
style={paginationStyles.pageBtn}
|
||||
>
|
||||
←
|
||||
</button>
|
||||
<span style={styles.pageInfo}>
|
||||
<span style={paginationStyles.pageInfo}>
|
||||
{sumPage} / {sumData.total_pages}
|
||||
</span>
|
||||
<button
|
||||
onClick={() => setSumPage((p) => Math.min(sumData.total_pages, p + 1))}
|
||||
disabled={sumPage === sumData.total_pages}
|
||||
style={styles.pageBtn}
|
||||
style={paginationStyles.pageBtn}
|
||||
>
|
||||
→
|
||||
</button>
|
||||
|
|
@ -223,13 +223,8 @@ export default function AuditPage() {
|
|||
);
|
||||
}
|
||||
|
||||
const pageStyles: Record<string, React.CSSProperties> = {
|
||||
// Override content for audit-specific layout
|
||||
content: {
|
||||
flex: 1,
|
||||
padding: "2rem",
|
||||
overflowY: "auto",
|
||||
},
|
||||
// Page-specific styles only
|
||||
const styles: Record<string, React.CSSProperties> = {
|
||||
tablesContainer: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
|
|
@ -237,64 +232,6 @@ const pageStyles: Record<string, React.CSSProperties> = {
|
|||
maxWidth: "1200px",
|
||||
margin: "0 auto",
|
||||
},
|
||||
tableCard: {
|
||||
background: "rgba(255, 255, 255, 0.03)",
|
||||
backdropFilter: "blur(10px)",
|
||||
border: "1px solid rgba(255, 255, 255, 0.08)",
|
||||
borderRadius: "20px",
|
||||
padding: "1.5rem",
|
||||
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)",
|
||||
},
|
||||
tableHeader: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
marginBottom: "1rem",
|
||||
},
|
||||
tableTitle: {
|
||||
fontFamily: "'Instrument Serif', Georgia, serif",
|
||||
fontSize: "1.5rem",
|
||||
fontWeight: 400,
|
||||
color: "#fff",
|
||||
margin: 0,
|
||||
},
|
||||
totalCount: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontSize: "0.875rem",
|
||||
color: "rgba(255, 255, 255, 0.4)",
|
||||
},
|
||||
tableWrapper: {
|
||||
overflowX: "auto",
|
||||
},
|
||||
table: {
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
},
|
||||
th: {
|
||||
textAlign: "left",
|
||||
padding: "0.75rem 1rem",
|
||||
fontSize: "0.75rem",
|
||||
fontWeight: 600,
|
||||
color: "rgba(255, 255, 255, 0.4)",
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.05em",
|
||||
borderBottom: "1px solid rgba(255, 255, 255, 0.08)",
|
||||
},
|
||||
tr: {
|
||||
borderBottom: "1px solid rgba(255, 255, 255, 0.04)",
|
||||
},
|
||||
td: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
color: "rgba(255, 255, 255, 0.7)",
|
||||
},
|
||||
tdNum: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
color: "rgba(255, 255, 255, 0.9)",
|
||||
fontFamily: "'DM Sans', monospace",
|
||||
},
|
||||
tdResult: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.875rem",
|
||||
|
|
@ -302,48 +239,4 @@ const pageStyles: Record<string, React.CSSProperties> = {
|
|||
fontWeight: 600,
|
||||
fontFamily: "'DM Sans', monospace",
|
||||
},
|
||||
tdDate: {
|
||||
padding: "0.875rem 1rem",
|
||||
fontSize: "0.75rem",
|
||||
color: "rgba(255, 255, 255, 0.4)",
|
||||
},
|
||||
emptyRow: {
|
||||
padding: "2rem 1rem",
|
||||
textAlign: "center",
|
||||
color: "rgba(255, 255, 255, 0.3)",
|
||||
fontSize: "0.875rem",
|
||||
},
|
||||
errorRow: {
|
||||
padding: "2rem 1rem",
|
||||
textAlign: "center",
|
||||
color: "#f87171",
|
||||
fontSize: "0.875rem",
|
||||
},
|
||||
pagination: {
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: "1rem",
|
||||
marginTop: "1rem",
|
||||
paddingTop: "1rem",
|
||||
borderTop: "1px solid rgba(255, 255, 255, 0.06)",
|
||||
},
|
||||
pageBtn: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
padding: "0.5rem 1rem",
|
||||
fontSize: "1rem",
|
||||
background: "rgba(255, 255, 255, 0.05)",
|
||||
color: "rgba(255, 255, 255, 0.7)",
|
||||
border: "1px solid rgba(255, 255, 255, 0.1)",
|
||||
borderRadius: "8px",
|
||||
cursor: "pointer",
|
||||
transition: "all 0.2s",
|
||||
},
|
||||
pageInfo: {
|
||||
fontFamily: "'DM Sans', system-ui, sans-serif",
|
||||
fontSize: "0.875rem",
|
||||
color: "rgba(255, 255, 255, 0.5)",
|
||||
},
|
||||
};
|
||||
|
||||
const styles = { ...sharedStyles, ...pageStyles };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue