mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-02-23 07:24:32 +01:00
feat: event card, event modal
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
import { lazyModal } from 'src/utils/helperFunctions';
|
||||
|
||||
|
||||
|
||||
export const { LazyComponent: EventModal, preload: projectDetailsCardPreload } = lazyModal(() => import('./EventModal'))
|
||||
@@ -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">
|
||||
{
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user