add radio page
This commit is contained in:
Generated
+4
-4
@@ -18,7 +18,7 @@
|
|||||||
"@trpc/react-query": "^10.37.1",
|
"@trpc/react-query": "^10.37.1",
|
||||||
"@trpc/server": "^10.37.1",
|
"@trpc/server": "^10.37.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"grommet-icons": "^4.11.0",
|
"grommet-icons": "^4.12.1",
|
||||||
"next": "^13.5.4",
|
"next": "^13.5.4",
|
||||||
"next-auth": "^4.23.0",
|
"next-auth": "^4.23.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
@@ -2729,9 +2729,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/grommet-icons": {
|
"node_modules/grommet-icons": {
|
||||||
"version": "4.11.0",
|
"version": "4.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/grommet-icons/-/grommet-icons-4.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/grommet-icons/-/grommet-icons-4.12.1.tgz",
|
||||||
"integrity": "sha512-ArXf2XyXmpk5JsQ8NudzNz3mbWv+TeZkPiyog2s9yoNAWTlIr3vzNjr97uon/Xm4Uiq2kiHkvO4i2fG1u6EaDg==",
|
"integrity": "sha512-LhOP6BkDAGiSNcUOfsGGRo+AKD6zWOXeNeusY1WYvKplAR6mKCAQfH7Nig2Buc/v5zadKSko2NDtCQqwJaME0Q==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^16.6.0 || ^17.0.0 || ^18.0.0",
|
"react": "^16.6.0 || ^17.0.0 || ^18.0.0",
|
||||||
"react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0",
|
"react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0",
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
"@trpc/react-query": "^10.37.1",
|
"@trpc/react-query": "^10.37.1",
|
||||||
"@trpc/server": "^10.37.1",
|
"@trpc/server": "^10.37.1",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"grommet-icons": "^4.11.0",
|
"grommet-icons": "^4.12.1",
|
||||||
"next": "^13.5.4",
|
"next": "^13.5.4",
|
||||||
"next-auth": "^4.23.0",
|
"next-auth": "^4.23.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="relative rounded-t-sm p-2 text-white opacity-50">
|
<div className="absolute bottom-0 rounded-t-sm p-2 text-white opacity-50">
|
||||||
<p className="text-center">
|
<p className="text-center">
|
||||||
The 'PipBoy' is owned by Bethesda, I'm just doing this for fun!
|
The 'PipBoy' is owned by Bethesda, I'm just doing this for fun!
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ export default function Header({
|
|||||||
}: HeaderProps) {
|
}: HeaderProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="text-white max-w-sm mx-auto pt-2 pb-4">
|
<div className="text-white max-w-md mx-auto pt-2 pb-4 text-center">
|
||||||
<div className="inline-block pb-2 space-x-6 text-center">
|
<div className="inline-block pb-2 space-x-6">
|
||||||
<HeaderItem content="HOME" linkTo={
|
<HeaderItem content="HOME" linkTo={
|
||||||
isNotHomePage ? "/?noAnimation"
|
isNotHomePage ? "/?noAnimation"
|
||||||
: "/"
|
: "/"
|
||||||
} />
|
} />
|
||||||
<HeaderItem content="LINKS" linkTo="/links" />
|
<HeaderItem content="LINKS" linkTo="/links" />
|
||||||
<HeaderItem content="PROJECTS" linkTo="/projects" />
|
<HeaderItem content="PROJECTS" linkTo="/projects" />
|
||||||
|
<HeaderItem content="RADIO" linkTo="/radio" />
|
||||||
<HeaderItem content="ABOUT" linkTo="/about" />
|
<HeaderItem content="ABOUT" linkTo="/about" />
|
||||||
</div>
|
</div>
|
||||||
<hr className="border-green-500" />
|
<hr className="border-green-500" />
|
||||||
|
|||||||
+39
-7
@@ -2,25 +2,57 @@ import RootLayout from "@/components/RootLayout";
|
|||||||
import Footer from "@/components/footer";
|
import Footer from "@/components/footer";
|
||||||
import Header from "@/components/header";
|
import Header from "@/components/header";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import {useState} from 'react';
|
||||||
|
|
||||||
|
// icons
|
||||||
|
import {
|
||||||
|
Twitter,
|
||||||
|
MailOption
|
||||||
|
} from 'grommet-icons'
|
||||||
|
|
||||||
export default function LinksPage() {
|
export default function LinksPage() {
|
||||||
|
const [icon, setIcon] = useState<Element | null>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RootLayout>
|
<RootLayout>
|
||||||
<Header isNotHomePage={true} />
|
<Header isNotHomePage={true} />
|
||||||
<div className="text-green-500 text-center">
|
<div className="text-green-500 max-h-96">
|
||||||
<h1 className="font-bold text-3xl">My Links!</h1>
|
<h1 className="font-bold text-3xl ml-2">My Links!</h1>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2 float-left">
|
||||||
<Link href="https://twitter.com/avvex__" target="_blank">
|
<Link
|
||||||
|
href="https://twitter.com/avvex__"
|
||||||
|
target="_blank"
|
||||||
|
onMouseOver={() => {
|
||||||
|
setIcon(<Twitter size="large" />)
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setIcon(null)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="hover:bg-green-500 hover:text-black">
|
<div className="hover:bg-green-500 hover:text-black">
|
||||||
<h1 className="text-2xl mx-32">Twitter</h1>
|
<h1 className="text-2xl mr-32 ml-2">Twitter</h1>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
<Link href="https://mast.thatalex.dev/@alex" target="_blank">
|
<Link
|
||||||
|
href="https://mast.thatalex.dev/@alex"
|
||||||
|
target="_blank"
|
||||||
|
onMouseOver={() => {
|
||||||
|
setIcon(<MailOption size="large" />)
|
||||||
|
}}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setIcon(null)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="hover:bg-green-500 hover:text-black">
|
<div className="hover:bg-green-500 hover:text-black">
|
||||||
<h1 className="text-2xl mx-32">Mastodon</h1>
|
<h1 className="text-2xl mr-32 ml-2">Mastodon</h1>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="float-right">
|
||||||
|
{/* <Twitter size='xlarge' className="mr-24" /> */}
|
||||||
|
{icon}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Footer />
|
<Footer />
|
||||||
</RootLayout>
|
</RootLayout>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import RootLayout from "@/components/RootLayout";
|
||||||
|
import Footer from "@/components/footer";
|
||||||
|
import Header from "@/components/header";
|
||||||
|
import { api } from "@/utils/api";
|
||||||
|
|
||||||
|
// next components
|
||||||
|
import Link from 'next/link';
|
||||||
|
import Image from "next/image";
|
||||||
|
|
||||||
|
export default function MusicPage() {
|
||||||
|
const { data: musicData, fetchStatus} = api.misc.song.useQuery();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<RootLayout>
|
||||||
|
<Header isNotHomePage={true} />
|
||||||
|
<div className="text-green-500 flicker max-w-1/2">
|
||||||
|
<div className="float-left">
|
||||||
|
{
|
||||||
|
fetchStatus === "idle" ?
|
||||||
|
musicData?.data.tracks.map((v,k) => {
|
||||||
|
return <div key={k}>
|
||||||
|
<div className={`text-lg ${k === 0 ? "bg-green-500 text-black" : "hover:bg-green-500 hover:text-black"}`}>
|
||||||
|
<Link href={v.url} target="_blank">
|
||||||
|
<h1 className="ml-2 mr-36 truncate max-w-10">{k === 0 && "■"} {v.name}</h1>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
: <h1 className="font-bold text-green-500">Fetching..</h1>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="float-right">
|
||||||
|
{
|
||||||
|
fetchStatus === "idle" &&
|
||||||
|
<Image
|
||||||
|
src={musicData?.data.tracks[0]?.image[2]?.["#text"] ?? "https://storage.thatalex.dev"}
|
||||||
|
alt="Cover Art"
|
||||||
|
width="160"
|
||||||
|
height="160"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
|
</RootLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { postRouter } from "@/server/api/routers/post";
|
import { postRouter } from "@/server/api/routers/post";
|
||||||
import { linksRouter } from "./routers/links";
|
import { linksRouter } from "./routers/links";
|
||||||
import { blogRouter } from "./routers/blog";
|
import { blogRouter } from "./routers/blog";
|
||||||
|
import { miscRouter } from "./routers/misc";
|
||||||
import { createTRPCRouter } from "@/server/api/trpc";
|
import { createTRPCRouter } from "@/server/api/trpc";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,7 +12,8 @@ import { createTRPCRouter } from "@/server/api/trpc";
|
|||||||
export const appRouter = createTRPCRouter({
|
export const appRouter = createTRPCRouter({
|
||||||
post: postRouter,
|
post: postRouter,
|
||||||
links: linksRouter,
|
links: linksRouter,
|
||||||
blog: blogRouter
|
blog: blogRouter,
|
||||||
|
misc: miscRouter
|
||||||
});
|
});
|
||||||
|
|
||||||
// export type definition of API
|
// export type definition of API
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import {
|
||||||
|
createTRPCRouter,
|
||||||
|
publicProcedure
|
||||||
|
} from '@/server/api/trpc';
|
||||||
|
|
||||||
|
type ImageListType = {
|
||||||
|
"size": string,
|
||||||
|
"#text": string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrackResponseType = {
|
||||||
|
status: number,
|
||||||
|
data: {
|
||||||
|
tracks: LastTrackType[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type LastTrackType = {
|
||||||
|
"@attr": {
|
||||||
|
"nowplaying": string
|
||||||
|
},
|
||||||
|
"album": {
|
||||||
|
"mbid": string,
|
||||||
|
"#text": string
|
||||||
|
},
|
||||||
|
"artist": {
|
||||||
|
"mbid": string,
|
||||||
|
"#text": string,
|
||||||
|
},
|
||||||
|
"image": ImageListType[],
|
||||||
|
"mbid": string,
|
||||||
|
"name": string,
|
||||||
|
"streamable": number,
|
||||||
|
"url": string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const miscRouter = createTRPCRouter({
|
||||||
|
song: publicProcedure
|
||||||
|
.query(async () => {
|
||||||
|
const response = await axios.get<TrackResponseType>("https://api.thatalex.dev/v4/social/music")
|
||||||
|
return response.data
|
||||||
|
}),
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user