Footer desktop initial

This commit is contained in:
Kalle
2022-07-11 16:11:09 +03:00
parent 925553f8d2
commit 4b8eecc2c9
10 changed files with 261 additions and 7 deletions

3
.gitignore vendored
View File

@@ -11,4 +11,5 @@ dump
/cypress/videos
/cypress/screenshots
.DS_Store
.DS_Store
.excalidraw

View File

@@ -5,7 +5,11 @@ import type * as React from "react";
import { ArrowUpIcon } from "./icons/ArrowUp";
export function SubNav({ children }: { children: React.ReactNode }) {
return <nav className="sub-nav__container">{children}</nav>;
return (
<div>
<nav className="sub-nav__container">{children}</nav>
</div>
);
}
export function SubNavLink({

View File

@@ -0,0 +1,92 @@
import { Link, useLoaderData } from "@remix-run/react";
import type { RootLoaderData } from "~/root";
import { discordFullName } from "~/utils/strings";
import {
FAQ_PAGE,
SENDOU_INK_DISCORD_URL,
SENDOU_INK_GITHUB_URL,
SENDOU_INK_PATREON_URL,
SENDOU_TWITTER_URL,
userPage,
} from "~/utils/urls";
import { DiscordIcon } from "../icons/Discord";
import { GitHubIcon } from "../icons/GitHub";
import { PatreonIcon } from "../icons/Patreon";
import { TwitterIcon } from "../icons/Twitter";
// xxx: add some sendouLove
export function Footer() {
const data = useLoaderData<RootLoaderData>();
return (
<footer className="layout__footer">
<div className="layout__footer__link-list">
<a href={SENDOU_TWITTER_URL} target="_blank" rel="noreferrer">
sendou.ink by Sendou
</a>
<Link to={"/"}>Contributors</Link>
<Link to={FAQ_PAGE}>FAQ</Link>
</div>
<div className="layout__footer__socials">
<a
className="layout__footer__social-link"
href={SENDOU_INK_GITHUB_URL}
target="_blank"
rel="noreferrer"
>
<div className="layout__footer__social-header">
GitHub<p>Source code</p>
</div>
<GitHubIcon className="layout__footer__social-icon github" />
</a>
<a
className="layout__footer__social-link"
href={SENDOU_TWITTER_URL}
target="_blank"
rel="noreferrer"
>
<div className="layout__footer__social-header">
Twitter<p>Updates</p>
</div>
<TwitterIcon className="layout__footer__social-icon twitter" />
</a>
<a
className="layout__footer__social-link"
href={SENDOU_INK_DISCORD_URL}
target="_blank"
rel="noreferrer"
>
<div className="layout__footer__social-header">
Discord<p>Help & feedback</p>
</div>{" "}
<DiscordIcon className="layout__footer__social-icon discord" />
</a>
<a
className="layout__footer__social-link"
href={SENDOU_INK_PATREON_URL}
target="_blank"
rel="noreferrer"
>
<div className="layout__footer__social-header">
Patreon<p>Support</p>
</div>{" "}
<PatreonIcon className="layout__footer__social-icon patreon" />
</a>
</div>
<div>
<h4 className="layout__footer__patron-title">
Thanks to the patrons for the support
</h4>
<ul className="layout__footer__patron-list">
{data.patrons.map((patron) => (
<li key={patron.id}>
<Link to={userPage(patron.discordId)}>
{discordFullName(patron)}
</Link>
</li>
))}
</ul>
</div>
</footer>
);
}

View File

@@ -5,6 +5,7 @@ import { UserItem } from "./UserItem";
import navItems from "./nav-items.json";
import { useLocation } from "@remix-run/react";
import { Image } from "../Image";
import { Footer } from "./Footer";
export const Layout = React.memo(function Layout({
children,
@@ -19,7 +20,7 @@ export const Layout = React.memo(function Layout({
);
return (
<>
<div className="layout__container">
<header className="layout__header">
{currentPagesNavItem ? (
<h1 className="layout__page-heading">
@@ -45,6 +46,7 @@ export const Layout = React.memo(function Layout({
</header>
<Menu expanded={menuOpen} closeMenu={() => setMenuOpen(false)} />
{children}
</>
<Footer />
</div>
);
});

View File

@@ -145,3 +145,25 @@ export function findAllPlusMembers() {
plusTier: NonNullable<UserWithPlusTier["plusTier"]>;
}>;
}
const findAllPatronsStm = sql.prepare(`
select
"id",
"discordId",
"discordName",
"discordDiscriminator",
"patronTier"
from "User"
where "patronTier" is not null
order by "patronTier" desc, "patronSince" asc
`);
export type FindAllPatrons = Array<
Pick<
User,
"id" | "discordId" | "discordName" | "discordDiscriminator" | "patronTier"
>
>;
export function findAllPatrons() {
return findAllPatronsStm.all() as FindAllPatrons;
}

View File

@@ -9,6 +9,7 @@ import { sql } from "~/db/sql";
import type { UpsertManyPlusVotesArgs } from "./models/plusVotes.server";
import { ADMIN_DISCORD_ID } from "~/constants";
import shuffle from "just-shuffle";
import { dateToDatabaseTimestamp } from "~/utils/dates";
const ADMIN_TEST_AVATAR = "fcfd65a3bea598905abb9ca25296816b";
@@ -26,6 +27,7 @@ const basicSeeds = [
badgesToAdmin,
badgesToUsers,
badgeManagers,
patrons,
];
export function seed() {
@@ -42,7 +44,7 @@ function wipeDB() {
"PlusVote",
"PlusSuggestion",
"PlusVote",
"BadgeOwner",
"TournamentBadgeOwner",
"BadgeManager",
];
@@ -226,7 +228,7 @@ function badgesToAdmin() {
for (const id of badgesWithDuplicates) {
sql
.prepare(
`insert into "BadgeOwner" ("badgeId", "userId") values ($id, $userId)`
`insert into "TournamentBadgeOwner" ("badgeId", "userId") values ($id, $userId)`
)
.run({ id, userId: 1 });
}
@@ -259,7 +261,7 @@ function badgesToUsers() {
const userToGetABadge = userIds.shift()!;
sql
.prepare(
`insert into "BadgeOwner" ("badgeId", "userId") values ($id, $userId)`
`insert into "TournamentBadgeOwner" ("badgeId", "userId") values ($id, $userId)`
)
.run({ id, userId: userToGetABadge });
@@ -278,3 +280,22 @@ function badgeManagers() {
.run({ id, userId: 2 });
}
}
function patrons() {
const userIds = sql
.prepare(`select "id" from "User" order by random() limit 50`)
.all()
.map((u) => u.id);
for (const id of userIds) {
sql
.prepare(
`update user set "patronTier" = $patronTier, "patronSince" = $patronSince where id = $id`
)
.run({
id,
patronSince: dateToDatabaseTimestamp(faker.date.past()),
patronTier: faker.helpers.arrayElement([1, 1, 2, 2, 2, 3, 3, 4]),
});
}
}

View File

@@ -20,6 +20,8 @@ import layoutStyles from "~/styles/layout.css";
import resetStyles from "~/styles/reset.css";
import { Catcher } from "./components/Catcher";
import { Layout } from "./components/layout";
import { db } from "./db";
import type { FindAllPatrons } from "./db/models/users.server";
import type { UserWithPlusTier } from "./db/types";
import { getUser } from "./modules/auth";
@@ -41,6 +43,7 @@ export const meta: MetaFunction = () => ({
});
export interface RootLoaderData {
patrons: FindAllPatrons;
user?: Pick<
UserWithPlusTier,
"id" | "discordId" | "discordAvatar" | "plusTier"
@@ -51,6 +54,7 @@ export const loader: LoaderFunction = async ({ request }) => {
const user = await getUser(request);
return json<RootLoaderData>({
patrons: db.users.findAllPatrons(),
user: user
? {
discordAvatar: user.discordAvatar,

View File

@@ -23,6 +23,7 @@
--theme-vibrant: hsl(255deg 78% 65%);
--theme-transparent: hsl(255deg 66.7% 75% / 40%);
--theme-transparent-vibrant: hsl(255deg 78% 65% / 54%);
--theme-semi-transparent-vibrant: hsl(255deg 78% 65% / 75%);
--theme-secondary: hsl(85deg 66.7% 55.3%);
/* background-pattern.svg not using this currently */
@@ -312,6 +313,11 @@ article {
white-space: pre-line;
}
ol,
ul {
padding: 0;
}
select {
all: unset;
width: 90%;

View File

@@ -1,3 +1,9 @@
.layout__container {
display: flex;
flex-direction: column;
height: 100%;
}
.layout__header {
--item-size: 2.75rem;
@@ -35,6 +41,7 @@
margin: 0 auto;
padding-block-end: var(--s-32);
padding-inline: var(--s-3);
width: 100%;
}
.layout__burger {
@@ -182,3 +189,97 @@
flex-direction: column;
gap: var(--s-2);
}
.layout__footer {
background-color: var(--bg-darker);
margin-block-start: auto;
padding: var(--s-2-5);
display: flex;
flex-direction: column;
gap: var(--s-6);
}
.layout__footer__link-list {
display: flex;
justify-content: space-between;
font-size: var(--fonts-xxs);
}
.layout__footer__link-list > a {
flex: 1 1 0;
text-align: center;
}
.layout__footer__socials {
display: flex;
gap: var(--s-2);
justify-content: center;
}
.layout__footer__social-link {
background-color: var(--theme-transparent-vibrant);
border-radius: var(--rounded);
height: 16rem;
flex: 1 1 0;
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-between;
padding: var(--s-4);
font-size: var(--fonts-lg);
cursor: pointer;
max-width: 10rem;
}
.layout__footer__social-link:hover {
background-color: var(--theme-semi-transparent-vibrant);
}
.layout__footer__social-link:hover > .layout__footer__social-icon {
transform: translateY(-0.3rem);
}
/* .layout__footer__social-link:hover > .layout__footer__social-icon.github {
fill: #333;
}
.layout__footer__social-link:hover > .layout__footer__social-icon.twitter {
fill: #1da1f2;
}
.layout__footer__social-link:hover > .layout__footer__social-icon.discord {
fill: #5865f2;
}
.layout__footer__social-link:hover > .layout__footer__social-icon.patreon {
fill: #f96854;
} */
.layout__footer__social-icon {
height: 2.25rem;
transition: transform 0.25s ease-in-out;
}
.layout__footer__social-header {
text-align: center;
}
.layout__footer__social-header > p {
font-size: var(--fonts-xxs);
}
.layout__footer__patron-title {
text-align: center;
font-weight: var(--semi-bold);
font-size: var(--fonts-sm);
}
.layout__footer__patron-list {
display: flex;
list-style: none;
flex-wrap: wrap;
font-size: var(--fonts-xs);
gap: var(--s-1);
justify-content: center;
margin-block-start: var(--s-2);
}

View File

@@ -1,6 +1,7 @@
import type { Badge } from "~/db/types";
export const SENDOU_INK_DISCORD_URL = "https://discord.gg/sendou";
export const SENDOU_TWITTER_URL = "https://twitter.com/sendouc";
export const SENDOU_INK_TWITTER_URL = "https://twitter.com/sendouink";
export const SENDOU_INK_PATREON_URL = "https://patreon.com/sendou";
export const SENDOU_INK_GITHUB_URL = "https://github.com/Sendouc/sendou.ink";