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

[RSN-75] - Implemented swiping for suggestions #77

Merged
merged 1 commit into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
141 changes: 141 additions & 0 deletions Client/reasn-client/apps/web/app/events/suggestions/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"use client";

import { Card, CardVariant } from "@reasn/ui/src/components/shared";
import { Add, Dismiss, Question } from "@reasn/ui/src/icons";
import clsx from "clsx";
import React, { MouseEvent, useState } from "react";

const EventsSuggestionsPage = () => {
const [events, setEvents] = useState<number[]>([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
]);
const currentCardRef = React.useRef<HTMLDivElement>(null);
const nextCardRef = React.useRef<HTMLDivElement>(null);
const [isAnimating, setIsAnimating] = useState(false);
const [action, setAction] = useState<"like" | "dislike" | "participate" | "">(
"",
);

const handleDismissEvent = (e: MouseEvent<HTMLElement>) => {
currentCardRef.current?.classList.add("animate-fadeOutLeft");
setIsAnimating(true);
setAction("dislike");
setTimeout(() => {
currentCardRef.current?.classList.remove("animate-fadeOutLeft");
setEvents((prev) => prev.slice(1));
setIsAnimating(false);
setAction("");
}, 500);
e.stopPropagation();
};

const handleLikeEvent = (e: MouseEvent<HTMLElement>) => {
currentCardRef.current?.classList.add("animate-fadeOutDown");
setIsAnimating(true);
setAction("like");
setTimeout(() => {
currentCardRef.current?.classList.remove("animate-fadeOutDown");
setEvents((prev) => prev.slice(1));
setIsAnimating(false);
setAction("");
}, 500);
e.stopPropagation();
};

const handleParticipateInEvent = (e: MouseEvent<HTMLElement>) => {
currentCardRef.current?.classList.add("animate-fadeOutRight");
setIsAnimating(true);
setAction("participate");
setTimeout(() => {
currentCardRef.current?.classList.remove("animate-fadeOutRight");
setEvents((prev) => prev.slice(1));
setIsAnimating(false);
setAction("");
}, 500);
e.stopPropagation();
};

return (
<div className="relative flex w-full flex-col items-center justify-center">
<div
className={clsx(
"absolute right-[-50%] top-[-25%] z-0 h-[50%] w-[200%] rounded-full blur-3xl",
"bg-blue-400 duration-1000",
{ "opacity-30": action === "like" },
{ "opacity-10": action !== "like" },
)}
></div>
<div
className={clsx(
"absolute left-[-50%] top-[-25%] z-0 h-[100%] w-[100%] rounded-full blur-3xl",
"bg-red-400 duration-1000",
{ "opacity-30": action === "dislike" },
{ "opacity-10": action !== "dislike" },
)}
></div>
<div
className={clsx(
"absolute right-[-50%] top-[-25%] z-0 h-[100%] w-[100%] rounded-full blur-3xl",
"bg-green-400 duration-1000",
{ "opacity-30": action === "participate" },
{ "opacity-10": action !== "participate" },
)}
></div>
<div className="relative h-[60vh] w-full items-center justify-center">
{events.map((val, idx) => (
<div
key={val + idx}
className={clsx(
"absolute left-1/2 duration-500",
{ "pointer-events-none": idx !== 0 },
{ "opacity-5 blur-sm": idx > 1 || (idx === 1 && !isAnimating) },
{ "opacity-1 blur-none": idx === 1 && isAnimating },
{ "opacity-1 pointer-events-auto": idx === 0 },
)}
style={{
transform: `translate(-50%, ${idx * 1.5}%)`,
zIndex: `${11 - idx}`,
}}
ref={idx === 0 ? currentCardRef : idx === 1 ? nextCardRef : null}
>
<Card variant={CardVariant.Swiping} event="Abc" />
</div>
))}
</div>
<div className="flex w-full items-center justify-center gap-10 lg:gap-24">
<div
onClick={handleDismissEvent}
className={clsx(
"flex h-12 w-28 cursor-pointer items-center justify-center rounded-full",
"bg-red-500 bg-opacity-40 p-2 text-2xl font-semibold",
"group duration-300 hover:bg-red-700",
)}
>
<Dismiss className="h-5 w-5 fill-red-500 duration-300 group-hover:fill-black" />
</div>
<div
onClick={handleLikeEvent}
className={clsx(
"flex h-12 w-16 cursor-pointer items-center justify-center rounded-full",
"bg-blue-400 bg-opacity-40 p-2 text-2xl font-semibold",
"group duration-300 hover:bg-blue-700",
)}
>
<Question className="h-5 w-5 fill-blue-400 duration-300 group-hover:fill-black" />
</div>
<div
onClick={handleParticipateInEvent}
className={clsx(
"flex h-12 w-28 cursor-pointer items-center justify-center rounded-full",
"bg-green-500 bg-opacity-40 p-2 text-2xl font-semibold",
"group duration-300 hover:bg-green-700",
)}
>
<Add className="h-5 w-5 fill-green-500 duration-300 group-hover:fill-black" />
</div>
</div>
</div>
);
};

