Table fixes

This commit is contained in:
Sean Edmunds
2025-11-07 14:15:54 -06:00
parent 1b23933875
commit f37cf84a61
10 changed files with 238 additions and 170 deletions

View File

@@ -80,11 +80,11 @@ function App() {
useEffect(() => {
if (allThemes && themeName) {
if (currentThemePlaylist === 'All') {
if (themeName !== 'random') {
if (themeName === 'random') {
handleThemeChange(allThemes, false);
} else {
const temp = allThemes.find((t: Theme) => t.name === themeName);
setTheme(temp);
} else {
handleThemeChange(allThemes, false);
}
} else if (currentThemePlaylist === 'Time of Day') {
const themeList = JSON.parse(

View File

@@ -45,8 +45,11 @@ export const SearchHistoryColumns = (
</Box>
</Group>
),
size: 64,
maxSize: 64,
meta: {
filterVariant: 'counter',
},
size: 32,
maxSize: 32,
enableSorting: false,
}),
columnHelper.accessor('prefix', {
@@ -64,26 +67,43 @@ export const SearchHistoryColumns = (
if (value === null) return true;
return row.getValue(id) === value;
},
size: 32,
maxSize: 32,
}),
columnHelper.accessor('provider', {
id: 'provider',
cell: ({ cell }: any) => <Text mx={8}>{cell.getValue()}</Text>,
cell: ({ cell }: any) => (
<Text mx={8} style={{ textAlign: 'center' }}>
{cell.getValue()}
</Text>
),
header: () => <Text fw={600}>Provider</Text>,
meta: {
filterVariant: 'mantineSelect',
},
size: 128,
maxSize: 128,
}),
columnHelper.accessor('searchTerm', {
id: 'searchTerm',
cell: ({ cell }: any) => (
<Text w={'100%'} mx={8} style={{ justifySelf: 'center' }}>
{cell.getValue()}
</Text>
<Group
style={{
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
}}
>
<Text w={'100%'} mx={8} style={{ justifySelf: 'center' }}>
{cell.getValue()}
</Text>
</Group>
),
header: () => <Text fw={600}>Search String</Text>,
meta: {
filterVariant: 'text',
},
maxSize: 1920,
}),
columnHelper.accessor('dateTimeStamp', {
id: 'dateTimeStamp',
@@ -115,5 +135,7 @@ export const SearchHistoryColumns = (
}
return true;
},
size: 132,
maxSize: 132,
}),
];

View File

@@ -1,4 +1,4 @@
import { Button, Group } from '@mantine/core';
import { Button, Group, Text } from '@mantine/core';
import {
type ColumnFiltersState,
flexRender,
@@ -10,7 +10,7 @@ import {
type SortingState,
useReactTable,
} from '@tanstack/react-table';
import { type Dispatch, type SetStateAction, useState } from 'react';
import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
import { Filter } from './components';
export function DataTable({
@@ -55,32 +55,47 @@ export function DataTable({
globalFilterFn: 'includesString',
onGlobalFilterChange: setGlobalFilter,
});
useEffect(() => {
if (!filtersEnabled) {
setColumnFilters([]);
}
}, [filtersEnabled]);
return (
<table style={{ width: '100%', backgroundColor: 'var(--mantine-color-primary-0)' }}>
<table
style={{
borderSpacing: '2px 0px',
backgroundColor: 'var(--mantine-color-accent-0)',
}}
>
<thead
style={{
position: 'sticky',
top: 0,
zIndex: 1,
backgroundColor: 'var(--mantine-color-primary-0)',
borderTopLeftRadius: '1rem',
borderTopRightRadius: '1rem',
}}
>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
<th
key={header.id}
style={{
width: header.getSize(),
padding: 0,
}}
>
{header.isPlaceholder ? null : (
<>
<Button
{...{
style: {
cursor: 'pointer',
width: '100%',
borderRadius: '0px',
backgroundColor: 'transparent',
},
px: 0,
onClick: () => {
if (header.column.getCanSort()) {
if (sorting[0].id === header.id) {
@@ -114,6 +129,7 @@ export function DataTable({
<Filter
column={header.column}
options={[...new Set(data.map((item: any) => item[header.id]))]}
resultCount={table.getFilteredRowModel().rows.length}
/>
) : null}
</>
@@ -139,7 +155,12 @@ export function DataTable({
}}
>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
<td
key={cell.id}
style={{
width: cell.column.getSize(),
}}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
@@ -158,6 +179,26 @@ export function DataTable({
))}
</tr>
))}
<tr
style={{
width: '100%',
backgroundColor: 'var(--mantine-color-primary-0)',
position: 'sticky',
bottom: 0,
}}
>
<td colSpan={5}>
<Text
style={{
color: 'var(--mantine-color-background-0)',
fontWeight: 'bold',
textAlign: 'center',
}}
>
Total Entries: {table.getRowCount()}
</Text>
</td>
</tr>
</tfoot>
</table>
);

View File

@@ -8,6 +8,7 @@ import {
RangeSlider,
Select,
Stack,
Text,
} from '@mantine/core';
import { DatePickerInput } from '@mantine/dates';
import type { Column, RowData } from '@tanstack/react-table';
@@ -26,11 +27,20 @@ declare module '@tanstack/react-table' {
| 'multiSelect'
| 'slider'
| 'checkbox'
| 'counter'
| 'none';
}
}
export function Filter({ column, options }: { column: Column<unknown>; options: any }) {
export function Filter({
column,
options,
resultCount,
}: {
column: Column<unknown>;
options: any;
resultCount?: number;
}) {
const columnFilterValue = column.getFilterValue();
const { filterVariant } = column.columnDef.meta ?? {};
const optionsFilter: OptionsFilter = ({ options, search }) => {
@@ -88,12 +98,15 @@ export function Filter({ column, options }: { column: Column<unknown>; options:
label: selectClasses.menuSelectLabel,
options: selectClasses.menuSelectOptions,
option: selectClasses.menuSelectOption,
dropdown: selectClasses.dropdown,
}}
data={options.map((option: ComboboxItem) => {
return { value: option, label: option };
})}
data={options
.map((option: ComboboxItem) => {
return { value: option, label: option };
})
.sort((a: ComboboxItem, b: ComboboxItem) => a.label.localeCompare(b.label))}
onChange={(e: any) => column.setFilterValue(e)}
w={'auto'}
clearable
/>
) : filterVariant === 'multiSelect' ? (
<MultiSelect
@@ -149,6 +162,13 @@ export function Filter({ column, options }: { column: Column<unknown>; options:
<Checkbox onChange={(value) => column.setFilterValue(value.target.checked)} />
</Group>
// See faceted column filters example for datalist search suggestions
) : filterVariant === 'counter' ? (
<Group h={36} align='center' justify='center'>
<Text c={'var(--mantine-color-background-0)'}>
{resultCount}/{options.length}
</Text>
</Group>
// See faceted column filters example for datalist search suggestions
) : (
<Box
style={{

View File

@@ -132,6 +132,7 @@ function SettingsCard({
placeholder={`Sort ${sectionTitle}...`}
value={sort}
data={['Custom', 'A>Z', 'Z>A', 'Newest', 'Oldest']}
className={selectClasses.settingsItem}
classNames={{
wrapper: selectClasses.menuSelectWrapper,
root: selectClasses.menuSelectRoot,

View File

@@ -108,23 +108,6 @@ const SearchHistory = () => {
setGlobalFilter={setGlobalFilter}
/>
</Stack>
<Group
w={'100%'}
style={{
backgroundColor: 'var(--mantine-color-primary-0)',
}}
align='center'
justify='center'
>
<Text
style={{
color: 'var(--mantine-color-background-0)',
fontWeight: 'bold',
}}
>
Results: {searchHistory.length}
</Text>
</Group>
</Stack>
</Stack>
</Stack>

View File

@@ -221,15 +221,15 @@ export function ThemePlaylists() {
<ThemePlaylistCard
cardPlaylist={{
id:
themePlaylists?.filter(
themePlaylists?.find(
(a: ThemePlaylist) => a.name === 'Time of Day',
)[0]?.id ?? undefined,
)?.id ?? undefined,
name: 'Time of Day',
default: 1,
themeList:
themePlaylists?.filter(
themePlaylists?.find(
(a: ThemePlaylist) => a.name === 'Time of Day',
)[0]?.themeList ?? '[]',
)?.themeList ?? '[]',
}}
handleOpen={handleOpen}
allThemes={allThemeData}

View File

@@ -67,7 +67,7 @@ export function ThemePlaylistCard({
paddingLeft: '.25rem',
backgroundColor: 'var(--mantine-color-border-0)',
borderRadius: '4px',
color: 'var(--mantine-color-background-0)',
color: 'var(--mantine-color-primary-0)',
zIndex: 3,
}}
>
@@ -130,44 +130,7 @@ export function ThemePlaylistCard({
>
{hover && <Overlay opacity={0.5} zIndex={1} />}
<Stack h={'100%'} w={'100%'} align='center' mt={'.75rem'}>
{cardPlaylist.name !== 'Time of Day' ? (
<>
<Text
px={'.5rem'}
mt={'.5rem'}
mb={'-.5rem'}
style={{
color: 'var(--mantine-color-background-0)',
backgroundColor: 'var(--mantine-color-primary-0)',
borderRadius: '4px',
zIndex: 160,
}}
>
Count: {themeList.length}
</Text>
<ScrollArea
className={scrollAreaClasses.default}
classNames={scrollAreaClasses}
h={'255px'}
w={'100%'}
style={{ zIndex: 2 }}
>
<Stack gap={4}>
{themeList.length > 0 &&
themeList
.sort((a: number, b: number) => (a > b ? 1 : -1))
.map((item: number) => {
const miniTheme: any = allThemes.find(
(theme: Theme) => theme.id === item,
);
return (
<ThemeMiniCard key={miniTheme?.id} miniTheme={miniTheme} />
);
})}
</Stack>
</ScrollArea>
</>
) : (
{cardPlaylist.name === 'Time of Day' ? (
<>
<Text
px={'.5rem'}
@@ -207,6 +170,43 @@ export function ThemePlaylistCard({
</Stack>
</ScrollArea>
</>
) : (
<>
<Text
px={'.5rem'}
mt={'.5rem'}
mb={'-.5rem'}
style={{
color: 'var(--mantine-color-background-0)',
backgroundColor: 'var(--mantine-color-primary-0)',
borderRadius: '4px',
zIndex: 160,
}}
>
Count: {themeList.length}
</Text>
<ScrollArea
className={scrollAreaClasses.default}
classNames={scrollAreaClasses}
h={'255px'}
w={'100%'}
style={{ zIndex: 2 }}
>
<Stack gap={4}>
{themeList.length > 0 &&
themeList
.sort((a: number, b: number) => (a > b ? 1 : -1))
.map((item: number) => {
const miniTheme: any = allThemes.find(
(theme: Theme) => theme.id === item,
);
return (
<ThemeMiniCard key={miniTheme?.id} miniTheme={miniTheme} />
);
})}
</Stack>
</ScrollArea>
</>
)}
</Stack>
</Button>