add page for teams

pull/448/head
femyeda 2021-08-13 14:46:42 -05:00
parent 917431f4e8
commit 60a4b8b29e
4 changed files with 214 additions and 3 deletions

View File

@ -0,0 +1,83 @@
import React from "react";
import Text from "@components/ui/Text";
import Link from "next/link";
import Avatar from "@components/Avatar";
import { ArrowRightIcon } from "@heroicons/react/outline";
import useTheme from "@components/Theme";
import classnames from "classnames";
const Team = ({ team }) => {
useTheme();
const Member = ({ member }) => {
const classes = classnames(
"group",
"relative",
"flex flex-col",
"space-y-4",
"p-4",
"bg-white dark:bg-opacity-8",
"border border-neutral-200",
"hover:cursor-pointer",
"hover:border-black hover:border-2 dark:border-neutral-700 dark:hover:border-neutral-600",
"rounded-sm",
"hover:shadow-md"
);
return (
<Link key={member.id} href={`/${member.user.username}`}>
<div className={classes}>
<ArrowRightIcon
className={classnames(
"text-black dark:text-white",
"absolute top-4 right-4",
"h-4 w-4",
"transition-opacity",
"opacity-0 group-hover:opacity-100 group-hover:block"
)}
/>
<Avatar user={member.user} className="w-12 h-12 rounded-full" />
<section className="space-y-2">
<Text variant="title">{member.user.name}</Text>
<Text variant="subtitle" className="w-6/8">
{member.user.bio}
</Text>
</section>
</div>
</Link>
);
};
const Members = ({ members }) => {
if (!members || members.length === 0) {
return null;
}
return (
<section className="mx-auto min-w-full lg:min-w-lg max-w-5xl grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-12 gap-y-6">
{members.map((member) => {
return <Member key={member.id} member={member} />;
})}
</section>
);
};
return (
<article className="flex flex-col space-y-8 lg:space-y-12">
<div className="mb-8 text-center">
<Avatar
user={{
email: team.name,
}}
className="mx-auto w-20 h-20 rounded-full mb-4"
/>
<Text variant="headline">{team.name}</Text>
</div>
<Members members={team.members} />
</article>
);
};
export default Team;

54
lib/teams/getTeam.ts Normal file
View File

@ -0,0 +1,54 @@
import { Team } from "@prisma/client";
import prisma from "@lib/prisma";
import logger from "@lib/logger";
const log = logger.getChildLogger({ prefix: ["[lib] getTeam"] });
export const getTeam = async (idOrSlug: string): Promise<Team | null> => {
const teamIdOrSlug = idOrSlug;
let team = null;
log.debug(`{teamIdOrSlug} ${teamIdOrSlug}`);
const teamSelectInput = {
id: true,
name: true,
slug: true,
members: {
where: {
accepted: true,
},
select: {
user: {
select: {
id: true,
username: true,
email: true,
name: true,
bio: true,
avatar: true,
theme: true,
},
},
},
},
};
team = await prisma.team.findFirst({
where: {
OR: [
{
id: parseInt(teamIdOrSlug) || undefined,
},
{
slug: teamIdOrSlug,
},
],
},
select: teamSelectInput,
});
log.debug(`{team}`, { team });
return team;
};

54
pages/team/[idOrSlug].tsx Normal file
View File

@ -0,0 +1,54 @@
import { GetServerSideProps } from "next";
import Head from "next/head";
import Theme from "@components/Theme";
import { getTeam } from "@lib/teams/getTeam";
import Team from "@components/team/screens/Team";
export default function Page(props) {
const { isReady } = Theme();
return (
isReady && (
<div>
<Head>
<title>{props.team.name} | Calendso</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="mx-auto py-24 px-4">
<Team team={props.team} />
</main>
</div>
)
);
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const teamIdOrSlug = Array.isArray(context.query?.idOrSlug)
? context.query.idOrSlug.pop()
: context.query.idOrSlug;
const team = await getTeam(teamIdOrSlug);
if (!team) {
return {
notFound: true,
};
}
return {
props: {
team,
},
};
};
// Auxiliary methods
export function getRandomColorCode(): string {
let color = "#";
for (let idx = 0; idx < 6; idx++) {
color += Math.floor(Math.random() * 10);
}
return color;
}

View File

@ -95,22 +95,28 @@ module.exports = {
inter: ["Inter", "sans-serif"],
kollektif: ["Kollektif", "sans-serif"],
},
maxHeight: (theme) => ({
maxHeight: (theme, { breakpoints }) => ({
0: "0",
97: "25rem",
...theme("spacing"),
...breakpoints(theme("screens")),
...theme("screens"),
full: "100%",
screen: "100vh",
}),
minHeight: (theme) => ({
minHeight: (theme, { breakpoints }) => ({
0: "0",
...theme("spacing"),
...breakpoints(theme("screens")),
...theme("screens"),
full: "100%",
screen: "100vh",
}),
minWidth: (theme) => ({
minWidth: (theme, { breakpoints }) => ({
0: "0",
...theme("spacing"),
...breakpoints(theme("screens")),
...theme("screens"),
full: "100%",
screen: "100vw",
}),
@ -118,9 +124,23 @@ module.exports = {
0: "0",
...theme("spacing"),
...breakpoints(theme("screens")),
...theme("screens"),
full: "100%",
screen: "100vw",
}),
opacity: {
0: "0",
8: "0.08",
10: "0.10",
20: "0.20",
40: "0.40",
60: "0.60",
80: "0.80",
25: "0.25",
50: "0.5",
75: "0.75",
100: "1",
},
},
},
variants: {