Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.

Commit

Permalink
feat: add search and filtering to wishlist
Browse files Browse the repository at this point in the history
adjusts various styles to have more consistency (hover, active, focus...)
  • Loading branch information
pixelass committed Sep 10, 2021
1 parent 283ae01 commit f79348a
Show file tree
Hide file tree
Showing 34 changed files with 372 additions and 106 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"axios": "0.21.4",
"date-fns": "2.23.0",
"deepmerge": "4.2.2",
"focus-trap-react": "^8.7.1",
"focus-trap-react": "8.7.1",
"graphql": "15.5.3",
"lodash.isequal": "4.5.0",
"next": "11.1.2",
Expand All @@ -68,7 +68,8 @@
"react-textarea-autosize": "8.3.3",
"sitemap": "7.0.0",
"tslib": "2.3.1",
"use-cookie-consent": "^0.1.13",
"use-cookie-consent": "0.1.13",
"use-debounce": "7.0.0",
"zustand": "3.5.10"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion public/static/locales/de/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"CANNOT_UPDATE_VOTED_WISH": "Ein Wunsch mit Stimmen kann nicht bearbeitet werden.",
"CANNOT_UPDATE_MODERATED_WISH": "Ein Wunsch der moderiert wurde kann nicht bearbeitet werden."
},
"fields-labels": {
"field-labels": {
"search": "Suchen…",
"confirmPassword": "Passwort bestätigen",
"email": "E-Mail Adresse",
"firstName": "Vorname",
Expand Down
2 changes: 2 additions & 0 deletions public/static/locales/de/wishlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"update-wish": "Wunsch anpassen",
"wish": "Ich habe einen Wunsch"
},
"search-wishes": "Wünsche durchsuchen",
"filter": "Filter",
"pending": "Ausstehend",
"declined": "Abgelehnt",
"tooltip": {
Expand Down
3 changes: 2 additions & 1 deletion public/static/locales/en/form.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"CANNOT_UPDATE_VOTED_WISH": "Cannot update a wish that already has votes.",
"CANNOT_UPDATE_MODERATED_WISH": "Cannot update a wish that has been moderated."
},
"fields-labels": {
"field-labels": {
"search": "Search…",
"confirmPassword": "Confirm password",
"email": "E-mail address",
"firstName": "First name",
Expand Down
2 changes: 2 additions & 0 deletions public/static/locales/en/wishlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"update-wish": "Update wish",
"wish": "I have a wish"
},
"search-wishes": "Search wishes",
"filter": "Filter",
"pending": "Pending",
"declined": "Declined",
"tooltip": {
Expand Down
18 changes: 9 additions & 9 deletions src/atoms/button/styled.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { setOpacity } from "@/ions/utils/color";
import { pxToRem } from "@/ions/utils/unit";
import { css } from "@emotion/react";
import styled from "@emotion/styled";
Expand Down Expand Up @@ -73,7 +72,7 @@ export const StyledButton = styled.button<StyledButtonProps>`
&:active {
background: ${primary
? `${theme.palette.brandDark} linear-gradient(rgba(0,0,0,0.2), rgba(0,0,0,0.1))`
? `${theme.palette.brandDark} linear-gradient(rgba(0,0,0,0.1), rgba(0,0,0,0.1))`
: theme.ui.atoms.button.active.background};
color: ${primary ? theme.ui.colors.primary.color : "currentColor"};
}
Expand All @@ -83,11 +82,6 @@ export const StyledButton = styled.button<StyledButtonProps>`
}
&:focus-visible {
background: ${primary
? theme.palette.brandDark
: theme.ui.atoms.button.focus.background};
color: ${primary ? theme.ui.colors.primary.color : "currentColor"};
&::after {
content: "";
}
Expand Down Expand Up @@ -126,7 +120,14 @@ export const StyledLanguageButton = styled.button`
&:hover {
&::after {
content: "";
background: ${setOpacity(theme.palette.brand, 30)};
background: ${theme.ui.atoms.button.hover.background};
}
}
&:active {
&::after {
content: "";
background: ${theme.ui.atoms.button.active.background};
}
}
Expand All @@ -144,7 +145,6 @@ export const StyledLanguageButton = styled.button`
bottom: ${pxToRem(-theme.spaces.xs)};
left: ${pxToRem(-theme.spaces.xs)};
border-radius: ${theme.shapes.s};
background: ${theme.ui.atoms.button.focus.background};
}
${theme.mq.m} {
Expand Down
2 changes: 2 additions & 0 deletions src/atoms/floating-label/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import { StyledFloatingLabelProps } from "./types";
export const StyledFloatingLabel = styled.span<StyledFloatingLabelProps>`
display: flex;
position: absolute;
z-index: 1;
top: ${pxToRem(30)};
left: ${pxToRem(24)};
transform-origin: 0 0;
transition-property: transform;
will-change: transform;
transition-timing-function: ease-in-out;
font-weight: 400;
white-space: nowrap;
${({ theme, floating, initial }) =>
css`
transition-duration: ${initial ? "0s" : theme.speeds.fast};
Expand Down
1 change: 0 additions & 1 deletion src/atoms/icon-button/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const StyledIconButton = styled.button`
}
&:focus-visible {
background-color: ${theme.ui.atoms.button.focus.background};
box-shadow: inset 0 0 0 ${theme.borders.focusRing} ${theme.ui.colors.focusRing.border};
}
`};
Expand Down
1 change: 1 addition & 0 deletions src/atoms/input-wrapper/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StyledInputWrapperProps } from "./types";

export const StyledInputWrapper = styled.label<StyledInputWrapperProps>`
position: relative;
z-index: 0;
margin: 0 auto ${pxToRem(16)};
padding: 0;
Expand Down
33 changes: 30 additions & 3 deletions src/atoms/tag/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,40 @@ import { StyledTagProps } from "./types";

export const StyledTag = styled.span<StyledTagProps>`
width: max-content;
${({ theme, colorScheme }) => css`
padding: ${pxToRem(theme.spaces.xxs)} ${pxToRem(theme.spaces.xs)};
&:focus {
outline: 0;
}
${({ theme, colorScheme, as }) => css`
padding: ${pxToRem(as === "button" ? theme.spaces.xs : theme.spaces.xxs)}
${pxToRem(as === "button" ? theme.spaces.s : theme.spaces.xs)};
border-radius: ${theme.shapes.s};
font-size: ${pxToRem(14)};
font-size: ${pxToRem(as === "button" ? 16 : 14)};
line-height: ${pxToRem(as === "button" ? 32 : 18)};
font-weight: 600;
background: ${setOpacity(theme.palette[colorScheme], 20)};
box-shadow: inset 0 0 0 1px ${setOpacity(theme.palette[colorScheme], 20)};
&:hover {
background: ${setOpacity(theme.palette[colorScheme], 30)};
box-shadow: inset 0 0 0 1px ${setOpacity(theme.palette[colorScheme], 30)};
}
&:active {
background: ${setOpacity(theme.palette[colorScheme], 40)};
box-shadow: inset 0 0 0 1px ${setOpacity(theme.palette[colorScheme], 40)};
}
&:focus-visible {
box-shadow: inset 0 0 0 ${theme.borders.focusRing} ${theme.ui.colors.focusRing.border};
}
${theme.mq.m} {
padding: ${pxToRem(theme.spaces.xxs)} ${pxToRem(theme.spaces.xs)};
font-size: ${pxToRem(14)};
line-height: ${pxToRem(18)};
}
`};
`;

Expand Down
3 changes: 3 additions & 0 deletions src/atoms/tag/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Palette } from "@/types/theme";
import { ElementType, EventHandler, MouseEvent } from "react";

export interface StyledTagProps {
colorScheme: keyof Palette;
as?: ElementType;
onClick?: EventHandler<MouseEvent>;
}

export interface TagProps extends StyledTagProps {}
34 changes: 34 additions & 0 deletions src/ions/hooks/breakpoint/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { pxToRem } from "@/ions/utils/unit";
import { Sizes } from "@/types/theme";
import { useTheme } from "@emotion/react";
import { useEffect, useState } from "react";

export const useBreakpoint = (size: keyof Sizes, defaultState = false) => {
const theme = useTheme();
const query = `(min-width: ${pxToRem(theme.breakpoints[size])})`;
const [state, setState] = useState(
typeof window === "undefined" ? defaultState : window.matchMedia(query).matches
);

useEffect(() => {
let mounted = true;
const mediaQueryList = window.matchMedia(query);
const onChange = () => {
if (!mounted) {
return;
}

setState(mediaQueryList.matches);
};

mediaQueryList.addEventListener("change", onChange);
setState(mediaQueryList.matches);

return () => {
mounted = false;
mediaQueryList.removeEventListener("change", onChange);
};
}, [query]);

return state;
};
11 changes: 9 additions & 2 deletions src/ions/hooks/scroll-y/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { useEffect, useState } from "react";

export const useScrollY = (active?: boolean) => {
export const useScrollY = (active = false) => {
const [scrollY, setScrollY] = useState(0);

useEffect(() => {
const handleScroll = () => {
setScrollY(window.scrollY);
if (active) {
setScrollY(window.scrollY);
} else {
setScrollY(0);
}
};

const unsubscribe = () => {
Expand All @@ -13,6 +18,8 @@ export const useScrollY = (active?: boolean) => {

if (active) {
window.addEventListener("scroll", handleScroll, { passive: true });
} else {
window.removeEventListener("scroll", handleScroll);
}

return unsubscribe;
Expand Down
29 changes: 27 additions & 2 deletions src/ions/queries/wishes.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import { gql } from "@apollo/client";

export const WISHES = gql`
query wishes {
wishes(orderBy: { createdAt: desc }) {
query wishes($query: String!) {
wishes(
orderBy: { createdAt: desc }
where: { OR: [{ subject: { contains: $query } }, { body: { contains: $query } }] }
) {
authorId
body
id
subject
voted
votes
moderate
}
}
`;

export const MY_WISHES = gql`
query myWishes($query: String!, $authorId: Int!) {
wishes(
orderBy: { createdAt: desc }
where: {
AND: [
{ OR: [{ subject: { contains: $query } }, { body: { contains: $query } }] }
{ authorId: { equals: $authorId } }
]
}
) {
authorId
body
id
Expand Down
9 changes: 9 additions & 0 deletions src/ions/stores/query/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import create from "zustand";
import { QueryStore } from "./types";

export const useSearchQuery = create<QueryStore>(set => ({
query: "",
setQuery: query => {
set({ query });
},
}));
4 changes: 4 additions & 0 deletions src/ions/stores/query/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface QueryStore {
query: string;
setQuery(value: string): void;
}
3 changes: 3 additions & 0 deletions src/ions/stores/wish/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ export const useWish = create<WishStore>(set => ({
setSubject: subject => {
set({ subject });
},
clear: () => {
set({ body: undefined, id: undefined, subject: undefined });
},
}));
1 change: 1 addition & 0 deletions src/ions/stores/wish/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export interface WishStore {
setId(value?: number): void;
setBody(value?: string): void;
setSubject(value?: string): void;
clear(): void;
}
10 changes: 5 additions & 5 deletions src/ions/theme/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ export const grid: GridConfig = {
export const layout: Layout = {
header: {
height: {
xs: 64,
s: 64,
m: 64,
l: 96,
xl: 96,
xs: 68,
s: 68,
m: 68,
l: 68,
xl: 68,
},
},
};
Expand Down
2 changes: 1 addition & 1 deletion src/molecules/input-field/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const InputField: FC<InputFieldProps> = ({
initial={isValid}
id={`${id}_label`}
>
{t(`form:fields-labels.${name}`)}
{t(`form:field-labels.${name}`)}
{required && <StyledRequiredIndicator>*</StyledRequiredIndicator>}
</StyledFloatingLabel>
<StyledInput
Expand Down
2 changes: 1 addition & 1 deletion src/molecules/input-field/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Except } from "type-fest";
export interface InputFieldProps extends Except<HTMLProps<HTMLInputElement>, "onChange"> {
fullWidth?: boolean;
autoFocus?: boolean;
validation: RegisterOptions;
validation?: RegisterOptions;
args?: Record<string, string | number>;
testId?: string;
helpText?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/molecules/textarea-field/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const TextArea: FC<TextAreaFieldProps> = ({
initial={isValid}
id={`${id}_label`}
>
{t(`form:fields-labels.${name}`)}
{t(`form:field-labels.${name}`)}
{required && <StyledRequiredIndicator>*</StyledRequiredIndicator>}
</StyledFloatingLabel>
<StyledTextArea
Expand Down
4 changes: 3 additions & 1 deletion src/organisms/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Icon from "@/atoms/icon";
import IconButton from "@/atoms/icon-button";
import Logo from "@/atoms/logo";
import Typography from "@/atoms/typography";
import { useBreakpoint } from "@/ions/hooks/breakpoint";
import { useScrollY } from "@/ions/hooks/scroll-y";
import Drawer from "@/molecules/drawer";
import {
Expand All @@ -21,7 +22,8 @@ import { HeaderProps } from "./types";
const Header: FC<HeaderProps> = ({ children, className, dark, innerRef, testId }) => {
const { t } = useTranslation(["navigation"]);
const { route } = useRouter();
const scrollY = useScrollY(true);
const isLargeScreen = useBreakpoint("l");
const scrollY = useScrollY(isLargeScreen);
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const isIndented = scrollY > 150 && route === "/wishlist";

Expand Down
3 changes: 2 additions & 1 deletion src/organisms/header/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ export const StyledHeader = styled.header<StyledHeaderProps>`
z-index: 1;
align-content: center;
align-items: center;
height: ${pxToRem(68)};
${({ theme, dark, elevated }) => css`
padding: ${pxToRem(theme.spaces.xs)} 0;
height: ${pxToRem(theme.layout.header.height.xs)};
${theme.mq.l} {
position: sticky;
top: 0;
height: ${pxToRem(theme.layout.header.height.l)};
background-color: ${dark
? theme.ui.colors.dark.background
: theme.ui.colors.light.background};
Expand Down
Loading

0 comments on commit f79348a

Please sign in to comment.