Skip to content

Commit

Permalink
Crags todos (#41)
Browse files Browse the repository at this point in the history
* Move sort state to query state.

* Save selected columns to localstorage.

* Added 'dodaj plezalisce' cta to the end of crags list.

* Align actions row to center.

* Add message when filters produce no results. Also hide table header in this case.

* Adjust nr label for routes/boulders/both cases.

* Adjust padding on table/compact and fix compact/table switching.

* Fix columns in localstorage.

* Fix range slider so that the thumbs do not exceed container at the far end positions.

* Export approach time filter to component and make it collapsible.

* Add filter chips and reorganize crag filters.

* Fix top horizontal divider when filter chips are active.

* Update useQueryState library.

* Completely reorganize crags. Use context. Temporarily under crags2 page.

* Fix 'smer' plural in filters pane.

* Remove temp crags and replace it with new crags2.

* Fix navi and breadcrumbs links to crags page.
  • Loading branch information
salamca committed Jun 9, 2024
1 parent 54cbb70 commit 89ce78e
Show file tree
Hide file tree
Showing 36 changed files with 1,649 additions and 1,160 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"leaflet": "^1.9.4",
"next": "^14.1.4",
"next-cookies": "^2.0.3",
"next-usequerystate": "^1.13.1",
"next-usequerystate": "^1.17.4",
"react": "^18.2.0",
"react-aria": "^3.21.0",
"react-dom": "^18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function CragHeader({ crag }: Props) {
},
{
label: "Plezališča",
link: `/plezalisca/${crag.country.slug}`,
link: `/plezalisca?country=${crag.country.slug}`,
},
{
label: crag.name,
Expand Down
100 changes: 100 additions & 0 deletions src/app/[lang]/crags/components/actions-row/actions-row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import Button from "@/components/ui/button";
import IconClose from "@/components/ui/icons/close";
import IconMore from "@/components/ui/icons/more";
import IconSearch from "@/components/ui/icons/search";
import TextField from "@/components/ui/text-field";
import { useRef, useState } from "react";
import ShowMap from "./show-map";
import ToggleFiltersPane from "./toggle-filters-pane";
import SelectColumns from "./select-columns";
import Sort from "./sort";
import { useCragsContext } from "../crags-context";

function ActionsRow() {
const { search } = useCragsContext();

const [searchFocus, setSearchFocus] = useState(false);

const searchFieldRef = useRef<HTMLInputElement>(null);
const handleSearchIconClick = () => {
setSearchFocus(true);

setTimeout(() => {
searchFieldRef.current && searchFieldRef.current.focus();
}, 0);
};

return (
<>
{/* Actions row */}
{/*
for <sm: all icons, including search are displayed centered.
for >=sm: search icon becomes search text field and sticks right, all other icons stick left
for <md: filter pane is triggered by filter icon
for >=md: filter pane is always visible, filter icon dissapears
*/}

<div
className={`x-auto relative z-10 mx-auto rotate-0 items-center justify-center border-b border-b-neutral-200 px-4 2xl:container xs:px-8 sm:justify-between md:border-b-0 ${
searchFocus || search.query ? "block sm:flex" : "flex justify-center"
}`}
>
<div className="flex items-center justify-center py-4 sm:py-5">
<ShowMap />

<ToggleFiltersPane />

<div className="ml-3 h-6 border-l border-neutral-300 pr-3"></div>

<SelectColumns />

<div className="ml-3 h-6 border-l border-neutral-300 pr-3"></div>

<Sort />

<div className="flex items-center sm:hidden">
<div className="ml-3 h-6 border-l border-neutral-300 pr-3"></div>
<Button variant="quaternary" onClick={handleSearchIconClick}>
<IconSearch />
</Button>
</div>

<div className="ml-3 h-6 border-l border-neutral-300 pr-3"></div>
<Button variant="quaternary">
<IconMore />
</Button>
</div>

<div
className={`min-w-0 sm:ml-8 sm:w-80 ${
searchFocus || search.query
? "mb-6 block sm:mb-0"
: "hidden sm:block"
}`}
>
<TextField
ref={searchFieldRef}
value={search.query}
onChange={search.setQuery}
onBlur={() => setSearchFocus(false)}
prefix={<IconSearch />}
placeholder="Poišči po imenu"
aria-label="Poišči po imenu"
suffix={
search.query && (
<Button
variant="quaternary"
onClick={() => search.setQuery("")}
>
<IconClose />
</Button>
)
}
/>
</div>
</div>
</>
);
}

export default ActionsRow;
34 changes: 34 additions & 0 deletions src/app/[lang]/crags/components/actions-row/select-columns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Button from "@/components/ui/button";
import IconColumns from "@/components/ui/icons/columns";
import { Select, Option } from "@/components/ui/select";
import { useCragsContext } from "../crags-context";

function SelectColumns() {
const { columns } = useCragsContext();

return (
<Select
multi
customTrigger={
<Button variant="quaternary">
<div className="flex">
<IconColumns />
<span className="ml-2 max-lg:hidden">Izberi stolpce</span>
</div>
</Button>
}
value={columns.selectedState}
onChange={columns.setSelectedState}
>
{columns.all
.filter((column) => column.isOptional)
.map((column) => (
<Option key={column.name} value={column.name}>
{column.label}
</Option>
))}
</Select>
);
}

export default SelectColumns;
14 changes: 14 additions & 0 deletions src/app/[lang]/crags/components/actions-row/show-map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Button from "@/components/ui/button";
import IconMap from "@/components/ui/icons/map";

function ShowMap() {
return (
<Button variant="quaternary">
<div className="flex">
<IconMap />
<span className="ml-2 max-lg:hidden">Pokaži zemljevid</span>
</div>
</Button>
);
}
export default ShowMap;
38 changes: 38 additions & 0 deletions src/app/[lang]/crags/components/actions-row/sort.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Button from "@/components/ui/button";
import IconSort from "@/components/ui/icons/sort";
import { Select, Option } from "@/components/ui/select";
import { useCragsContext } from "../crags-context";

function Sort() {
const {
sort: { sort, setSort },
} = useCragsContext();

return (
<Select
customTrigger={
<Button variant="quaternary">
<div className="flex">
<IconSort />
<span className="ml-2 max-lg:hidden">Uredi</span>
</div>
</Button>
}
value={sort}
onChange={setSort}
>
<Option value="name,asc">Po abecedi, naraščajoče</Option>
<Option value="name,desc">Po abecedi, padajoče</Option>
<Option value="nrRoutes,asc">Po št. smeri, naraščajoče</Option>
<Option value="nrRoutes,desc">Po št. smeri, padajoče</Option>
<Option value="maxDifficulty,asc">Po najtežji smeri, naraščajoče</Option>
<Option value="maxDifficulty,desc">Po najtežji smeri, padajoče</Option>
<Option value="minDifficulty,asc">Po najlažji smeri, naraščajoče</Option>
<Option value="minDifficulty,desc">Po najlažji smeri, padajoče</Option>
<Option value="approachTime,asc">Po času dostopa, naraščajoče</Option>
<Option value="approachTime,desc">Po času dostopa, padajoče</Option>
</Select>
);
}

export default Sort;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Button from "@/components/ui/button";
import IconFilter from "@/components/ui/icons/filter";
import { useCragsContext } from "../crags-context";

function ToggleFiltersPane() {
const {
filtersPane: { toggleOpen },
} = useCragsContext();

return (
<div className="flex items-center md:hidden">
<div className="ml-3 h-6 border-l border-neutral-300 pr-3"></div>
<Button variant="quaternary" onClick={toggleOpen}>
<IconFilter />
</Button>
</div>
);
}

export default ToggleFiltersPane;
18 changes: 0 additions & 18 deletions src/app/[lang]/crags/components/crag-list-cards.tsx

This file was deleted.

52 changes: 0 additions & 52 deletions src/app/[lang]/crags/components/crag-list-table.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useCragsContext } from "../../crags-context";
import FilterChip from "./filter-chip";

function ActiveFilters() {
const {
filters: { filters },
} = useCragsContext();

const activeFilters = Object.values(filters).filter(
(filter) => filter.isActive
);

return (
<>
{activeFilters.length > 0 && (
<div className="mx-2 flex flex-wrap gap-2 border-b border-b-neutral-200 py-2 xs:mx-8 md:mx-0 md:border-b-0 md:pt-0">
{activeFilters.map((filter, index) => (
<FilterChip
key={index}
label={filter.label}
value={filter.stringValue}
onReset={filter.onReset}
/>
))}
</div>
)}
</>
);
}

export default ActiveFilters;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Button from "@/components/ui/button";
import IconClose from "@/components/ui/icons/close";

type TFilterChipProps = {
label: string;
value: string;
onReset: () => void;
};

function FilterChip({ label, value, onReset }: TFilterChipProps) {
return (
<div className="inline-flex items-center rounded-lg bg-blue-50 py-px pl-3 pr-2">
<div>
{label}: {value}
</div>
<Button variant="quaternary" onClick={onReset}>
<IconClose />
</Button>
</div>
);
}

export default FilterChip;
Loading

0 comments on commit 89ce78e

Please sign in to comment.