feat: event card, event modal

This commit is contained in:
MTG2000
2022-09-01 13:26:44 +03:00
parent b07e2a98d2
commit b512b19804
11 changed files with 159 additions and 23 deletions

View File

@@ -69,6 +69,7 @@ export interface NexusGenInputs {
export interface NexusGenEnums {
POST_TYPE: "Bounty" | "Question" | "Story"
RoleLevelEnum: 3 | 0 | 1 | 2 | 4
TournamentEventTypeEnum: 2 | 0 | 1
VOTE_ITEM_TYPE: "Bounty" | "PostComment" | "Project" | "Question" | "Story" | "User"
}
@@ -261,7 +262,7 @@ export interface NexusGenObjects {
links: string[]; // [String!]!
location: string; // String!
title: string; // String!
type: string; // String!
type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum!
website: string; // String!
}
TournamentFAQ: { // root type
@@ -562,7 +563,7 @@ export interface NexusGenFieldTypes {
links: string[]; // [String!]!
location: string; // String!
title: string; // String!
type: string; // String!
type: NexusGenEnums['TournamentEventTypeEnum']; // TournamentEventTypeEnum!
website: string; // String!
}
TournamentFAQ: { // field return type
@@ -886,7 +887,7 @@ export interface NexusGenFieldTypeNames {
links: 'String'
location: 'String'
title: 'String'
type: 'String'
type: 'TournamentEventTypeEnum'
website: 'String'
}
TournamentFAQ: { // field return type name

View File

@@ -351,10 +351,16 @@ type TournamentEvent {
links: [String!]!
location: String!
title: String!
type: String!
type: TournamentEventTypeEnum!
website: String!
}
enum TournamentEventTypeEnum {
IRLMeetup
TwitterSpace
Workshop
}
type TournamentFAQ {
answer: String!
question: String!

View File

@@ -4,6 +4,7 @@ const {
stringArg,
extendType,
nonNull,
enumType,
} = require('nexus');
const { prisma } = require('../../../prisma');
@@ -35,6 +36,18 @@ const TournamentFAQ = objectType({
}
})
const TournamentEventTypeEnum = enumType({
name: 'TournamentEventTypeEnum',
members: {
TwitterSpace: 0,
Workshop: 1,
IRLMeetup: 2,
},
});
const TournamentEvent = objectType({
name: 'TournamentEvent',
definition(t) {
@@ -45,7 +58,7 @@ const TournamentEvent = objectType({
t.nonNull.date('date');
t.nonNull.string('location');
t.nonNull.string('website');
t.nonNull.string('type');
t.nonNull.field('type', { type: TournamentEventTypeEnum })
t.nonNull.list.nonNull.string('links');
}
})

View File

@@ -4,8 +4,10 @@ import dayjs from "dayjs";
import advancedFormat from 'dayjs/plugin/advancedFormat'
import { trimText } from "src/utils/helperFunctions";
import { Override } from "src/utils/interfaces";
import { Tag, Tournament } from "src/graphql";
dayjs.extend(advancedFormat)
import { Tag, Tournament, TournamentEventTypeEnum } from "src/graphql";
import { UnionToObjectKeys } from 'src/utils/types/utils';
import { useAppDispatch, } from "src/utils/hooks";
import { openModal } from "src/redux/features/modals.slice";
interface Props {
@@ -22,8 +24,25 @@ interface Props {
}
export default function EventCard({ event }: Props) {
const dispatch = useAppDispatch()
const openEventModal = () => {
dispatch(openModal({
Modal: "EventModal",
isPageModal: true,
props: {
event
}
}))
}
return (
<div className="rounded-16 bg-white overflow-hidden border-2 flex flex-col">
<div
role='button'
className="rounded-16 bg-white overflow-hidden border-2 flex flex-col"
onClick={openEventModal}
>
<img className="w-full h-[160px] object-cover" src={event.image} alt="" />
<div className="p-16 grow flex flex-col">
<div className="flex flex-col gap-8">
@@ -34,13 +53,31 @@ export default function EventCard({ event }: Props) {
{event.date}
</p>
<p className="text-body4 font-medium text-gray-600">
<IoLocationOutline className="mr-8" /> {event.location}
<IoLocationOutline className="mr-4" /> <span className="align-middle">{event.location}</span>
</p>
<p className="text-body4 text-gray-600 line-clamp-2">
{trimText(event.description, 90)}
</p>
<span className={`mt-8 text-body5 self-start px-8 py-4 rounded-20 ${mapTypeToBadge[event.type].color}`}>
{mapTypeToBadge[event.type].text}
</span>
</div>
</div>
</div>
)
}
export const mapTypeToBadge: UnionToObjectKeys<Props['event'], 'type', { text: string, color: string }> = {
[TournamentEventTypeEnum.TwitterSpace]: {
text: "🐦 Twitter space",
color: "bg-blue-50 text-blue-500"
},
[TournamentEventTypeEnum.Workshop]: {
text: "🛠️ Workshop",
color: "bg-green-50 text-green-500"
},
[TournamentEventTypeEnum.IrlMeetup]: {
text: "🤝 IRL meetup",
color: "bg-red-50 text-red-500"
},
}

View File

@@ -0,0 +1,63 @@
import { MdClose, } from 'react-icons/md';
import { ModalCard } from 'src/Components/Modals/ModalsContainer/ModalsContainer';
import { useMediaQuery } from 'src/utils/hooks';
import { Tournament, } from 'src/graphql';
import { MEDIA_QUERIES } from 'src/utils/theme';
import { IoGlobe, IoLocationOutline } from 'react-icons/io5';
import { mapTypeToBadge } from '../EventCard/EventCard';
interface Props extends ModalCard {
event: Pick<Tournament['events'][number],
| "id"
| "title"
| "image"
| "description"
| "date"
| "location"
| "type"
| "website">
}
export default function ProjectDetailsCard({ direction, event, ...props }: Props) {
const closeModal = () => {
props.onClose?.();
}
const isMdScreen = useMediaQuery(MEDIA_QUERIES.isMedium)
return (
<div
className={`modal-card max-w-[768px] ${(props.isPageModal && !isMdScreen) && '!rounded-0 w-full min-h-screen'}`}
>
<div className="relative h-[160px]">
<img className="w-full h-full object-cover" src={event.image} alt="" />
<button className="w-32 h-32 bg-gray-700 text-white absolute top-16 right-16 rounded-full flex flex-col justify-center items-center" onClick={closeModal}><MdClose className=' inline-block text-body2 lg:text-body1' /></button>
<span className={`absolute top-16 left-16 text-body5 self-start px-8 py-4 rounded-20 bg-gray-700 text-white `}>
{mapTypeToBadge[event.type].text}
</span>
</div>
<div className="p-16 md:p-24">
<h1 className="text-body1 font-bold">{event.title}</h1>
<p className="text-body4 font-medium text-gray-900 mt-8">
{event.date}
</p>
<div className="flex gap-16 mt-8">
<p className="text-body4 font-medium text-primary-600 shrink-0">
<IoLocationOutline className="mr-4" /> <span className="align-middle">{event.location}</span>
</p>
<p className="text-body4 font-medium text-primary-600 overflow-hidden whitespace-nowrap text-ellipsis">
<IoGlobe className="mr-4" />
<a href={event.website} target="_blank" rel="noreferrer" > <span className="align-middle ">{event.website}</span></a>
</p>
</div>
<p className="text-body4 text-gray-600 mt-24">
{event.description}
</p>
</div>
</div>
)
}

View File

@@ -0,0 +1,6 @@
import { lazyModal } from 'src/utils/helperFunctions';
export const { LazyComponent: EventModal, preload: projectDetailsCardPreload } = lazyModal(() => import('./EventModal'))

View File

@@ -10,7 +10,7 @@ interface Props {
export default function EventsPage({ data: { events, events_count } }: Props) {
return (
<div>
<div className='pb-42'>
<h2 className='text-body1 font-bolder text-gray-900 mb-24'>Events 📆 ({events_count})</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-24">
{

View File

@@ -42,7 +42,7 @@ export default function Navigation({ data }: Props) {
], [data.events_count, data.makers_count, data.projects_count])
return (
<div className="w-full bg-white py-16 border-b-2 border-gray-200">
<div className="w-full bg-white py-16 border-b-2 border-gray-200 sticky-top-element">
<div className="relative group content-container">
<div className="overflow-hidden" ref={viewportRef}>
<div className="select-none w-full flex gap-16">

View File

@@ -521,10 +521,16 @@ export type TournamentEvent = {
links: Array<Scalars['String']>;
location: Scalars['String'];
title: Scalars['String'];
type: Scalars['String'];
type: TournamentEventTypeEnum;
website: Scalars['String'];
};
export enum TournamentEventTypeEnum {
IrlMeetup = 'IRLMeetup',
TwitterSpace = 'TwitterSpace',
Workshop = 'Workshop'
}
export type TournamentFaq = {
__typename?: 'TournamentFAQ';
answer: Scalars['String'];
@@ -787,7 +793,7 @@ export type GetTournamentByIdQueryVariables = Exact<{
}>;
export type GetTournamentByIdQuery = { __typename?: 'Query', getTournamentById: { __typename?: 'Tournament', id: number, title: string, description: string, thumbnail_image: string, cover_image: string, start_date: any, end_date: any, location: string, website: string, events_count: number, makers_count: number, projects_count: number, prizes: Array<{ __typename?: 'TournamentPrize', title: string, amount: string, image: string }>, judges: Array<{ __typename?: 'TournamentJudge', name: string, jobTitle: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, date: any, location: string, website: string, type: string, links: Array<string> }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> } };
export type GetTournamentByIdQuery = { __typename?: 'Query', getTournamentById: { __typename?: 'Tournament', id: number, title: string, description: string, thumbnail_image: string, cover_image: string, start_date: any, end_date: any, location: string, website: string, events_count: number, makers_count: number, projects_count: number, prizes: Array<{ __typename?: 'TournamentPrize', title: string, amount: string, image: string }>, judges: Array<{ __typename?: 'TournamentJudge', name: string, jobTitle: string, avatar: string }>, events: Array<{ __typename?: 'TournamentEvent', id: number, title: string, image: string, description: string, date: any, location: string, website: string, type: TournamentEventTypeEnum, links: Array<string> }>, faqs: Array<{ __typename?: 'TournamentFAQ', question: string, answer: string }> } };
export type VoteMutationVariables = Exact<{
itemType: Vote_Item_Type;

View File

@@ -1,4 +1,4 @@
import { Tournament } from "src/graphql";
import { Tournament, TournamentEventTypeEnum } from "src/graphql";
import { getCoverImage } from "./utils";
export const tournaments: Tournament[] = [{
@@ -50,7 +50,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🐦 Twitter space",
type: TournamentEventTypeEnum.TwitterSpace,
website: "https://event.name"
},
{
@@ -61,7 +61,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🛠 Workshop",
type: TournamentEventTypeEnum.Workshop,
website: "https://event.name"
},
{
@@ -72,7 +72,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🤝 IRL meetup",
type: TournamentEventTypeEnum.IrlMeetup,
website: "https://event.name"
},
{
@@ -83,7 +83,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🛠 Workshop",
type: TournamentEventTypeEnum.Workshop,
website: "https://event.name"
},
@@ -95,7 +95,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🛠 Workshop",
type: TournamentEventTypeEnum.Workshop,
website: "https://event.name"
},
@@ -107,7 +107,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Semper turpis est, ac e
image: getCoverImage(),
links: [],
location: "Online",
type: "🛠 Workshop",
type: TournamentEventTypeEnum.Workshop,
website: "https://event.name"
},
],

View File

@@ -14,6 +14,7 @@ import { LinkingAccountModal } from "src/features/Profiles/pages/EditProfilePage
import { ComponentProps } from "react";
import { generateId } from "src/utils/helperFunctions";
import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal";
import { EventModal } from "src/features/Tournaments/pages/EventsPage/EventModal";
export enum Direction {
START,
@@ -38,6 +39,9 @@ export const ALL_MODALS = {
Claim_SubmittedCard,
Claim_FundWithdrawCard,
// Tournaments
EventModal: EventModal,
// Misc
ConfirmModal,
VoteCard,
@@ -63,9 +67,9 @@ type NonNullableObject<T> = {
type ModalAction<U extends keyof typeof ALL_MODALS = keyof typeof ALL_MODALS> = U extends any ?
{} extends NonNullableObject<ModalProps<U>> ?
{ Modal: U }
{ Modal: U, isPageModal?: boolean, }
:
{ Modal: U, props: ModalProps<U> }
{ Modal: U, isPageModal?: boolean, props: ModalProps<U> }
:
never;
@@ -134,7 +138,7 @@ export const modalSlice = createSlice({
state.isOpen = true;
let props: any = {};
props.isPageModal = action.payload.Modal === 'ProjectDetailsCard';
props.isPageModal = action.payload.isPageModal;
if ('props' in action.payload)
props = { ...props, ...action.payload.props }