parent
6e200f6d5e
commit
52bea590eb
|
|
@ -2,6 +2,10 @@ import { SVGProps } from "react";
|
|||
|
||||
type IconProps = SVGProps<SVGSVGElement>;
|
||||
|
||||
export const ArrowDown = (props: IconProps) => (
|
||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 19.1642L18.2071 12.9571L16.7929 11.5429L12 16.3358L7.20711 11.5429L5.79289 12.9571L12 19.1642ZM12 13.5143L18.2071 7.30722L16.7929 5.89301L12 10.6859L7.20711 5.89301L5.79289 7.30722L12 13.5143Z"></path></svg>
|
||||
)
|
||||
|
||||
export const StarFill = (props: IconProps) => (
|
||||
<svg {...props} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12.0006 18.26L4.94715 22.2082L6.52248 14.2799L0.587891 8.7918L8.61493 7.84006L12.0006 0.5L15.3862 7.84006L23.4132 8.7918L17.4787 14.2799L19.054 22.2082L12.0006 18.26Z"></path></svg>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import type { MetaFunction } from "@remix-run/node";
|
||||
import { Link, useLoaderData } from "@remix-run/react";
|
||||
import { type MetaFunction } from "@remix-run/node";
|
||||
import { siteTitle } from "~/utils";
|
||||
import { BiliBili, CloudMusic, GitHub, QQ, Steam, TwitterX } from "~/components/common/icons";
|
||||
import { ArrowDown, BiliBili, CloudMusic, GitHub, QQ, Steam, TwitterX } from "~/components/common/icons";
|
||||
|
||||
import styles from "./styles.module.less";
|
||||
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
{ title: siteTitle() },
|
||||
|
|
@ -11,10 +14,20 @@ export const meta: MetaFunction = () => {
|
|||
];
|
||||
};
|
||||
|
||||
export async function loader() {
|
||||
const data = (await fetch("https://paul.ren/api/sync").then((res) =>
|
||||
res.json()
|
||||
)) as unknown as API.Response<API.Sync.ISyncData>;
|
||||
|
||||
return { data };
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
const { data } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<main className="px-2 py-24">
|
||||
<section className="flex flex-col h-[60vh] max-w-2xl mx-auto">
|
||||
<main className="px-2 py-24 max-w-3xl mx-auto">
|
||||
<section className="-mt-40 relative flex flex-col h-screen min-h-[40rem] max-w-3xl mx-auto">
|
||||
<div className="my-auto px-4 py-10 bg-white rounded-xl text-center">
|
||||
<div className="mx-auto w-40 mb-10 relative select-none">
|
||||
<div className="top-4 left-2 w-36 h-36 rounded-full absolute bg-pink-100"></div>
|
||||
|
|
@ -43,6 +56,44 @@ export default function Index() {
|
|||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<ArrowDown className="absolute left-0 right-0 bottom-20 mx-auto w-10 h-10 opacity-60 animate-bounce" />
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl mb-4">近期博文</h2>
|
||||
<div className="bg-white rounded-xl p-5">
|
||||
{data.data.blog.map((item) => (
|
||||
<p key={item.link} className="flex mb-3 last:mb-0">
|
||||
<a className="flex-1" href={item.link} target="_blank" rel="noreferrer">{item.title}</a>
|
||||
<span className="font-mono opacity-50">{item.date}</span>
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mb-16">
|
||||
<h2 className="text-3xl mb-4">近期日记</h2>
|
||||
<div className="bg-white rounded-xl p-5">
|
||||
{data.data.note.map((item) => (
|
||||
<p key={item.id} className="flex mb-3 last:mb-0">
|
||||
<Link className="flex-1" to={`/note/${year}/${item.id}`}>{item.title}</Link>
|
||||
<span className="font-mono opacity-50">{item.date}</span>
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-3xl mb-4">近期捕获</h2>
|
||||
<div className="bg-white rounded-xl p-5 grid grid-cols-2 gap-5">
|
||||
{data.data.media.map((item) => (
|
||||
<div key={item.id}>
|
||||
<img className="mb-3 rounded-xl" src={item.thumb_url} alt={item.title} />
|
||||
<h3 className="text-lg mb-1">{item.title}</h3>
|
||||
<p className="text-xs opacity-50">{item.take_time.substring(0, 10)}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ export default function Note() {
|
|||
{item.starred && (
|
||||
<StarFill className="absolute -top-5 -right-5 w-28 h-28 text-yellow-300 text-opacity-20 -rotate-[23deg]" />
|
||||
)}
|
||||
<h2 className="text-pink-400 text-2xl font-bold mb-4" style={{ viewTransitionName: `note-title-${item.id}` }}>
|
||||
<h2 className={clsn(cover && "mr-40", "text-pink-400 text-2xl font-bold mb-4")} style={{ viewTransitionName: `note-title-${item.id}` }}>
|
||||
{item.title}
|
||||
</h2>
|
||||
<p className={clsn(cover && "mr-40", "mb-8 relative")}>{item.except}</p>
|
||||
<div className="flex items-end justify-between text-sm">
|
||||
<div className={clsn(cover && "mr-40", "flex items-end justify-between text-sm")}>
|
||||
<p className="opacity-60">{item.date}</p>
|
||||
<span className="flex items-center opacity-60">
|
||||
<ThumbUpFill className="h-4 w-4 mr-1" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
interface IBlogData {
|
||||
title: string
|
||||
image: string
|
||||
date: string
|
||||
link: string
|
||||
content: string
|
||||
}
|
||||
|
||||
declare namespace API {
|
||||
namespace Sync {
|
||||
interface ISyncData {
|
||||
blog: IBlogData[]
|
||||
video: unknown[]
|
||||
note: API.Note.INoteData[]
|
||||
say: API.Say.ISayData[]
|
||||
media: API.Media.IMediaData[]
|
||||
music: API.Music.IMusicData[]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue