Skip to content

Commit

Permalink
feat: add tag selection and improve ux
Browse files Browse the repository at this point in the history
  • Loading branch information
Rei-x committed Feb 10, 2023
1 parent e9b8fbd commit fbe0506
Show file tree
Hide file tree
Showing 14 changed files with 346 additions and 149 deletions.
38 changes: 38 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@next-auth/prisma-adapter": "^1.0.5",
"@next/font": "^13.1.6",
"@prisma/client": "^4.9.0",
"@tanstack/react-query": "^4.20.0",
"@trpc/client": "^10.9.0",
"@trpc/next": "^10.9.0",
"@trpc/react-query": "^10.9.0",
"@trpc/server": "^10.9.0",
"framer-motion": "^9.0.2",
"jotai": "^2.0.1",
"next": "13.1.6",
"next-auth": "^4.19.0",
"react": "18.2.0",
Expand Down
3 changes: 3 additions & 0 deletions src/atoms/selectedTags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { atom } from "jotai";

export const selectedTagsAtom = atom<string[]>([]);
13 changes: 13 additions & 0 deletions src/components/AnimatePresenceSSR.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AnimatePresence } from "framer-motion";
import type { ComponentProps } from "react";
import React from "react";

export const AnimatePresenceSSR = (
props: ComponentProps<typeof AnimatePresence>
) => {
return typeof window !== "undefined" ? (
<AnimatePresence {...props} />
) : (
<>{props.children}</>
);
};
10 changes: 9 additions & 1 deletion src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { chakra, Stack } from "@chakra-ui/react";
import type { ReactNode } from "react";
import React from "react";
import { Lato } from "@next/font/google";
import { Footer } from "./Footer";
import { Navbar } from "./Navbar";

const lato = Lato({
subsets: ["latin"],
weight: ["300", "400", "700"],
variable: "--font-lato",
display: "swap",
});

export const Layout = ({ children }: { children: ReactNode }) => {
return (
<Stack minH="100vh" justify="space-between">
<Stack minH="100vh" justify="space-between" className={`${lato.variable}`}>
<div>
<Navbar />
<chakra.main>{children}</chakra.main>
Expand Down
67 changes: 67 additions & 0 deletions src/components/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { RouterOutputs } from "@/utils/api";
import { InfoOutlineIcon } from "@chakra-ui/icons";
import type { BoxProps } from "@chakra-ui/react";
import { VStack, Wrap, WrapItem, Text, Box } from "@chakra-ui/react";
import { motion } from "framer-motion";
import React from "react";
import { AnimatePresenceSSR } from "./AnimatePresenceSSR";
import { Organisation } from "./Organisation";

export const List = ({
data,
...styles
}: {
data?: RouterOutputs["organizations"]["getAll"];
} & BoxProps) => {
return (
<Box {...styles}>
<AnimatePresenceSSR>
{data?.length === 0 ? (
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ type: "spring", duration: 0.4 }}
>
<VStack>
<InfoOutlineIcon mt={16} />
<Text size="md">
Brak organizacji, które spełniają twoje zapytanie
</Text>
</VStack>
</motion.div>
) : null}
</AnimatePresenceSSR>

<VStack>
{data && data?.length > 0 ? (
<Text color="GrayText" ml={10} fontSize="sm" alignSelf="start">
{data?.length} wyników
</Text>
) : null}
<Wrap
w={{ base: "100%", md: "900px" }}
spacing={4}
mx="auto"
justify="center"
>
<AnimatePresenceSSR mode="popLayout">
{data?.map((org) => (
<motion.div
key={org.id}
layout
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.8, opacity: 0, dur: 0.1 }}
transition={{ type: "spring", duration: 0.4 }}
>
<WrapItem p={2}>
<Organisation {...org} />
</WrapItem>
</motion.div>
))}
</AnimatePresenceSSR>
</Wrap>
</VStack>
</Box>
);
};
132 changes: 34 additions & 98 deletions src/components/Organisation.tsx
Original file line number Diff line number Diff line change
@@ -1,118 +1,54 @@
import {
Stack,
Heading,
Button,
Text,
Badge,
Center,
Flex,
useColorModeValue,
Wrap,
WrapItem,
VStack,
HStack,
IconButton,
} from "@chakra-ui/react";

import NextImage from "next/image";

const Tag = ({ tag }: { tag: string }) => {
return (
<Badge
px={2}
py={1}
bg={useColorModeValue("gray.50", "gray.800")}
fontWeight={"400"}
>
{tag}
</Badge>
);
};
import { FaHeart } from "react-icons/fa";
import { Tag } from "./Tag";

export const Organisation = ({
name,
description,
logoUrl,
tags,
}: {
name: string;
description: string;
logoUrl: string;
tags: string[];
}) => {
return (
<Center py={6}>
<Stack
borderWidth="1px"
borderRadius="lg"
w={{ sm: "100%", md: "540px" }}
height={{ sm: "476px", md: "20rem" }}
direction={{ base: "column", md: "row" }}
bg={useColorModeValue("white", "gray.900")}
boxShadow={"sm"}
padding={4}
>
<Flex flex={1} bg="blue.200" borderRadius="lg" justify="center">
<NextImage
style={{
objectFit: "cover",
objectPosition: "center",
borderRadius: "0.5rem",
}}
alt={name}
width={300}
height={300}
src={logoUrl}
/>
</Flex>
<Stack
flex={1}
maxW="300px"
flexDirection="column"
justifyContent="center"
alignItems="center"
p={1}
>
<Stack pt={3}>
<Heading fontSize={"xl"} fontFamily={"body"} textAlign="center">
{name}
</Heading>
<Text
textAlign={"center"}
color={useColorModeValue("gray.700", "gray.400")}
px={3}
>
{description}
</Text>
<Wrap align={"center"} justify={"center"} direction={"row"} mt={6}>
{tags.map((tag) => (
<WrapItem key={tag}>
<Tag tag={tag} />
</WrapItem>
))}
</Wrap>
</Stack>
<Stack
width={"100%"}
direction={"row"}
padding={2}
justifyContent={"space-between"}
alignItems={"center"}
>
<Button
flex={1}
fontSize={"sm"}
bg={"blue.400"}
color={"white"}
_hover={{
bg: "blue.500",
}}
_focus={{
bg: "blue.500",
}}
>
Więcej informacji
</Button>
</Stack>
</Stack>
</Stack>
</Center>
<VStack
p={6}
w="400px"
h="340px"
shadow="md"
justify="space-between"
align="start"
>
<VStack justifyContent="flex-start" align="start">
<Text fontSize="sm">W4</Text>
<Text fontWeight="semibold" fontSize="lg">
{name}
</Text>
<Wrap pt={2} direction="row">
{tags.map((tag) => (
<WrapItem key={tag}>
<Tag tag={tag} />
</WrapItem>
))}
</Wrap>
<Text pt={4} color="GrayText">
{description}
</Text>
</VStack>
<HStack mt="auto" spacing={4} justify="start">
<Button colorScheme="blue">Zobacz</Button>
<IconButton icon={<FaHeart />} aria-label="Dodaj do ulubionych" />
</HStack>
</VStack>
);
};
Loading

0 comments on commit fbe0506

Please sign in to comment.