Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
zapbampow committed Jul 15, 2023
2 parents f701e78 + 2b1b5a3 commit 1eed156
Show file tree
Hide file tree
Showing 16 changed files with 219 additions and 52 deletions.
2 changes: 1 addition & 1 deletion app/components/bggStats/Measurer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function Measurer({
if (!visible) return null;

return (
<div ref={measurerRef} className="absolute invisible w-max">
<div ref={measurerRef} className="invisible absolute w-max">
{value}
</div>
);
Expand Down
19 changes: 13 additions & 6 deletions app/components/bggStats/answers/RecordedPlays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,21 @@ import {
getSortedRowModel,
} from "@tanstack/react-table";
import type { ColumnHelper } from "@tanstack/react-table";
import { ExternalLink, NewBadge } from "../icons";
import { ExternalLink } from "../icons";

import TableWithPagination from "../table/TableWithPagination";
import type { PlayDataModel } from "~/models/bgg/gameDataModels";
import { TrophyFilled, Trophy, Dice1 } from "../icons";
import { TrophyFilled } from "../icons";
import IconLegend from "./IconLegend";
import { useIsMobile } from "~/hooks/useIsMobile";
import RecordCards from "../table/RecordCards";

export default function RecordedPlays() {
const { state: data } = usePlayResultsContext();
React.useEffect(() => {
console.log("data", data);
}, [data]);
const isMobile = useIsMobile();
// React.useEffect(() => {
// console.log("data", data);
// }, [data]);

const columnHelper = createColumnHelper<PlayDataModel>();
const columns = [
Expand Down Expand Up @@ -103,7 +106,11 @@ export default function RecordedPlays() {

return (
<Container>
<TableWithPagination table={table} />
{isMobile ? (
<RecordCards table={table} />
) : (
<TableWithPagination table={table} />
)}
<IconLegend />
</Container>
);
Expand Down
2 changes: 1 addition & 1 deletion app/components/bggStats/datepicker/DatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export default function DatePickerComponent({ filter }: Props) {
clearAriaLabel="Clear date"
/>
</div>
<div onClick={removeFilter} className=" hover:text-red-500">
<div onClick={removeFilter} className="ml-auto hover:text-red-500">
<Trash width={16} />
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/components/bggStats/datepicker/MultiDatePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default function MultiDatePickerComponent({ filter }: Props) {
onCalendarClose={() => setIsOpen(false)}
rangeDivider="and"
/>
<div onClick={removeFilter} className=" hover:text-red-500">
<div onClick={removeFilter} className="ml-auto hover:text-red-500">
<Trash width={16} />
</div>
</div>
Expand Down
60 changes: 40 additions & 20 deletions app/components/bggStats/filters/ComboBoxFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import ClearFilter from "./ClearFilter";
import { Check, Search, Trash } from "../icons";
import useDebounce from "~/hooks/useDebounce";
import { usePlayResultsContext } from "~/contexts/bggStats/playResultsContext";
import { useIsMobile } from "~/hooks/useIsMobile";
import { useWindowSize } from "~/hooks/useWindowSize";

type Props = {
filter: FilterType;
Expand All @@ -38,6 +40,7 @@ export default function ComboBoxFilter({ filter }: Props) {
let inputRef = useRef<HTMLInputElement | null>(null);
let btnRef = useRef<HTMLButtonElement>(null);
let filterBtnRef = useRef<HTMLDivElement>(null);
const isMobile = useIsMobile();

const [options, setOptions] = useState<SelectionType[]>([]);
const [selection, setSelection] = useState<SelectionType>({});
Expand All @@ -55,6 +58,28 @@ export default function ComboBoxFilter({ filter }: Props) {
return option.label.toLowerCase().includes(query.toLowerCase());
});

let { width } = useWindowSize();

const getSelectionText = (selection: SelectionType | undefined) => {
if (!selection) return "";

if (isMobile) {
let ch = width / 11;

if (selection.label.length < ch) {
return selection.label;
} else {
return `${selection.label.slice(0, ch - 5)}...`;
}
}

if (selection.label.length > 20) {
return `${selection.label.slice(0, 20)}...`;
}

return selection.label;
};

const handleChange = (selection: SelectionType) => {
setSelection(selection);
setSelectionText(getSelectionText(selection));
Expand Down Expand Up @@ -129,19 +154,24 @@ export default function ComboBoxFilter({ filter }: Props) {
<div
className={`relative flex items-center ${comboContainerStyles} hover:cursor-pointer`}
>
<Measurer
value={`${filter.label}: ${selectionText}`}
visible={visible}
setVisible={setVisible}
impactedRef={filterBtnRef}
addedWidth={selectionText ? 40 : 0}
/>
{!isMobile && (
<Measurer
value={`${filter.label}: ${selectionText}`}
visible={visible}
setVisible={setVisible}
impactedRef={filterBtnRef}
addedWidth={selectionText ? 40 : 0}
/>
)}

<div
ref={filterBtnRef}
className="flex items-center w-full gap-4 overflow-hidden font-semibold text-left transition-all whitespace-nowrap sm:max-w-sm"
className="flex w-full items-center justify-between gap-4 overflow-hidden whitespace-nowrap text-left font-semibold transition-all sm:max-w-sm"
onClick={clickButton}
>
{filter.label}: {selectionText}
<span>
{filter.label}: {selectionText}
</span>
{selectionText ? (
<button
className="text-slate-400 hover:text-red-500"
Expand Down Expand Up @@ -171,7 +201,7 @@ export default function ComboBoxFilter({ filter }: Props) {
}}
autoFocus
placeholder="search"
className={`flex-1 px-2 bg-transparent font-semibold transition transition-all ease-in-out duration-500 ${hoverStyles} focus:outline-0`}
className={`flex-1 bg-transparent px-2 font-semibold transition transition-all duration-500 ease-in-out ${hoverStyles} focus:outline-0`}
/>
<Search className="cursor-default text-slate-500" />
<Combobox.Button
Expand Down Expand Up @@ -233,13 +263,3 @@ export default function ComboBoxFilter({ filter }: Props) {
</div>
);
}

const getSelectionText = (selection: SelectionType | undefined) => {
if (!selection) return "";

if (selection.label.length > 20) {
return `${selection.label.slice(0, 20)}...`;
}

return selection.label;
};
41 changes: 30 additions & 11 deletions app/components/bggStats/filters/ComboBoxFilterMultiple.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import RemoveFilter from "./RemoveFilter";
import Measurer from "~/components/bggStats/Measurer";
import useDebounce from "~/hooks/useDebounce";
import { usePlayResultsContext } from "~/contexts/bggStats/playResultsContext";
import { useIsMobile } from "~/hooks/useIsMobile";
import { useWindowSize } from "~/hooks/useWindowSize";

type Props = {
filter: FilterType;
Expand All @@ -32,6 +34,7 @@ export default function ComboBoxFilterMultiple({ filter }: Props) {
let inputRef = useRef<HTMLInputElement | null>(null);
let btnRef = useRef<HTMLButtonElement>(null);
let filterBtnRef = useRef<HTMLDivElement>(null);
const isMobile = useIsMobile();

const [selections, setSelections] = useState<SelectionType[]>([]); // selected options
const [allOptions, setAllOptions] = useState<SelectionType[]>([]);
Expand All @@ -43,10 +46,24 @@ export default function ComboBoxFilterMultiple({ filter }: Props) {

const labelSelectionText = `${filter.label}: ${selectionText}`;

const buttonText =
labelSelectionText.length > 40
const getButtonText = () => {
if (isMobile) {
let { width } = useWindowSize();
let ch = width / 10;

if (labelSelectionText.length < ch) {
return labelSelectionText;
} else {
return `${labelSelectionText.slice(0, ch - 5)}...`;
}
}

return labelSelectionText.length > 40
? `${labelSelectionText.slice(0, 40)}...`
: labelSelectionText;
};

const buttonText = getButtonText();

const debouncedQuery = useDebounce(query, 350);

Expand Down Expand Up @@ -143,16 +160,18 @@ export default function ComboBoxFilterMultiple({ filter }: Props) {

return (
<div className={`relative ${comboContainerStyles} hover:cursor-pointer`}>
<Measurer
value={buttonText}
visible={visible}
setVisible={setVisible}
impactedRef={filterBtnRef}
addedWidth={selectionText ? 40 : 2}
/>
{!isMobile && (
<Measurer
value={buttonText}
visible={visible}
setVisible={setVisible}
impactedRef={filterBtnRef}
addedWidth={selectionText ? 40 : 2}
/>
)}
<div
ref={filterBtnRef}
className="flex items-center w-full gap-4 overflow-hidden font-semibold text-left transition-all whitespace-nowrap sm:max-w-sm"
className="flex w-full items-center justify-between gap-4 overflow-hidden whitespace-nowrap text-left font-semibold transition-all sm:max-w-sm"
onClick={clickButton}
>
{buttonText}
Expand Down Expand Up @@ -181,7 +200,7 @@ export default function ComboBoxFilterMultiple({ filter }: Props) {
onChange={(e: React.FormEvent<HTMLInputElement>) => {
setQuery(e.currentTarget.value);
}}
className={`flex-1 bg-transparent font-semibold transition transition-all ease-in-out duration-500 focus:outline-0 placeholder:font-normal`}
className={`flex-1 bg-transparent font-semibold transition transition-all duration-500 ease-in-out placeholder:font-normal focus:outline-0`}
placeholder="search"
/>
<Combobox.Button ref={btnRef} className="display-none">
Expand Down
2 changes: 1 addition & 1 deletion app/components/bggStats/filters/FilterBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default function FilterBar() {

return (
<Container>
<div className="flex flex-wrap gap-2 mb-8 filters">
<div className="filters mb-8 flex flex-col flex-wrap gap-2 sm:flex-row">
{/* Filter components */}
{state.slice(1).map((filter: FilterType) => {
return <FilterToComponent key={filter.order} filter={filter} />;
Expand Down
2 changes: 1 addition & 1 deletion app/components/bggStats/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const openMultiComboboxMenuStyles = `
bg-slate-100 shadow-lg shadow-slate-500/20 z-10 w-full md:w-[350px] absolute left-0 top-[5.5rem] md:top-12 w-fit
`;
export const openComboboxMenuStyles = `
bg-slate-100 shadow-lg shadow-slate-500/20 z-10 w-full md:w-[350px] absolute left-0 top-[2.75rem] mt-1 w-fit
bg-slate-100 shadow-lg shadow-slate-500/20 z-10 w-[350px] absolute left-0 top-[2.75rem] mt-1 w-fit
`;

export const comboActiveItem = `
Expand Down
14 changes: 7 additions & 7 deletions app/components/bggStats/table/PaginationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function PaginationRow({ table }: Props) {
if (pageCount <= 1) return null;

return (
<div className="flex items-center justify-between gap-2 bg-white rounded-br-md rounded-bl-md ">
<div className="flex items-center justify-between gap-2 rounded bg-white sm:rounded-tl-none sm:rounded-tr-none ">
{/* Previous page buttons */}
<div>
<button
Expand All @@ -39,9 +39,9 @@ export default function PaginationRow({ table }: Props) {
</div>

{/* Pagination settings */}
<div className="flex justify-center flex-auto gap-8 py-4">
<span className="flex items-center gap-1">
Go to page:
<div className="flex flex-auto items-center justify-center gap-8 py-4">
<span className="flex flex-col items-center gap-1 xs:flex-row">
<span className="hidden sm:inline">Go to page:</span>
<input
type="number"
min={1}
Expand All @@ -51,16 +51,16 @@ export default function PaginationRow({ table }: Props) {
const page = e.target.value ? Number(e.target.value) - 1 : 0;
table.setPageIndex(page);
}}
className="w-16 px-1 border rounded "
className="w-16 rounded border px-1 text-center sm:text-left"
/>
of {pageCount}
<span>of {pageCount}</span>
</span>
<select
value={table.getState().pagination.pageSize}
onChange={(e) => {
table.setPageSize(Number(e.target.value));
}}
className="border rounded"
className="rounded border"
>
{[10, 25, 50, 100].map((pageSize) => (
<option key={pageSize} value={pageSize}>
Expand Down
75 changes: 75 additions & 0 deletions app/components/bggStats/table/RecordCards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { PlayDataModel } from "~/models/bgg/gameDataModels.js";
import { TrophyFilled, ExternalLink } from "../icons";
import dayjs from "dayjs";
import PaginationRow from "./PaginationRow.js";
import type { Table as TableType } from "@tanstack/table-core";
import type { FirstRecordRow } from "~/utils/conversion/getFirstPlayDateFromPlays";

type Props = {
table: TableType<PlayDataModel | FirstRecordRow>;
};
export default function RecordCards({ table }: Props) {
return (
<div className="grid gap-8">
<div className="grid gap-4">
{table.getRowModel().rows.map((row) => (
<Card key={row.id} data={row.original} />
))}
</div>
<PaginationRow table={table} />
</div>
);
}

function Card({ data }: { data: PlayDataModel }) {
return (
<a
className="mt-[3px] text-slate-600"
href={`https://www.boardgamegeek.com/play/details/${data.playId}`}
target="_blank"
rel="noopener noreferrer"
>
<div className="grid gap-6 rounded border bg-white p-2">
<div className="grid">
<div className="text-2xl font-semibold">{data.gameName}</div>
{data.players.length > 0 && (
<div className="flex flex-wrap items-center">
<Names players={data.players} />
</div>
)}
</div>

<div className="flex items-center justify-between text-sm text-slate-500">
<div>{dayjs(data.date).format("MMM DD, YYYY")}</div>
<div>{data.location}</div>
</div>
</div>
</a>
);
}

const Names = ({ players }: { players: PlayDataModel["players"] }) => {
let names = players.map((pdata, i, arr) => {
let length = arr.length;
let { userId, name, win, new: firstPlay } = pdata;
return (
<span className="inline-flex items-center" key={`${name}${userId}`}>
{win ? (
<TrophyFilled width={14} className="inline text-yellow-500" />
) : (
""
)}
{name}
{/* {firstPlay ? <NewBadge width={16} strokeWidth={1} /> : ""} */}
{i === length - 1 ? "" : ",\u00A0"}
</span>
);
});
return <>{names}</>;
};

type Row = {
id: string;
index: number;
original: PlayDataModel;
};

0 comments on commit 1eed156

Please sign in to comment.