export default EventsSuggestionsPage;
2 changes: 1 addition & 1 deletion Client/reasn-client/apps/web/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const middleware = (req: NextRequest) => {

if (path.startsWith("/events") && session.user?.role === UserRole.USER) {
return NextResponse.redirect(new URL("/events", req.url));
}
}
};

export const config = {
Expand Down
22 changes: 22 additions & 0 deletions Client/reasn-client/apps/web/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ module.exports = {
screens: {
xs: "460px",
},
keyframes: {
fadeOutRight: {
"0%": { transform: "translateX(-50%) rotate(0deg)", opacity: 1 },
"100%": { transform: "translateX(100%) rotate(30deg)", opacity: 0 },
},
fadeOutLeft: {
"0%": { transform: "translateX(-50%) rotate(0deg)", opacity: 1 },
"100%": { transform: "translateX(-150%) rotate(-30deg)", opacity: 0 },
},
fadeOutDown: {
"0%": { transform: "translateX(-50%) translateY(0%)", opacity: 1 },
"100%": {
transform: "translateX(-50%) translateY(-100%)",
opacity: 0,
},
},
},
animation: {
fadeOutRight: "fadeOutRight 0.5s ease-in-out forwards",
fadeOutLeft: "fadeOutLeft 0.5s ease-in-out forwards",
fadeOutDown: "fadeOutDown 0.5s ease-in-out forwards",
},
},
},
plugins: [],
Expand Down
30 changes: 30 additions & 0 deletions Client/reasn-client/packages/ui/src/components/shared/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export enum CardVariant {
Big,
Tile,
List,
Swiping,
}

export interface CardProps {
Expand All @@ -31,6 +32,7 @@ export const Card = (props: Readonly<CardProps>) => {
{variant === CardVariant.Big && <CardBig event={event} />}
{variant === CardVariant.Tile && <CardTile event={event} />}
{variant === CardVariant.List && <CardList event={event} />}
{variant === CardVariant.Swiping && <CardSwiping event={event} />}
</div>
);
};
Expand Down Expand Up @@ -145,3 +147,31 @@ const CardList = ({ event }: { event: string }) => {
</div>
);
};

const CardSwiping = ({ event }: { event: string }) => {
return (
<div className="group relative h-[45vh] w-[20vw] min-w-[15em] cursor-pointer overflow-clip rounded-3xl md:h-[50vh] md:min-h-[10em] md:min-w-[20em] lg:min-h-[25em] lg:min-w-[25em]">
<img
src={MOCK_IMG_URL}
alt=""
className="absolute left-0 top-0 h-full object-cover"
/>
<div className="relative flex h-2/3 w-full flex-col gap-2 bg-[#232326ee] p-4 text-[#F7F8F8]">
<div className="flex flex-wrap gap-1 text-xs text-[#cacaca]">
<p className="rounded-md bg-[#4b4e52] px-[5px] py-[1px]">#abcd</p>
<p className="rounded-md bg-[#4b4e52] px-[5px] py-[1px]">#abcd</p>
<p className="rounded-md bg-[#4b4e52] px-[5px] py-[1px]">#abcd</p>
<p className="rounded-md bg-[#4b4e52] px-[5px] py-[1px]">#abcd</p>
</div>
<h2 className="w-4/5 break-words text-3xl font-semibold">
Koncert fagaty na PWR w C-16
</h2>
<p className="hidden text-base text-[#cacaca] md:block">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Unde
quisquam maiores doloremque molestiae ducimus, distinctio accusamus
sed voluptatem eius itaque.
</p>
</div>
</div>
);
};
17 changes: 3 additions & 14 deletions Client/reasn-client/packages/ui/src/components/shared/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
import React from "react";
import {
CommentDto,
CommentDtoMapper,
} from "@reasn/common/src/schemas/CommentDto";
import { ButtonBase, FloatingTextarea } from "./form";

interface CommentProps {
comment?: CommentDto;
comment?: string;
}

