Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: filters save in local storage #87

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: useFilter hook add
  • Loading branch information
vatsalsinghkv committed Oct 29, 2024
commit 7ecd9546ef84c6f7fd32fe4eebb8acdefdf76dc0
62 changes: 28 additions & 34 deletions src/containers/Filter.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,24 @@
import { MiniContainer, Select } from '@/components';
import SortingTagFilter from '@/components/SortingTagFilter';
import { useFilter } from '@/lib/hooks/use-filter';
import { toId } from '@/lib/utils';
import { Label, sortedLabels } from '@/models/Label';
import { Language, sortedLanguages } from '@/models/Language';
import { SortingTag, sortedSortingTags } from '@/models/SortingTag';
import { useUrlValues } from '@/providers/urlProvider';
import { FormEvent, useState } from 'react';
import { sortedLanguages } from '@/models/Language';
import { sortedSortingTags } from '@/models/SortingTag';

const Filter = () => {
const [customLabel, setCustomLabel] = useState("");

const [labels, setLabels] = useState(sortedLabels);

const customLabelHandler = (e: FormEvent) => {
e.preventDefault();
setLabels([...labels, customLabel]);
onLabelChange(customLabel);
setCustomLabel("");
}

const { dispatch, language, ordering, sortingTag, label } = useUrlValues();

const onLanguageChange = (payload: Language) => {
return () => dispatch({ type: 'update-language', payload });
};

const onLabelChange = (payload: Label) => {
return () => dispatch({ type: 'update-label', payload });
};

const onSortingTagClick = (payload: SortingTag) => {
return () => dispatch({ type: 'update-sorting-tag', payload });
};
const {
language,
label,
labels,
ordering,
sortingTag,
customLabel,
customLabelHandler,
languageChangeHandler,
labelsChangeHandler,
sortingTagClickHandler,
setCustomLabel,
} = useFilter();

return (
<>
@@ -43,7 +30,7 @@ const Filter = () => {
value={lang}
checked={lang === language}
name={lang}
onChange={onLanguageChange(lang)}
onChange={languageChangeHandler(lang)}
/>
</li>
))}
@@ -58,16 +45,23 @@ const Filter = () => {
value={l}
checked={l === label}
name={l}
onChange={onLabelChange(l)}
onChange={labelsChangeHandler(l)}
/>
</li>
))}
</ul>
<form className='mt-2' onSubmit={(e) => { customLabelHandler(e) }}>
<form
className='mt-2'
onSubmit={(e) => {
customLabelHandler(e);
}}
>
<input
value={customLabel}
type='input'
onChange={(e) => { setCustomLabel(e.target.value) }}
onChange={(e) => {
setCustomLabel(e.target.value);
}}
placeholder='+ add custom label'
className='block bg-transparent p-3 py-1.5 font-mono text-xs capitalize transition-all border rounded cursor-pointer hover:text-accent hover:border-accent focus:text-accent focus:border-accent border-dark-2 peer-hover:border-accent peer-focus:border-accent peer-focus:text-accent peer-checked:text-accent peer-checked:border-accent peer-checked:bg-accent-light peer-focus:outline-none'
/>
@@ -80,7 +74,7 @@ const Filter = () => {
<li key={tag}>
<SortingTagFilter
isSelected={tag === sortingTag}
onClick={onSortingTagClick(tag)}
onClick={sortingTagClickHandler(tag)}
ordering={ordering}
value={tag}
/>
3 changes: 3 additions & 0 deletions src/containers/Provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Provider({ children }: { children: React.ReactNode }) {
return;
}
91 changes: 91 additions & 0 deletions src/lib/hooks/use-filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Label, sortedLabels } from '@/models/Label';
import { Language } from '@/models/Language';
import { Ordering } from '@/models/Ordering';
import { SortingTag } from '@/models/SortingTag';
import { useUrlValues } from '@/providers/urlProvider';
import { FormEvent, createContext, useContext, useState } from 'react';

// Define the type for the context state
type FilterContextType = {
customLabel: string;
language: Language;
label: string;
ordering: Ordering;
sortingTag: SortingTag;
labels: Label[];
customLabelHandler: (e: FormEvent) => void;
setCustomLabel: (label: string) => void;
languageChangeHandler: (payload: Language) => () => void;
labelsChangeHandler: (payload: Label) => () => void;
sortingTagClickHandler: (payload: SortingTag) => () => void;
};

const initialState: FilterContextType = {
customLabel: '',
language: 'all',
label: 'hacktoberfest',
ordering: 'asc',
sortingTag: 'best-match',
labels: sortedLabels,
customLabelHandler: () => {},
setCustomLabel: () => {},
languageChangeHandler: () => () => {},
labelsChangeHandler: () => () => {},
sortingTagClickHandler: () => () => {},
};

const FilterContext = createContext<FilterContextType>(initialState);

export default function FilterProvider({
children,
}: {
children: React.ReactNode;
}) {
const [customLabel, setCustomLabel] = useState<string>('');
const [labels, setLabels] = useState<Label[]>(sortedLabels);

const customLabelHandler = (e: FormEvent) => {
e.preventDefault();
setLabels([...labels, customLabel]);
labelsChangeHandler(customLabel as Label)();
setCustomLabel('');
};

const { dispatch, language, ordering, sortingTag, label } = useUrlValues();

const languageChangeHandler = (payload: Language) => {
return () => dispatch({ type: 'update-language', payload });
};

const labelsChangeHandler = (payload: Label) => {
return () => dispatch({ type: 'update-label', payload });
};

const sortingTagClickHandler = (payload: SortingTag) => {
return () => dispatch({ type: 'update-sorting-tag', payload });
};

return (
<FilterContext.Provider
value={{
customLabel,
label,
language,
ordering,
sortingTag,
labels,
customLabelHandler,
languageChangeHandler,
labelsChangeHandler,
sortingTagClickHandler,
setCustomLabel,
}}
>
{children}
</FilterContext.Provider>
);
}

export function useFilter() {
return useContext(FilterContext);
}
5 changes: 4 additions & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
@@ -3,14 +3,17 @@ import '@/index.css';
import React from 'react';
import ReactDOM from 'react-dom/client';

import FilterProvider from './lib/hooks/use-filter';
import ThemeProvider from './lib/hooks/use-theme';
import UrlProvider from './providers/urlProvider';

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<UrlProvider>
<ThemeProvider>
<App />
<FilterProvider>
<App />
</FilterProvider>
</ThemeProvider>
</UrlProvider>
</React.StrictMode>