Skip to content

Commit

Permalink
added workshop settings save after leaving
Browse files Browse the repository at this point in the history
  • Loading branch information
Andcool-Systems committed Nov 26, 2024
1 parent c2b06ea commit 000b7e4
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 50 deletions.
11 changes: 9 additions & 2 deletions src/app/modules/components/card.module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { usePathname, useRouter } from "next/navigation";
import { UseGlobalTooltip } from "./tooltip";
import useCookie from "../utils/useCookie.module";
import ApiManager from "../utils/apiManager";
import { useConfigContext } from "@/app/workshop/ConfigContext";


export const formatDate = (date: Date) => {
Expand Down Expand Up @@ -84,20 +85,26 @@ const backgrounds: { [key: string]: string } = {
default: 'default'
}

interface AnimatedLinkProps
interface ReferrerLinkProps
extends Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, "href">,
LinkProps {
children: ReactNode;
href: string;
}

export const ReferrerLink: React.FC<AnimatedLinkProps> = ({ children, href, ...props }) => {
export const ReferrerLink: React.FC<ReferrerLinkProps> = ({ children, href, ...props }) => {
const pathname = usePathname();
const router = useRouter();
const context = useConfigContext();

const handleTransition = async (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
e.preventDefault();
if (pathname.endsWith(href)) return;
window.sessionStorage.setItem('referrer', pathname);
if (context && context.lastConfig) {
const scroll = window.scrollY || document.documentElement.scrollTop;
window.sessionStorage.setItem('workshopState', JSON.stringify({ ...context.lastConfig, scroll }));
}
router.push(href);
};

Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/components/paginator.module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface PaginatorProps {
}

export const Paginator = ({ total_count, take, onChange, page }: PaginatorProps) => {
const [_page, _setPage] = useState<number>(0);
const [_page, _setPage] = useState<number>(page);
const [_pages, _setPages] = useState<JSX.Element[]>([]);

const [_totalCount, _setTotalCount] = useState<number>(total_count);
Expand Down
23 changes: 13 additions & 10 deletions src/app/modules/components/search.module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,42 @@ import style_workshop from "@/app/styles/workshop/page.module.css";
import { IconSearch, IconFilter } from '@tabler/icons-react';
import IconSvg from '@/app/resources/icon.svg';

const options: readonly { value: number, label: String }[] = [
const options_take: readonly { value: number, label: string }[] = [
{ value: 12, label: "12" },
{ value: 24, label: "24" },
{ value: 36, label: "36" },
{ value: 48, label: "48" },
];

const options_sortir: readonly { value: string, label: String }[] = [
const options_sortir: readonly { value: string, label: string }[] = [
{ value: 'relevant_up', label: 'По релевантности' },
{ value: 'popular_up', label: 'По популярности' },
{ value: 'date_up', label: 'По дате создания' },
{ value: 'name_up', label: 'По имени' }
];

interface SearchProps {
search: string,
onSearch(search: string): void,
onChangeTake(take: number): void,
onChangeSort(sort: string): void,
onChangeFilters(categories: Category[]): void,
sort: string,
take: number,
search: string,
categories: Category[]
}

export const Search = ({
search,
onSearch,
onChangeTake,
onChangeFilters,
onChangeSort,
categories
categories,
sort,
take,
search
}: SearchProps) => {
const [_search, _setSearch] = useState<string>(search || "");
const [_search, _setSearch] = useState<string>(search ?? '');
const [expanded, setExpanded] = useState<boolean>(false);
const [_categories, _setCategories] = useState<Category[]>([]);

Expand Down Expand Up @@ -72,7 +76,6 @@ export const Search = ({
/>
});


return (
<div className={Styles.parent}>
<div>
Expand Down Expand Up @@ -100,21 +103,21 @@ export const Search = ({
options={options_sortir}
className={`react-select-container ${Styles.select_sortir}`}
classNamePrefix="react-select"
defaultValue={options_sortir[0]}
onChange={(n, _) => onChangeSort(n.value)}
value={options_sortir.find(i => i.value === sort)}
isSearchable={false}
/>
</div>

<div style={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
<p className={Styles.take}>Отображать на странице</p>
<Select
options={options}
options={options_take}
className={`react-select-container ${Styles.select_take}`}
classNamePrefix="react-select"
defaultValue={options[0]}
isSearchable={false}
onChange={(n, _) => onChangeTake(n.value)}
value={options_take.find(i => i.value === take)}
/>
</div>

Expand Down
2 changes: 2 additions & 0 deletions src/app/modules/providers.module.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { useCookies } from "next-client-cookies";
import { Inter } from "next/font/google";
import { CSSProperties } from "react";
import WorkshopCacheListener from "./utils/workshopCacheListener.module";

const queryClient = new QueryClient();
const inter = Inter({ subsets: ["latin"] });
Expand Down Expand Up @@ -49,6 +50,7 @@ const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<QueryClientProvider client={queryClient}>
<html lang="ru" className={inter.className} style={theme as CSSProperties}>
<WorkshopCacheListener />
{children}
</html>
</QueryClientProvider>
Expand Down
18 changes: 18 additions & 0 deletions src/app/modules/utils/workshopCacheListener.module.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use client';

import { useEffect } from 'react';
import { usePathname } from 'next/navigation';

const WorkshopCacheListener = (): null => {
const pathname = usePathname();

useEffect(() => {
if (!pathname.startsWith('/workshop')) {
sessionStorage.removeItem('workshopState');
}
}, [pathname]);

return null;
};

export default WorkshopCacheListener;
14 changes: 14 additions & 0 deletions src/app/workshop/ConfigContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createContext, useContext } from "react";

export interface ConfigInterface {
page: number,
take: number,
search?: string,
filters?: string,
sort?: string,
totalCount: number,
scroll?: number
}

export const ConfigContext = createContext<{ lastConfig: ConfigInterface }>(null);
export const useConfigContext = () => useContext(ConfigContext);
125 changes: 88 additions & 37 deletions src/app/workshop/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React from "react";
import React, { createContext, useContext } from "react";
import { useEffect, useState } from "react";
import Header from "@/app/modules/components/header.module";
import Style from "@/app/styles/workshop/page.module.css";
Expand All @@ -18,7 +18,7 @@ import { useCookies } from "next-client-cookies";
import { renderSkin } from "../modules/utils/skinCardRender.module";
import { SimpleGrid } from "../modules/components/adaptiveGrid.module";
import ApiManager from "../modules/utils/apiManager";

import { ConfigContext, ConfigInterface } from "./ConfigContext";

export default function Home() {
const cookies = useCookies();
Expand All @@ -28,21 +28,59 @@ export default function Home() {
const [page, setPage] = useState<number>(0);
const [take, setTake] = useState<number>(12);
const [search, setSearch] = useState<string>('');
const [firstLoaded, setFirstLoaded] = useState<boolean>(false);

const [lastConfig, setLastConfig] = useState(null);
const [categories, setCategories] = useState<Category[]>([]);

const [filters, setFilters] = useState<Category[]>([]);
const [filters, setFilters] = useState<Category[]>([]); // Temp state for search callback
const [scroll, setScroll] = useState<number>(0);

const [sort, setSort] = useState<string>('relevant_up');
const [alertShown, setAlertShown] = useState<boolean>(false);


useEffect(() => {
ApiManager.getCategories().then(setCategories);
const workshopState = window.sessionStorage.getItem('workshopState');
ApiManager.getCategories().then(categories => {
if (workshopState) {
window.sessionStorage.removeItem('workshopState');

const data = JSON.parse(workshopState) as ConfigInterface;
data.page && setPage(data.page);
data.totalCount && setTotalCount(data.totalCount);
data.take && setTake(data.take);
data.search && setSearch(data.search);
data.sort && setSort(data.sort);
data.scroll && setScroll(data.scroll);

let _categories = categories;
if (data.filters) {
const initial_filters = data.filters.split(',').map(Number);
_categories = categories.map(i => {
if (initial_filters.includes(i.id)) i.enabled = true;
return i;
});
}
setFilters(_categories);
setCategories(_categories);
} else {
setCategories(categories);
setFilters(categories);
}

setFirstLoaded(true);
});

if (!workshopState) {
setFirstLoaded(true);
}
}, [])


useEffect(() => {
if (!firstLoaded) return;

const filters_str = filters.filter(filter => filter.enabled).map(filter => filter.id).toString();
const config = {
page: constrain(page, 0, Math.ceil(totalCount / take)),
Expand All @@ -61,7 +99,7 @@ export default function Home() {
});

setLastConfig(config);
}, [page, search, take, filters, sort])
}, [page, search, take, filters, sort, firstLoaded])


useEffect(() => {
Expand All @@ -76,40 +114,53 @@ export default function Home() {
top: 0,
behavior: "smooth"
});
}, [page])
}, [page]);

useEffect(() => {
if (elements && elements.length > 0 && scroll > 0) {
setScroll(0);
window.scrollTo({
top: scroll,
behavior: "smooth"
});
}
}, [elements]);

return (
<body>
<BrowserNotification
expanded={alertShown}
onClose={() => {
cookies.set('warningAccepted', 'true');
setAlertShown(false);
}}
/>
<Header />
<main className={Style.main}>
<div className={Style.center}>
<Search
search={search}
onSearch={setSearch}
onChangeTake={setTake}
categories={categories}
onChangeSort={setSort}
onChangeFilters={setFilters}
/>
{elements && elements.length > 0 &&
<Paginator total_count={totalCount} take={take} onChange={setPage} page={page} />}
{elements && elements.length > 0 ?
<SimpleGrid>{elements}</SimpleGrid> :
<TheresNothingHere elements={elements} />
}
{elements && elements.length > 0 &&
<Paginator total_count={totalCount} take={take} onChange={setPage} page={page} />}
</div>
<Footer />
</main>
</body>
<ConfigContext.Provider value={{ lastConfig: { ...lastConfig, totalCount } }}>
<body>
<BrowserNotification
expanded={alertShown}
onClose={() => {
cookies.set('warningAccepted', 'true');
setAlertShown(false);
}}
/>
<Header />
<main className={Style.main}>
<div className={Style.center}>
<Search
sort={sort}
take={take}
search={search}
categories={categories}
onSearch={setSearch}
onChangeTake={setTake}
onChangeSort={setSort}
onChangeFilters={setFilters} />
{elements && elements.length > 0 &&
<Paginator total_count={totalCount} take={take} onChange={setPage} page={page} />}
{elements && elements.length > 0 ?
<SimpleGrid>{elements}</SimpleGrid> :
<TheresNothingHere elements={elements} />
}
{elements && elements.length > 0 &&
<Paginator total_count={totalCount} take={take} onChange={setPage} page={page} />}
</div>
<Footer />
</main>
</body>
</ConfigContext.Provider>
);
}

Expand Down

0 comments on commit 000b7e4

Please sign in to comment.