Feat: Note & Gallery Details

日记列表增加点赞和精选效果,日记详情增加点赞等功能(尚未完善交互),相册列表增加精选和描述内容
This commit is contained in:
2024-07-11 23:49:43 +08:00
parent bacb9b8e5c
commit d03532b91f
7 changed files with 97 additions and 14 deletions
+14 -3
View File
@@ -2,6 +2,7 @@ import { NavLink, useLoaderData, useNavigate } from "@remix-run/react";
import { json, LoaderFunctionArgs, type MetaFunction } from "@remix-run/node";
import Pagination from "~/components/common/pagination";
import { clsn, siteTitle } from "~/utils";
import { StarFill } from "~/components/common/icons";
import styles from "./styles.module.less";
@@ -65,11 +66,21 @@ export default function Gallery() {
</section>
<section className="grid gap-8 grid-cols-2 sm:grid-cols-[repeat(auto-fill,minmax(18em,_1fr))] mb-12">
{media.data.map((item) => (
<div key={item.id} className="bg-white rounded-xl overflow-hidden border-4 border-transparent hover:border-pink-400 transition-colors border-b-4 border-b-cyan-200">
<div key={item.id} className="relative bg-white rounded-xl overflow-hidden border-4 border-transparent hover:border-pink-400 transition-colors border-b-4 border-b-cyan-200">
<img className={styles.image} src={item.thumb_url} alt={item.title} loading="lazy" />
<div className="relative p-4 sm:p-6 -mt-6 sm:-mt-12">
{item.content && (
<div className={clsn("absolute top-0 left-0 right-0 bottom-0 bg-opacity-60 bg-black p-4 sm:p-6 text-white leading-7 transition-opacity duration-300 opacity-0 hover:opacity-100", styles.desc)}>
{item.content}
</div>
)}
<div className="p-4 sm:p-6 -mt-6 sm:-mt-12">
<span className="block text-sm mb-4 opacity-60">{item.take_time.substring(0, 10)}</span>
<h1 className="text-pink-400 text-xl sm:text-2xl font-bold text-ellipsis overflow-hidden">{item.title}</h1>
<h1 className="text-pink-400 text-xl sm:text-2xl font-bold text-ellipsis overflow-hidden">
{item.title}
{item.starred && (
<StarFill className=" text-yellow-400 w-6 h-6 inline-block ml-2 align-[-.1em]" />
)}
</h1>
</div>
</div>
))}
+6 -3
View File
@@ -1,6 +1,9 @@
.image {
width: 100%;
.image, .desc {
aspect-ratio: 1 / 1;
background-color: #999;
clip-path: polygon(0 0, 100% 0%, 100% 100%, 0 75%);
}
.image {
width: 100%;
background-color: #999;
}
+41 -2
View File
@@ -1,6 +1,8 @@
import { LoaderFunctionArgs, MetaFunction, json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { useState } from "react";
import Article from "~/components/common/article";
import { CupFill, ShareFill, ThumbUpFill } from "~/components/common/icons";
import { siteTitle } from "~/utils";
export const meta: MetaFunction<typeof loader> = ({ data }) => {
@@ -27,15 +29,52 @@ export async function loader({ params }: LoaderFunctionArgs) {
export default function Detail() {
const note = useLoaderData<typeof loader>();
const [likes, setLikes] = useState(note.data.likes);
const onLike = () => {
setLikes((prevLike) => prevLike + 1);
}
const onShare = () => {
const shareData = {
title: note.data.title,
text: note.data.except,
url: `${location.protocol}//${location.host}${location.pathname}`,
};
if ("share" in navigator) {
navigator.share(shareData);
}
else {
alert("当前操作系统尚未实现此 API");
}
}
return (
<main className="px-2 py-24 max-w-3xl mx-auto">
<section className="mb-12">
<h1 className="text-center text-5xl/tight md:text-7xl/tight mb-4">{note.data.title}</h1>
<h1 className="text-center text-5xl/tight md:text-7xl/tight mb-4" style={{ viewTransitionName: `note-title-${note.data.id}` }}>
{note.data.title}
</h1>
<p className="text-center opacity-60">{note.data.date}</p>
</section>
<section className="p-5 bg-white rounded-xl border-b-4 border-b-cyan-200">
<section className="p-5 bg-white rounded-xl border-b-4 border-b-cyan-200 mb-8">
<Article html={note.data.content_html} />
</section>
<section className="flex gap-16 items-center justify-center text-base md:text-lg">
<button onClick={onLike}>
<ThumbUpFill className="inline-block h-8 w-8 mr-2" />
{likes}
</button>
<button onClick={onShare}>
<ShareFill className="inline-block h-8 w-8 mr-2" />
分享
</button>
<button>
<CupFill className="inline-block h-8 w-8 mr-2" />
打赏
</button>
</section>
</main>
);
};
+15 -4
View File
@@ -1,9 +1,10 @@
import { ChangeEvent, useEffect } from "react";
import { Link, useLoaderData, useNavigate, useSearchParams } from "@remix-run/react";
import { ChangeEvent, useEffect, useState } from "react";
import { Link, unstable_useViewTransitionState, useLoaderData, useNavigate, useSearchParams } from "@remix-run/react";
import { json, LoaderFunctionArgs, type MetaFunction } from "@remix-run/node";
import Pagination from "~/components/common/pagination";
import { clsn, siteTitle } from "~/utils";
import { getFirstImage, years } from "~/utils/note";
import { StarFill, ThumbUpFill } from "~/components/common/icons";
export const meta: MetaFunction = () => {
return [
@@ -61,11 +62,21 @@ export default function Note() {
key={item.id}
className="block group relative overflow-hidden p-5 bg-white rounded-xl mb-8 last:mb-0 border-4 border-transparent hover:border-pink-400 transition-colors border-b-cyan-200"
to={`/note/${year}/${item.id}`}
unstable_viewTransition
>
<h2 className="text-pink-400 text-2xl font-bold mb-4">{item.title}</h2>
<p className={clsn(cover && "mr-40", "mb-8")}>{item.except}</p>
{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}` }}>
{item.title}
</h2>
<p className={clsn(cover && "mr-40", "mb-8 relative")}>{item.except}</p>
<div className="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" />
{item.likes}
</span>
</div>
{cover && (
<div