Add ImagePreview to Fetch and set privacy policy
This commit is contained in:
parent
a08f13b9e5
commit
3e3b64cf00
4 changed files with 20 additions and 18 deletions
|
@ -2,6 +2,7 @@ import React from "react"
|
||||||
import { FetchPost, MediaPathTrc, SinglePost_t } from "./api"
|
import { FetchPost, MediaPathTrc, SinglePost_t } from "./api"
|
||||||
import { z } from 'zod/v4'
|
import { z } from 'zod/v4'
|
||||||
import { useInfiniteQuery } from "@tanstack/react-query"
|
import { useInfiniteQuery } from "@tanstack/react-query"
|
||||||
|
import ImageWithPreview from "./ImageWithPrview"
|
||||||
|
|
||||||
// type fetched = z.infer<typeof FetchPost_t>
|
// type fetched = z.infer<typeof FetchPost_t>
|
||||||
|
|
||||||
|
@ -9,15 +10,12 @@ const Single = ({ post }: { post: z.infer<typeof SinglePost_t> }) => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-full bg-gray-200 rounded-lg shadow-md p-6 flex flex-col gap-4 snap-start">
|
<div className="w-full max-w-full bg-gray-200 rounded-lg shadow-md p-6 flex flex-col gap-4 snap-start">
|
||||||
<p className="text-gray-800 text-base leading-relaxed break-all whitespace-pre-wrap">{post.content}</p>
|
<p className="text-gray-800 text-base leading-relaxed break-all whitespace-pre-wrap">{post.content}</p>
|
||||||
{post.enclosure.length > 0 && post.enclosure[0] != null && <div className="flex flex-row overflow-x-auto gap-3 py-2 -mx-2 px-2 border-t border-gray-200 pt-4">
|
{post.enclosure.length > 0 && post.enclosure[0] != null && <div className="flex flex-row overflow-x-auto gap-3 py-2 -mx-2 px-2 border-t border-gray-200 pt-4 h-32">
|
||||||
{post.enclosure.map((enc, index) => {
|
{post.enclosure.map((enc, index) => {
|
||||||
if (enc) {
|
if (enc) {
|
||||||
return <img
|
return <ImageWithPreview
|
||||||
key={index}
|
key={index}
|
||||||
src={MediaPathTrc(enc)}
|
src={MediaPathTrc(enc)}
|
||||||
alt={`Post media ${post.id}-${index}`}
|
|
||||||
loading="lazy"
|
|
||||||
className="rounded-md h-32 object-cover aspect-video flex-shrink-0"
|
|
||||||
/>
|
/>
|
||||||
} else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
@ -5,7 +5,7 @@ const ImageWithPreview = ({
|
||||||
remove,
|
remove,
|
||||||
}: {
|
}: {
|
||||||
src: string
|
src: string
|
||||||
remove: () => void
|
remove?: () => void
|
||||||
}) => {
|
}) => {
|
||||||
const [show, setShow] = useState(false)
|
const [show, setShow] = useState(false)
|
||||||
return (
|
return (
|
||||||
|
@ -26,14 +26,14 @@ const ImageWithPreview = ({
|
||||||
onClick={() => setShow(false)}
|
onClick={() => setShow(false)}
|
||||||
>
|
>
|
||||||
<div className="z-20 w-full md:w-fit fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 md:w-[50dvw]">
|
<div className="z-20 w-full md:w-fit fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 md:w-[50dvw]">
|
||||||
<img src={src} className="w-[90dvw] h-auto m-auto md:w-auto md:max-h-[80dvh]" />
|
<img src={src} className="w-[90dvw] h-auto m-auto md:w-auto md:max-h-[80dvh]" loading='lazy' />
|
||||||
<button
|
{remove && <button
|
||||||
type="button"
|
type="button"
|
||||||
className="mt-6 w-full py-3 bg-gray-800 text-white font-semibold rounded-lg hover:bg-gray-700 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed" // Consistent button styling
|
className="mt-6 w-full py-3 bg-gray-800 text-white font-semibold rounded-lg hover:bg-gray-700 transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed" // Consistent button styling
|
||||||
onClick={() => remove()}
|
onClick={() => remove()}
|
||||||
>
|
>
|
||||||
刪除
|
刪除
|
||||||
</button>
|
</button>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
5
src/Policy.tsx
Normal file
5
src/Policy.tsx
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export const Policy = () => {
|
||||||
|
return <div className="w-full h-fit">
|
||||||
|
Test
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -25,13 +25,11 @@ export const Zone = ({ setZone }: { setZone: (zone_name: string) => void }) => {
|
||||||
|
|
||||||
{/* Drawer handle/button */}
|
{/* Drawer handle/button */}
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{/* Visual handle indicator */}
|
|
||||||
<div className="w-12 h-1 bg-zinc-500 rounded-full mx-auto mt-3 mb-2" />
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={() => setToggle(!toggle)}
|
onClick={() => setToggle(!toggle)}
|
||||||
className="w-full py-3 px-6 text-white font-medium text-lg
|
className="w-full py-3 px-6 text-white font-medium text-lg
|
||||||
hover:bg-zinc-700 transition-colors duration-200
|
transition-colors duration-200
|
||||||
flex items-center justify-center gap-2"
|
flex items-center justify-center gap-2"
|
||||||
>
|
>
|
||||||
<span>選擇功能</span>
|
<span>選擇功能</span>
|
||||||
|
@ -50,7 +48,7 @@ export const Zone = ({ setZone }: { setZone: (zone_name: string) => void }) => {
|
||||||
{[
|
{[
|
||||||
{ key: 'post', label: 'PO文', icon: '✏️', delay: '100ms' },
|
{ key: 'post', label: 'PO文', icon: '✏️', delay: '100ms' },
|
||||||
{ key: 'delete', label: '刪文', icon: '🗑️', delay: '200ms' },
|
{ key: 'delete', label: '刪文', icon: '🗑️', delay: '200ms' },
|
||||||
{ key: 'view', label: '查看', icon: '👁️', delay: '300ms' }
|
{ key: 'view', label: '查看', icon: '👁️', delay: '300ms' },
|
||||||
].map(({ key, label, icon, delay }) => (
|
].map(({ key, label, icon, delay }) => (
|
||||||
<button
|
<button
|
||||||
key={key}
|
key={key}
|
||||||
|
@ -71,6 +69,7 @@ export const Zone = ({ setZone }: { setZone: (zone_name: string) => void }) => {
|
||||||
<span>{label}</span>
|
<span>{label}</span>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
|
<p className='text-slate-500 hover:text-gray-300 active:text-gray-200 w-fit mx-auto'>隱私政策:我們會搜集IP</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue