mirror of
https://github.com/Ategon/Jamjar.git
synced 2025-02-12 06:16:21 +00:00
Add post times
This commit is contained in:
parent
3df39a4405
commit
feb80916cc
5 changed files with 188 additions and 16 deletions
|
@ -1,7 +1,17 @@
|
||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
images: {
|
||||||
|
remotePatterns: [
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "static-cdn.jtvnw.net",
|
||||||
|
port: "",
|
||||||
|
pathname: "/**",
|
||||||
|
search: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import PostCard from "./PostCard";
|
import PostCard from "./PostCard";
|
||||||
import { PostType } from "@/types/PostType";
|
import { PostType } from "@/types/PostType";
|
||||||
import {
|
import {
|
||||||
|
@ -14,12 +14,31 @@ import { PostSort } from "@/types/PostSort";
|
||||||
import { PostStyle } from "@/types/PostStyle";
|
import { PostStyle } from "@/types/PostStyle";
|
||||||
import { getCookie } from "@/helpers/cookie";
|
import { getCookie } from "@/helpers/cookie";
|
||||||
import { UserType } from "@/types/UserType";
|
import { UserType } from "@/types/UserType";
|
||||||
import { LoaderCircle } from "lucide-react";
|
import {
|
||||||
|
Calendar,
|
||||||
|
Calendar1,
|
||||||
|
CalendarArrowDown,
|
||||||
|
CalendarCog,
|
||||||
|
CalendarDays,
|
||||||
|
CalendarFold,
|
||||||
|
CalendarRange,
|
||||||
|
Clock1,
|
||||||
|
Clock2,
|
||||||
|
Clock3,
|
||||||
|
Clock4,
|
||||||
|
ClockArrowDown,
|
||||||
|
ClockArrowUp,
|
||||||
|
LoaderCircle,
|
||||||
|
Sparkles,
|
||||||
|
Trophy,
|
||||||
|
} from "lucide-react";
|
||||||
import { toast } from "react-toastify";
|
import { toast } from "react-toastify";
|
||||||
|
import { PostTime } from "@/types/PostTimes";
|
||||||
|
|
||||||
export default function Posts() {
|
export default function Posts() {
|
||||||
const [posts, setPosts] = useState<PostType[]>();
|
const [posts, setPosts] = useState<PostType[]>();
|
||||||
const [sort, setSort] = useState<PostSort>("newest");
|
const [sort, setSort] = useState<PostSort>("newest");
|
||||||
|
const [time, setTime] = useState<PostTime>("all");
|
||||||
const [style, setStyle] = useState<PostStyle>("cozy");
|
const [style, setStyle] = useState<PostStyle>("cozy");
|
||||||
const [user, setUser] = useState<UserType>();
|
const [user, setUser] = useState<UserType>();
|
||||||
const [loading, setLoading] = useState<boolean>(true);
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
|
@ -45,8 +64,8 @@ export default function Posts() {
|
||||||
// Fetch posts with userSlug if user is available
|
// Fetch posts with userSlug if user is available
|
||||||
const postsResponse = await fetch(
|
const postsResponse = await fetch(
|
||||||
process.env.NEXT_PUBLIC_MODE === "PROD"
|
process.env.NEXT_PUBLIC_MODE === "PROD"
|
||||||
? `https://d2jam.com/api/v1/posts?sort=${sort}&user=${userData.slug}`
|
? `https://d2jam.com/api/v1/posts?sort=${sort}&user=${userData.slug}&time=${time}`
|
||||||
: `http://localhost:3005/api/v1/posts?sort=${sort}&user=${userData.slug}`
|
: `http://localhost:3005/api/v1/posts?sort=${sort}&user=${userData.slug}&time=${time}`
|
||||||
);
|
);
|
||||||
setPosts(await postsResponse.json());
|
setPosts(await postsResponse.json());
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -56,8 +75,8 @@ export default function Posts() {
|
||||||
// Fetch posts without userSlug if user is not available
|
// Fetch posts without userSlug if user is not available
|
||||||
const postsResponse = await fetch(
|
const postsResponse = await fetch(
|
||||||
process.env.NEXT_PUBLIC_MODE === "PROD"
|
process.env.NEXT_PUBLIC_MODE === "PROD"
|
||||||
? `https://d2jam.com/api/v1/posts?sort=${sort}`
|
? `https://d2jam.com/api/v1/posts?sort=${sort}&time=${time}`
|
||||||
: `http://localhost:3005/api/v1/posts?sort=${sort}`
|
: `http://localhost:3005/api/v1/posts?sort=${sort}&time=${time}`
|
||||||
);
|
);
|
||||||
setPosts(await postsResponse.json());
|
setPosts(await postsResponse.json());
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
@ -65,7 +84,94 @@ export default function Posts() {
|
||||||
};
|
};
|
||||||
|
|
||||||
loadUserAndPosts();
|
loadUserAndPosts();
|
||||||
}, [sort]);
|
}, [sort, time]);
|
||||||
|
|
||||||
|
const sorts: Record<
|
||||||
|
PostSort,
|
||||||
|
{ name: string; icon: ReactNode; description: string }
|
||||||
|
> = {
|
||||||
|
top: {
|
||||||
|
name: "Top",
|
||||||
|
icon: <Trophy />,
|
||||||
|
description: "Shows the most liked posts first",
|
||||||
|
},
|
||||||
|
newest: {
|
||||||
|
name: "Newest",
|
||||||
|
icon: <ClockArrowUp />,
|
||||||
|
description: "Shows the newest posts first",
|
||||||
|
},
|
||||||
|
oldest: {
|
||||||
|
name: "Oldest",
|
||||||
|
icon: <ClockArrowDown />,
|
||||||
|
description: "Shows the oldest posts first",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const times: Record<
|
||||||
|
PostTime,
|
||||||
|
{ name: string; icon: ReactNode; description: string }
|
||||||
|
> = {
|
||||||
|
hour: {
|
||||||
|
name: "Hour",
|
||||||
|
icon: <Clock1 />,
|
||||||
|
description: "Shows posts from the last hour",
|
||||||
|
},
|
||||||
|
three_hours: {
|
||||||
|
name: "Three Hours",
|
||||||
|
icon: <Clock2 />,
|
||||||
|
description: "Shows posts from the last three hours",
|
||||||
|
},
|
||||||
|
six_hours: {
|
||||||
|
name: "Six Hours",
|
||||||
|
icon: <Clock3 />,
|
||||||
|
description: "Shows posts from the last six hours",
|
||||||
|
},
|
||||||
|
twelve_hours: {
|
||||||
|
name: "Twelve Hours",
|
||||||
|
icon: <Clock4 />,
|
||||||
|
description: "Shows posts from the last twelve hours",
|
||||||
|
},
|
||||||
|
day: {
|
||||||
|
name: "Day",
|
||||||
|
icon: <Calendar />,
|
||||||
|
description: "Shows posts from the last day",
|
||||||
|
},
|
||||||
|
week: {
|
||||||
|
name: "Week",
|
||||||
|
icon: <CalendarDays />,
|
||||||
|
description: "Shows posts from the last week",
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
name: "Month",
|
||||||
|
icon: <CalendarRange />,
|
||||||
|
description: "Shows posts from the last month",
|
||||||
|
},
|
||||||
|
three_months: {
|
||||||
|
name: "Three Months",
|
||||||
|
icon: <CalendarFold />,
|
||||||
|
description: "Shows posts from the last three months",
|
||||||
|
},
|
||||||
|
six_months: {
|
||||||
|
name: "Six Months",
|
||||||
|
icon: <CalendarCog />,
|
||||||
|
description: "Shows posts from the last six months",
|
||||||
|
},
|
||||||
|
nine_months: {
|
||||||
|
name: "Nine Months",
|
||||||
|
icon: <CalendarArrowDown />,
|
||||||
|
description: "Shows posts from the last nine months",
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
name: "Year",
|
||||||
|
icon: <Calendar1 />,
|
||||||
|
description: "Shows posts from the last year",
|
||||||
|
},
|
||||||
|
all: {
|
||||||
|
name: "All Times",
|
||||||
|
icon: <Sparkles />,
|
||||||
|
description: "Shows all posts",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -78,7 +184,7 @@ export default function Posts() {
|
||||||
className="text-xs bg-white dark:bg-[#252525] !duration-250 !ease-linear !transition-all text-[#333] dark:text-white"
|
className="text-xs bg-white dark:bg-[#252525] !duration-250 !ease-linear !transition-all text-[#333] dark:text-white"
|
||||||
variant="faded"
|
variant="faded"
|
||||||
>
|
>
|
||||||
{sort.charAt(0).toUpperCase() + sort.slice(1)}
|
{sorts[sort]?.name}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownTrigger>
|
</DropdownTrigger>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
|
@ -87,9 +193,42 @@ export default function Posts() {
|
||||||
}}
|
}}
|
||||||
className="text-[#333] dark:text-white"
|
className="text-[#333] dark:text-white"
|
||||||
>
|
>
|
||||||
<DropdownItem key="newest">Newest</DropdownItem>
|
{Object.entries(sorts).map(([key, sort]) => (
|
||||||
<DropdownItem key="top">Top</DropdownItem>
|
<DropdownItem
|
||||||
<DropdownItem key="oldest">Oldest</DropdownItem>
|
key={key}
|
||||||
|
startContent={sort.icon}
|
||||||
|
description={sort.description}
|
||||||
|
>
|
||||||
|
{sort.name}
|
||||||
|
</DropdownItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownTrigger>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
className="text-xs bg-white dark:bg-[#252525] !duration-250 !ease-linear !transition-all text-[#333] dark:text-white"
|
||||||
|
variant="faded"
|
||||||
|
>
|
||||||
|
{times[time]?.name}
|
||||||
|
</Button>
|
||||||
|
</DropdownTrigger>
|
||||||
|
<DropdownMenu
|
||||||
|
onAction={(key) => {
|
||||||
|
setTime(key as PostTime);
|
||||||
|
}}
|
||||||
|
className="text-[#333] dark:text-white"
|
||||||
|
>
|
||||||
|
{Object.entries(times).map(([key, sort]) => (
|
||||||
|
<DropdownItem
|
||||||
|
key={key}
|
||||||
|
startContent={sort.icon}
|
||||||
|
description={sort.description}
|
||||||
|
>
|
||||||
|
{sort.name}
|
||||||
|
</DropdownItem>
|
||||||
|
))}
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button
|
<Button
|
||||||
|
@ -138,10 +277,15 @@ export default function Posts() {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col gap-3 p-4">
|
<div className="flex flex-col gap-3 p-4">
|
||||||
{posts &&
|
{posts && posts.length > 0 ? (
|
||||||
posts.map((post) => (
|
posts.map((post) => (
|
||||||
<PostCard key={post.id} post={post} style={style} user={user} />
|
<PostCard key={post.id} post={post} style={style} user={user} />
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<p className="text-center text-[#333] dark:text-white transition-color duration-250 ease-linear">
|
||||||
|
No posts match your filters
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { FeaturedStreamerType } from "@/types/FeaturedStreamerType";
|
import { FeaturedStreamerType } from "@/types/FeaturedStreamerType";
|
||||||
|
import { Image } from "@nextui-org/react";
|
||||||
|
import NextImage from "next/image";
|
||||||
|
|
||||||
export default function Streams() {
|
export default function Streams() {
|
||||||
const [streamers, setStreamers] = useState<FeaturedStreamerType[]>([]);
|
const [streamers, setStreamers] = useState<FeaturedStreamerType[]>([]);
|
||||||
|
@ -64,10 +66,13 @@ export default function Streams() {
|
||||||
margin: "0 auto",
|
margin: "0 auto",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<Image
|
||||||
|
as={NextImage}
|
||||||
src={currentStreamer.thumbnailUrl}
|
src={currentStreamer.thumbnailUrl}
|
||||||
alt={`${currentStreamer.userName}'s thumbnail`}
|
alt={`${currentStreamer.userName}'s thumbnail`}
|
||||||
style={{ width: "100%", borderRadius: "4px", marginBottom: "10px" }}
|
style={{ width: "100%", borderRadius: "4px", marginBottom: "10px" }}
|
||||||
|
width={320}
|
||||||
|
height={180}
|
||||||
/>
|
/>
|
||||||
<a
|
<a
|
||||||
href={`https://twitch.tv/${currentStreamer.userName}`}
|
href={`https://twitch.tv/${currentStreamer.userName}`}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export type PostSort = "newest" | "oldest";
|
export type PostSort = "newest" | "oldest" | "top";
|
||||||
|
|
13
src/types/PostTimes.ts
Normal file
13
src/types/PostTimes.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
export type PostTime =
|
||||||
|
| "hour"
|
||||||
|
| "three_hours"
|
||||||
|
| "six_hours"
|
||||||
|
| "twelve_hours"
|
||||||
|
| "day"
|
||||||
|
| "week"
|
||||||
|
| "month"
|
||||||
|
| "three_months"
|
||||||
|
| "six_months"
|
||||||
|
| "nine_months"
|
||||||
|
| "year"
|
||||||
|
| "all";
|
Loading…
Reference in a new issue