Table fixes
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
];
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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={{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user