import data

This commit is contained in:
Michael Zhang 2023-09-05 16:42:50 -05:00
parent 84c2292ee0
commit 841a48a955
18 changed files with 1750 additions and 109 deletions

7
.env Normal file
View File

@ -0,0 +1,7 @@
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="mysql://root:example@localhost:3306/omdb?schema=public"

5
.gitignore vendored
View File

@ -33,3 +33,8 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
dev.db
docker-data
/data.sql

12
docker-compose.yml Normal file
View File

@ -0,0 +1,12 @@
version: "3.7"
services:
dev-db:
image: mysql:8
command: --default-authentication-plugin=mysql_native_password
ports: [3306:3306]
environment:
- MYSQL_ROOT_PASSWORD=example
- MYSQL_DATABASE=omdb
volumes:
- ./docker-data/mysql:/var/lib/mysql

View File

@ -1,4 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {}
const nextConfig = {};
module.exports = nextConfig
module.exports = nextConfig;

1032
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,14 +9,25 @@
"lint": "next lint"
},
"dependencies": {
"@prisma/client": "^5.1.1",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-navigation-menu": "^1.1.3",
"@radix-ui/react-popover": "1.0.6",
"@types/node": "20.5.0",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"classnames": "^2.3.2",
"eslint": "8.47.0",
"eslint-config-next": "13.4.16",
"next": "13.4.16",
"prisma": "^5.1.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"typescript": "5.1.6"
},
"devDependencies": {
"prettier": "^3.0.2",
"sass": "^1.65.1"
}
}

View File

