Skip to content

Commit 0e4ca9f

Browse files
committed
feat(resources): add get_random_resources function and update resource components to include author details
1 parent 908380e commit 0e4ca9f

File tree

6 files changed

+79
-23
lines changed

6 files changed

+79
-23
lines changed

docs/etc/queries.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,51 @@ with check (
116116
)
117117
);
118118
```
119+
120+
```sql
121+
create or replace function get_random_resources()
122+
returns table (
123+
id uuid,
124+
name text,
125+
slug text,
126+
url text,
127+
description text,
128+
image text,
129+
tags text[],
130+
status text,
131+
created_at timestamp with time zone,
132+
category jsonb,
133+
author jsonb
134+
)
135+
language sql
136+
as $$
137+
select
138+
r.id,
139+
r.name,
140+
r.slug,
141+
r.url,
142+
r.description,
143+
r.image,
144+
r.tags,
145+
r.status,
146+
r.created_at,
147+
jsonb_build_object(
148+
'id', c.id,
149+
'name', c.name,
150+
'slug', c.slug,
151+
'created_at', c.created_at
152+
) as category,
153+
jsonb_build_object(
154+
'id', p.id,
155+
'username', p.username,
156+
'full_name', p.full_name,
157+
'avatar_url', p.avatar_url
158+
) as author
159+
from resources r
160+
join categories c on r.category = c.id
161+
join profiles p on r.author = p.id
162+
order by random()
163+
limit 10
164+
$$;
165+
166+
```

src/actions/resources.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ export const getResources = async (): Promise<ResourceList[]> => {
2222

2323
export const getAllResources = async (): Promise<Resource[]> => {
2424
const supabase = await createClient();
25-
const { data, error } = await supabase
26-
.from("resources")
27-
.select(`*, category:categories (id, name, slug, created_at)`);
25+
const { data, error } = await supabase.from("resources").select(`*,
26+
category:categories (id, name, slug, created_at),
27+
author:profiles (id, username, full_name, avatar_url)`);
2828

2929
if (error) throw new Error(error.message);
3030
return data;
@@ -84,7 +84,9 @@ export const getResourceBySlug = async (
8484
const supabase = await createClient();
8585
const { data, error } = await supabase
8686
.from("resources")
87-
.select("*")
87+
.select(
88+
"*, category:categories (id, name, slug, created_at), author:profiles (id, username, full_name, avatar_url)",
89+
)
8890
.eq("slug", slug)
8991
.single();
9092

src/components/resources/resource-card.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,24 @@ export default function ResourceCard({ resource }: Props) {
1717
<Card
1818
isBlurred
1919
radius="none"
20-
className="bg-white dark:bg-neutral-950 transition-colors duration-1000 !outline-none shadow-none rounded-xl border-2 border-neutral-200 dark:border-neutral-800"
20+
className="bg-white dark:bg-neutral-950 !outline-none shadow-none rounded-xl border-2 border-neutral-200 dark:border-neutral-800 group-hover:border-neutral-300 dark:group-hover:border-neutral-700"
2121
>
22-
<figure className="relative border-b-2 border-neutral-200 dark:border-neutral-800 overflow-hidden">
23-
<span className="hidden group-hover:block absolute top-2 right-2 bg-neutral-950 dark:bg-white text-white dark:text-neutral-950 px-2 py-1 rounded-lg text-xs z-50">
22+
<figure className="relative border-b-2 border-neutral-200 dark:border-neutral-800 overflow-hidden aspect-[2/1]">
23+
<span className="hidden group-hover:block absolute top-2 right-2 bg-neutral-950 dark:bg-white text-white dark:text-neutral-950 px-2 py-1 rounded-lg text-xs z-50 shadow-md">
2424
{resource.category?.name ?? "Uncategorized"}
2525
</span>
2626
<Image
2727
isBlurred
2828
src={resource.image}
2929
alt={resource.name}
3030
title={resource.name}
31-
width={400}
32-
height={200}
3331
loading="lazy"
3432
radius="none"
35-
className="transform transition-transform duration-300 group-hover:scale-105"
33+
sizes="(max-width: 768px) 100vw, (max-width: 1024px) 50vw, 33vw"
34+
className="w-full h-full object-cover"
3635
/>
3736
</figure>
38-
<CardFooter>
37+
<CardFooter className="min-h-[80px]">
3938
<div className="flex flex-col gap-2">
4039
<h2 className="text-sm font-medium line-clamp-2">
4140
{resource.name}
@@ -47,8 +46,9 @@ export default function ResourceCard({ resource }: Props) {
4746
size="sm"
4847
variant="flat"
4948
radius="sm"
50-
startContent={<Hash className="h-4 w-4" />}
49+
startContent={<Hash className="h-3 w-3" />}
5150
className="flex items-center gap-1"
51+
classNames={{ content: "text-xs" }}
5252
>
5353
{tag}
5454
</Chip>

src/components/resources/resource-detail.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
import type { Resource } from "@/types";
44

55
import Link from "next/link";
6-
import Image from "next/image";
7-
import { Avatar, Button, Card, Chip } from "@heroui/react";
6+
import { Avatar, Button, Card, Chip, Image } from "@heroui/react";
87
import { formatDistanceToNow } from "date-fns";
98
import { ArrowUpRight, Clock, Hash } from "lucide-react";
109

@@ -89,13 +88,20 @@ export default function ResourceDetail({ resource }: Props) {
8988
</div>
9089

9190
<footer className="flex justify-between">
92-
<div className="flex gap-4">
93-
<div className="flex items-center gap-2 text-sm text-neutral-500">
94-
by{" "}
95-
<span className="text-neutral-950 dark:text-white font-medium">
96-
{comments[0].author.name}
97-
</span>
98-
</div>
91+
<div className="flex justify-center items-center gap-3 text-sm text-gray-500">
92+
{resource.author.avatar_url && (
93+
<Image
94+
src={resource.author.avatar_url}
95+
alt={resource.author.username}
96+
width={18}
97+
height={18}
98+
radius="full"
99+
className="border-2 border-neutral-200 dark:border-neutral-800"
100+
/>
101+
)}
102+
<span className="hover:underline">
103+
{resource.author.full_name || resource.author.username}
104+
</span>
99105
</div>
100106
<div className="flex gap-2">
101107
<Button

src/components/resources/resource-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type Props = {
1010

1111
export default function ResourceList({ resources }: Props) {
1212
return (
13-
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
13+
<section className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
1414
{resources.map((resource) => (
1515
<ResourceCard key={resource.id} resource={resource} />
1616
))}

src/types/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export type Resource = {
3333
description?: string;
3434
image: string;
3535
tags: string[];
36-
author: string;
36+
author: ProfilePublic;
3737
category: Category;
3838
status: "pending" | "approved" | "rejected";
3939
created_at: string;

0 commit comments

Comments
 (0)