export const Comment = (props: CommentProps) => {
const comment = CommentDtoMapper.fromObject({
EventId: 1,
Content:
"Lorem ipsum dolor, sit amet consectetur adipisicing elit. Soluta quidem sapiente odit maxime. Officiis, error laborum. Voluptatem quibusdam mollitia possimus?",
CreatedAt: new Date(),
UserId: 1,
});

const { comment } = props;
return (
<div className="flex flex-col gap-4 rounded-md bg-[#4b4e526d] p-2">
<p className="font-thin">{comment.Content}</p>
<p className="font-thin">{comment}</p>
<div className="flex items-center gap-2">
<div className="relative rounded-full bg-gradient-to-r from-[#32346A] to-[#4E4F75] p-[2px]">
<img
Expand Down
40 changes: 40 additions & 0 deletions Client/reasn-client/packages/ui/src/icons/Add.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { IconProps } from "./IconProps";

export const Add = (props: IconProps) => {
const { className, colors, gradientTransform, onClick } = props;

return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
className={className}
viewBox="0 0 24 24"
fill="url(#gradient1)"
onClick={onClick}
>
<defs>
<linearGradient
id="gradient1"
x1="0%"
y1="0%"
x2="100%"
y2="0%"
gradientTransform={gradientTransform}
>
{colors?.map((color, index) => (
<stop
key={index}
offset={`${
index + 1 < colors.length ? index * (100 / colors.length) : 100
}%`}
style={{ stopColor: color, stopOpacity: 1 }}
/>
))}
</linearGradient>
</defs>
<path d="M11.883 3.007 12 3a1 1 0 0 1 .993.883L13 4v7h7a1 1 0 0 1 .993.883L21 12a1 1 0 0 1-.883.993L20 13h-7v7a1 1 0 0 1-.883.993L12 21a1 1 0 0 1-.993-.883L11 20v-7H4a1 1 0 0 1-.993-.883L3 12a1 1 0 0 1 .883-.993L4 11h7V4a1 1 0 0 1 .883-.993L12 3l-.117.007Z" />
</svg>
);
};
40 changes: 40 additions & 0 deletions Client/reasn-client/packages/ui/src/icons/Dismiss.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { IconProps } from "./IconProps";

export const Dismiss = (props: IconProps) => {
const { className, colors, gradientTransform, onClick } = props;

return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
className={className}
viewBox="0 0 24 24"
fill="url(#gradient1)"
onClick={onClick}
>
<defs>
<linearGradient
id="gradient1"
x1="0%"
y1="0%"
x2="100%"
y2="0%"
gradientTransform={gradientTransform}
>
{colors?.map((color, index) => (
<stop
key={index}
offset={`${
index + 1 < colors.length ? index * (100 / colors.length) : 100
}%`}
style={{ stopColor: color, stopOpacity: 1 }}
/>
))}
</linearGradient>
</defs>
<path d="m4.21 4.387.083-.094a1 1 0 0 1 1.32-.083l.094.083L12 10.585l6.293-6.292a1 1 0 1 1 1.414 1.414L13.415 12l6.292 6.293a1 1 0 0 1 .083 1.32l-.083.094a1 1 0 0 1-1.32.083l-.094-.083L12 13.415l-6.293 6.292a1 1 0 0 1-1.414-1.414L10.585 12 4.293 5.707a1 1 0 0 1-.083-1.32l.083-.094-.083.094Z" />
</svg>
);
};
40 changes: 40 additions & 0 deletions Client/reasn-client/packages/ui/src/icons/Question.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { IconProps } from "./IconProps";

export const Question = (props: IconProps) => {
const { className, colors, gradientTransform, onClick } = props;

return (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
className={className}
viewBox="0 0 24 24"
fill="url(#gradient1)"
onClick={onClick}
>
<defs>
<linearGradient
id="gradient1"
x1="0%"
y1="0%"
x2="100%"
y2="0%"
gradientTransform={gradientTransform}
>
{colors?.map((color, index) => (
<stop
key={index}
offset={`${
index + 1 < colors.length ? index * (100 / colors.length) : 100
}%`}
style={{ stopColor: color, stopOpacity: 1 }}
/>
))}
</linearGradient>
</defs>
<path d="M12 4C9.238 4 7 6.238 7 9a1 1 0 0 0 2 0c0-1.658 1.342-3 3-3s3 1.342 3 3c0 .816-.199 1.294-.438 1.629-.262.365-.625.638-1.128.985l-.116.078c-.447.306-1.023.699-1.469 1.247-.527.648-.849 1.467-.849 2.561v.5a1 1 0 1 0 2 0v-.5c0-.656.178-1.024.4-1.299.257-.314.603-.552 1.114-.903l.053-.037c.496-.34 1.133-.786 1.62-1.468C16.7 11.081 17 10.183 17 9c0-2.762-2.238-5-5-5ZM12 21.25a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5Z" />
</svg>
);
};
3 changes: 3 additions & 0 deletions Client/reasn-client/packages/ui/src/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ export { ArrowRight } from "./ArrowRight";
export { Upload } from "./Upload";
export { CaretDown } from "./CaretDown";
export { CaretUp } from "./CaretUp";
export { Add } from "./Add";
export { Question } from "./Question";
export { Dismiss } from "./Dismiss";
Loading