@ -0,0 +1,205 @@
-- CreateTable
CREATE TABLE `apikeys` (
`ApiID` INTEGER NOT NULL AUTO_INCREMENT,
`Name` TEXT NULL,
`ApiKey` TEXT NULL,
`UserID` INTEGER NULL,
UNIQUE INDEX `ApiKey`(`ApiKey`(255)),
PRIMARY KEY (`ApiID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `beatmap_creators` (
`BeatmapID` INTEGER NOT NULL,
`CreatorID` INTEGER NOT NULL,
INDEX `idx_BeatmapID`(`BeatmapID`),
PRIMARY KEY (`BeatmapID`, `CreatorID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `beatmap_edit_requests` (
`EditID` INTEGER NOT NULL AUTO_INCREMENT,
`BeatmapID` INTEGER NULL,
`SetID` INTEGER NULL,
`UserID` INTEGER NOT NULL,
`EditData` JSON NOT NULL,
`Timestamp` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`Status` ENUM('Pending', 'Denied', 'Approved') NULL DEFAULT 'Pending',
`EditorID` INTEGER NULL,
PRIMARY KEY (`EditID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `beatmaps` (
`BeatmapID` MEDIUMINT UNSIGNED NOT NULL,
`SetID` MEDIUMINT UNSIGNED NULL,
`SetCreatorID` INTEGER NULL,
`DifficultyName` VARCHAR(255) NULL,
`Mode` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`Status` TINYINT NOT NULL DEFAULT 0,
`SR` FLOAT NOT NULL DEFAULT 0,
`Rating` VARCHAR(45) NULL,
`ChartRank` INTEGER NULL,
`ChartYearRank` INTEGER NULL,
`Timestamp` TIMESTAMP(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
`RatingCount` INTEGER NULL,
`WeightedAvg` FLOAT NULL,
`Genre` INTEGER NULL,
`Lang` INTEGER NULL,
`Artist` VARCHAR(255) NULL,
`Title` VARCHAR(255) NULL,
`DateRanked` TIMESTAMP(0) NULL,
`Blacklisted` BOOLEAN NOT NULL DEFAULT false,
`BlacklistReason` TEXT NULL,
`controversy` DECIMAL(10, 8) NULL,
INDEX `beatmapset_id`(`SetID`),
FULLTEXT INDEX `Artist`(`DifficultyName`, `Artist`, `Title`),
PRIMARY KEY (`BeatmapID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `beatmapset_nominators` (
`SetID` INTEGER NULL,
`NominatorID` INTEGER NULL,
`Mode` INTEGER NULL,
INDEX `beatmapset_nominators_SetID_index`(`SetID`),
UNIQUE INDEX `beatmapset_nominators_pk`(`SetID`, `NominatorID`, `Mode`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `blacklist` (
`UserID` INTEGER NOT NULL,
PRIMARY KEY (`UserID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `comments` (
`CommentID` INTEGER NOT NULL AUTO_INCREMENT,
`UserID` INTEGER NOT NULL,
`SetID` INTEGER NOT NULL,
`Comment` TEXT NULL,
`date` TIMESTAMP(0) NULL DEFAULT CURRENT_TIMESTAMP(0),
PRIMARY KEY (`CommentID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `descriptor_votes` (
`VoteID` INTEGER NOT NULL AUTO_INCREMENT,
`BeatmapID` INTEGER NOT NULL,
`UserID` INTEGER NOT NULL,
`Vote` BOOLEAN NOT NULL,
`DescriptorID` INTEGER NOT NULL,
INDEX `descriptor_votes_BeatmapID_index`(`BeatmapID`),
UNIQUE INDEX `descriptor_votes_pk2`(`BeatmapID`, `UserID`, `DescriptorID`),
PRIMARY KEY (`VoteID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `descriptors` (
`DescriptorID` INTEGER NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(40) NOT NULL,
`ShortDescription` TEXT NULL,
`ParentID` INTEGER NULL,
`Usable` BOOLEAN NOT NULL DEFAULT true,
UNIQUE INDEX `descriptors_pk2`(`Name`),
PRIMARY KEY (`DescriptorID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `logs` (
`LogID` INTEGER NOT NULL AUTO_INCREMENT,
`UserID` INTEGER NOT NULL,
`LogData` JSON NULL,
PRIMARY KEY (`LogID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `mappernames` (
`UserID` INTEGER NOT NULL,
`Username` VARCHAR(255) NULL,
PRIMARY KEY (`UserID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `rating_tags` (
`UserID` INTEGER NULL,
`BeatmapID` INTEGER NULL,
`Tag` VARCHAR(150) NULL,
`TagID` INTEGER NOT NULL AUTO_INCREMENT,
UNIQUE INDEX `rating_tags_pk`(`BeatmapID`, `UserID`, `Tag`),
PRIMARY KEY (`TagID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `ratings` (
`RatingID` INTEGER NOT NULL AUTO_INCREMENT,
`BeatmapID` INTEGER NOT NULL,
`UserID` INTEGER NOT NULL,
`Score` DECIMAL(2, 1) NULL,
`date` DATETIME(0) NOT NULL,
INDEX `idx_beatmapID`(`BeatmapID`),
PRIMARY KEY (`RatingID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `setretrieveinfo` (
`LastRetrieval` DATETIME(0) NULL,
`LastDate` DATE NULL
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `user_correlations` (
`user1_id` INTEGER NULL,
`user2_id` INTEGER NULL,
`correlation` FLOAT NULL,
UNIQUE INDEX `user_correlations_pk`(`user1_id`, `user2_id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `user_relations` (
`UserIDFrom` INTEGER NULL,
`UserIDTo` INTEGER NULL,
`type` INTEGER NULL,
UNIQUE INDEX `user_relations_pk`(`UserIDTo`, `UserIDFrom`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- CreateTable
CREATE TABLE `users` (
`UserID` INTEGER NOT NULL,
`Username` VARCHAR(255) NULL,
`AccessToken` VARCHAR(2000) NULL,
`RefreshToken` VARCHAR(2000) NULL,
`banned` BOOLEAN NULL DEFAULT false,
`Weight` DECIMAL(6, 4) NULL,
`DoTrueRandom` BOOLEAN NOT NULL DEFAULT false,
`Custom00Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom05Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom10Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom15Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom20Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom25Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom30Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom35Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom40Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom45Rating` VARCHAR(60) NOT NULL DEFAULT '',
`Custom50Rating` VARCHAR(60) NOT NULL DEFAULT '',
`LastAccessedSite` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`HideRatings` BOOLEAN NULL DEFAULT false,
PRIMARY KEY (`UserID`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

View File

@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "mysql"

191
prisma/schema.prisma Normal file
View File

@ -0,0 +1,191 @@
generator client {
provider = "prisma-client-js"
previewFeatures = ["fullTextIndex", "fullTextSearch"]
}
datasource db {
provider = "mysql"
url = "mysql://root:example@localhost:3306/omdb"
}
model apikeys {
ApiID Int @id @default(autoincrement())
Name String? @db.Text
ApiKey String? @unique(map: "ApiKey", length: 255) @db.Text
UserID Int?
}
model beatmap_creators {
BeatmapID Int
CreatorID Int
@@id([BeatmapID, CreatorID])
@@index([BeatmapID], map: "idx_BeatmapID")
}
model beatmap_edit_requests {
EditID Int @id @default(autoincrement())
BeatmapID Int?
SetID Int?
UserID Int
EditData Json
Timestamp DateTime @default(now()) @db.Timestamp(0)
Status beatmap_edit_requests_Status? @default(Pending)
EditorID Int?
}
model beatmaps {
BeatmapID Int @id @db.UnsignedMediumInt
SetID Int? @db.UnsignedMediumInt
SetCreatorID Int?
DifficultyName String? @db.VarChar(255)
Mode Int @default(0) @db.UnsignedTinyInt
Status Int @default(0) @db.TinyInt
SR Float @default(0) @db.Float
Rating String? @db.VarChar(45)
ChartRank Int?
ChartYearRank Int?
Timestamp DateTime? @default(now()) @db.Timestamp(0)
RatingCount Int?
WeightedAvg Float? @db.Float
Genre Int?
Lang Int?
Artist String? @db.VarChar(255)
Title String? @db.VarChar(255)
DateRanked DateTime? @db.Timestamp(0)
Blacklisted Boolean @default(false)
BlacklistReason String? @db.Text
controversy Decimal? @db.Decimal(10, 8)
@@index([SetID], map: "beatmapset_id")
@@fulltext([DifficultyName, Artist, Title], map: "Artist")
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
model beatmapset_nominators {
SetID Int?
NominatorID Int?
Mode Int?
@@unique([SetID, NominatorID, Mode], map: "beatmapset_nominators_pk")
@@index([SetID], map: "beatmapset_nominators_SetID_index")
@@ignore
}
model blacklist {
UserID Int @id
}
model comments {
CommentID Int @id @default(autoincrement())
UserID Int
SetID Int
Comment String? @db.Text
date DateTime? @default(now()) @db.Timestamp(0)
}
model descriptor_votes {
VoteID Int @id @default(autoincrement())
BeatmapID Int
UserID Int
Vote Boolean
DescriptorID Int
@@unique([BeatmapID, UserID, DescriptorID], map: "descriptor_votes_pk2")
@@index([BeatmapID], map: "descriptor_votes_BeatmapID_index")
}
model descriptors {
DescriptorID Int @id @default(autoincrement())
Name String @unique(map: "descriptors_pk2") @db.VarChar(40)
ShortDescription String? @db.Text
ParentID Int?
Usable Boolean @default(true)
}
model logs {
LogID Int @id @default(autoincrement())
UserID Int
LogData Json?
}
model mappernames {
UserID Int @id
Username String? @db.VarChar(255)
}
model rating_tags {
UserID Int?
BeatmapID Int?
Tag String? @db.VarChar(150)
TagID Int @id @default(autoincrement())
@@unique([BeatmapID, UserID, Tag], map: "rating_tags_pk")
}
model ratings {
RatingID Int @id @default(autoincrement())
BeatmapID Int
UserID Int
Score Decimal? @db.Decimal(2, 1)
date DateTime @db.DateTime(0)
@@index([BeatmapID], map: "idx_beatmapID")
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
model setretrieveinfo {
LastRetrieval DateTime? @db.DateTime(0)
LastDate DateTime? @db.Date
@@ignore
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
model user_correlations {
user1_id Int?
user2_id Int?
correlation Float? @db.Float
@@unique([user1_id, user2_id], map: "user_correlations_pk")
@@ignore
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
model user_relations {
UserIDFrom Int?
UserIDTo Int?
type Int?
@@unique([UserIDTo, UserIDFrom], map: "user_relations_pk")
@@ignore
}
model users {
UserID Int @id
Username String? @db.VarChar(255)
AccessToken String? @db.VarChar(2000)
RefreshToken String? @db.VarChar(2000)
banned Boolean? @default(false)
Weight Decimal? @db.Decimal(6, 4)
DoTrueRandom Boolean @default(false)
Custom00Rating String @default("") @db.VarChar(60)
Custom05Rating String @default("") @db.VarChar(60)
Custom10Rating String @default("") @db.VarChar(60)
Custom15Rating String @default("") @db.VarChar(60)
Custom20Rating String @default("") @db.VarChar(60)
Custom25Rating String @default("") @db.VarChar(60)
Custom30Rating String @default("") @db.VarChar(60)
Custom35Rating String @default("") @db.VarChar(60)
Custom40Rating String @default("") @db.VarChar(60)
Custom45Rating String @default("") @db.VarChar(60)
Custom50Rating String @default("") @db.VarChar(60)
LastAccessedSite DateTime @default(now()) @db.Timestamp(0)
HideRatings Boolean? @default(false)
}
enum beatmap_edit_requests_Status {
Pending
Denied
Approved
}

View File

@ -1,9 +1,9 @@
:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
@ -38,6 +38,8 @@
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
--accent-1: DarkSlateGrey;
}
@media (prefers-color-scheme: dark) {
@ -86,6 +88,8 @@ body {
}
body {
position: relative;
font-family: Verdana, Geneva, Tahoma, sans-serif;
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
@ -95,6 +99,11 @@ body {
rgb(var(--background-start-rgb));
}
.container {
max-width: 980px;
margin: auto;
}
a {
color: inherit;
text-decoration: none;

View File

@ -1,22 +1,23 @@
import './globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
import TopBar from "@/components/TopBar";
import "./globals.scss";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<body>
<TopBar />
{children}
</body>
</html>
)
);
}

View File

@ -15,7 +15,6 @@
max-width: var(--max-width);
width: 100%;
z-index: 2;
font-family: var(--font-mono);
}
.description a {
@ -36,7 +35,6 @@
.code {
font-weight: 700;
font-family: var(--font-mono);
}
.grid {
@ -51,7 +49,9 @@
border-radius: var(--border-radius);
background: rgba(var(--card-rgb), 0);
border: 1px solid rgba(var(--card-border-rgb), 0);
transition: background 200ms, border 200ms;
transition:
background 200ms,
border 200ms;
}
.card span {
@ -97,7 +97,7 @@
.center::before,
.center::after {
content: '';
content: "";
left: 50%;
position: absolute;
filter: blur(45px);

View File

@ -1,95 +1,25 @@
import Image from 'next/image'
import styles from './page.module.css'
import Image from "next/image";
import styles from "./page.module.css";
import { PrismaClient } from "@prisma/client";
import RatingTable from "@/components/RatingTable";
export async function getData() {
const prisma = new PrismaClient();
const comments = await prisma.comments.findMany({ take: 20 });
return { comments };
}
export default async function Home() {
const data = await getData();
console.log("data", data);
export default function Home() {
return (
<main className={styles.main}>
<div className={styles.description}>
<p>
Get started by editing&nbsp;
<code className={styles.code}>src/app/page.tsx</code>
</p>
<div>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
By{' '}
<Image
src="/vercel.svg"
alt="Vercel Logo"
className={styles.vercelLogo}
width={100}
height={24}
priority
/>
</a>
</div>
</div>
<div className={styles.center}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js Logo"
width={180}
height={37}
priority
/>
</div>
<div className={styles.grid}>
<a
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Docs <span>-&gt;</span>
</h2>
<p>Find in-depth information about Next.js features and API.</p>
</a>
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Learn <span>-&gt;</span>
</h2>
<p>Learn about Next.js in an interactive course with&nbsp;quizzes!</p>
</a>
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Templates <span>-&gt;</span>
</h2>
<p>Explore the Next.js 13 playground.</p>
</a>
<a
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
className={styles.card}
target="_blank"
rel="noopener noreferrer"
>
<h2>
Deploy <span>-&gt;</span>
</h2>
<p>
Instantly deploy your Next.js site to a shareable URL with Vercel.
</p>
</a>
<div className="flex-container column-when-mobile-container">
<RatingTable />
</div>
</main>
)
);
}

View File

View File

@ -0,0 +1,68 @@
import styles from "./RatingTable.module.scss";
import { PrismaClient } from "@prisma/client";
export async function getData() {
const prisma = new PrismaClient();
const comments = await prisma.comments.findMany({ take: 20 });
return { comments };
}
export default async function RatingTable() {
return (
<div
className="flex-child column-when-mobile" // style="width:40%;height:32em;overflow-y:scroll;position:relative;"
>
<div className="flex-container ratingContainer alternating-bg">
<div
className="flex-child" // style="margin-left:0.5em;"
>
<a href="/mapset/115011">
<img
src="https://b.ppy.sh/thumb/115011l.jpg"
className="diffThumb"
onerror="this.onerror=null; this.src='/charts/INF.png';"
/>
</a>
</div>
<div className="flex-child">
<a // style="display:flex;"
href="/profile/11237996"
>
<img
src="https://s.ppy.sh/a/11237996"
// style="height:24px;width:24px;"
title="payney"
/>
</a>
</div>
<div
className="flex-child" //style="flex:0 0 66%;"
>
<a // style="display:flex;"
href="/profile/11237996"
>
payney{" "}
</a>
<div className="starRatingDisplay">
<div className="starBackground">
<i className="icon-star"></i>
<i className="icon-star"></i>
<i className="icon-star"></i>
<i className="icon-star"></i>
<i className="icon-star"></i>
</div>
<div className="starForeground">
<i className="star icon-star"></i>
<i className="star icon-star"></i>
<i className="star icon-star"></i>
<i className="star icon-star"></i>
</div>
</div>{" "}
on <a href="/mapset/115011">Lan</a>{" "}
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,29 @@
"use client";
import { ChangeEvent, useState } from "react";
export default function SearchBar() {
const [searchQuery, setSearchQuery] = useState("");
const changeSearchQuery = (evt: ChangeEvent<HTMLInputElement>) => {
setSearchQuery(evt.target.value);
// showResult(searchQuery)
};
return (
<form className="topBarSearch">
<input
className="topBarSearchBar"
type="text"
size={30}
// onfocusin="searchFocus()"
onChange={changeSearchQuery}
value={searchQuery}
autoComplete="off"
placeholder="Search... (or paste link)"
/>
<div id="topBarSearchResults"></div>
</form>
);
}

View File

@ -0,0 +1,63 @@
.topBar {
position: sticky;
top: 0px;
background-color: var(--accent-1);
.container {
display: flex;
}
.spacer {
flex-grow: 1;
}
.leftHalf,
.rightHalf {
display: flex;
}
.searchResults {
display: block;
}
.username {
color: white;
}
}
.homeLink {
margin-right: 8px;
color: white;
}
.topBarDropDown {
display: inline-block;
margin: 0px;
padding: 0px;
.dropdownContent {
display: none;
position: absolute;
background-color: #395f5f;
min-width: 8rem;
z-index: 1;
a {
float: none;
color: white;
padding: 0.01rem 1rem;
text-decoration: none;
display: block;
text-align: left;
&:hover {
background-color: DarkSlateGrey;
}
}
}
&:hover .dropdownContent {
display: block;
}
}

75
src/components/TopBar.tsx Normal file
View File

@ -0,0 +1,75 @@
"use client";
import SearchBar from "./SearchBar";
import styles from "./TopBar.module.scss";
import classNames from "classnames";
import { GearIcon } from "@radix-ui/react-icons";
export default function TopBar() {
return (
<div className={styles.topBar}>
<div className={classNames("container", styles.container)}>
<div className={styles.leftHalf}>
<a href="/" className={styles.homeLink}>
OMDB
</a>
<a href="/">
<div className="topBarLink">home</div>
</a>
<a href="/charts/">
<div className="topBarLink">charts</div>
</a>
<div className={styles.topBarDropDown}>
<div className="topBarLink topBarDropDownButton">maps</div>
<div className={styles.dropdownContent}>
<a href="/maps/?m=08&amp;y=2023">latest</a>
<a href="/random/">random</a>
</div>
</div>
<SearchBar />
</div>
<div className={styles.spacer} />
<div className={styles.rightHalf}>
<div className={styles.topBarDropDown}>
<div className="topBarLink topBarDropDownButton">osu! </div>
<div className={styles.dropdownContent}>
<a id="osuLink" href="">
osu!
</a>
<a id="taikoLink" href="">
osu!taiko
</a>
<a id="catchLink" href="">
osu!catch
</a>
<a id="maniaLink" href="">
osu!mania
</a>
</div>
</div>
<a href="/dashboard/">
<div className="topBarLink">dashboard</div>
</a>
<a href="/settings/">
<GearIcon />
</a>
<a href="/profile/2688103" style={{ color: "white" }}>
<img
src="https://s.ppy.sh/a/2688103"
style={{ height: "2rem", verticalAlign: "middle" }}
/>
</a>
<a className={styles.username} href="/profile/2688103">
<b>IOException</b>
</a>
</div>
</div>
</div>
);
}