mirror of
https://github.com/BradNut/svelteKitForBeginners
synced 2025-09-08 17:40:24 +00:00
Add profile page.
This commit is contained in:
parent
3ba06b230b
commit
5e44e9516e
2 changed files with 172 additions and 0 deletions
124
src/routes/home/profile/[user].svelte
Normal file
124
src/routes/home/profile/[user].svelte
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<script lang="ts">
|
||||
import type { User } from '@prisma/client'
|
||||
|
||||
import Tweet from '$root/components/tweet.svelte'
|
||||
import type { TweetType } from '$root/types'
|
||||
|
||||
export let profile: User
|
||||
export let tweets: TweetType[]
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{profile.name} ({profile.handle})</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="profile">
|
||||
<img
|
||||
class="banner"
|
||||
src="/profile/{profile.name}/banner.webp"
|
||||
alt="Profile Banner"
|
||||
>
|
||||
<img
|
||||
class="avatar"
|
||||
src={profile.avatar}
|
||||
alt={profile.name}
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="user">
|
||||
<span class="name">{profile.name}</span>
|
||||
<span class="handle">{profile.handle}</span>
|
||||
</div>
|
||||
<div class="about">
|
||||
<span class="about">{profile.about}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<a href="/" class="active">Tweets</a>
|
||||
<a href="/">Tweets & replies</a>
|
||||
<a href="/">Media</a>
|
||||
<a href="/">Likes</a>
|
||||
</nav>
|
||||
|
||||
{#each tweets as tweet (tweet.id)}
|
||||
<Tweet {tweet} />
|
||||
{/each}
|
||||
|
||||
<style>
|
||||
.profile {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-rows: 200px 60px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 1 / 2;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
grid-column: 1 / 2;
|
||||
grid-row: 1 / -1;
|
||||
place-self: center;
|
||||
align-self: flex-end;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin: 0 var(--spacing-16);
|
||||
border-radius: 50%;
|
||||
border: 4px solid var(--color-bg-primary);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--spacing-16);
|
||||
margin-top: var(--spacing-16);
|
||||
padding: 0 var(--spacing-16);
|
||||
}
|
||||
|
||||
.user {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: var(--font-24);
|
||||
font-weight: 700;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.handle {
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: var(--spacing-32);
|
||||
border-bottom: 1px solid var(--color-border-primary);
|
||||
}
|
||||
|
||||
a {
|
||||
padding: var(--spacing-16) var(--spacing-32);
|
||||
font-size: var(--font-16);
|
||||
color: var(--color-text-muted);
|
||||
border-bottom: 4px solid transparent;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background-color: var(--color-link-hover);
|
||||
border-bottom: 4px solid var(--color-brand);
|
||||
}
|
||||
|
||||
.active {
|
||||
font-weight: 700;
|
||||
border-bottom: 4px solid var(--color-brand);
|
||||
}
|
||||
</style>
|
||||
48
src/routes/home/profile/[user].ts
Normal file
48
src/routes/home/profile/[user].ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import type { RequestHandler } from "@sveltejs/kit";
|
||||
|
||||
import prisma from "$root/lib/prisma";
|
||||
import { timePosted } from "$root/lib/date";
|
||||
|
||||
export const get: RequestHandler = async ({ params }) => {
|
||||
const profile = await prisma.user.findFirst({
|
||||
where: { name: params.user }
|
||||
})
|
||||
|
||||
const tweets = await prisma.tweet.findMany({
|
||||
where: { user: { id: 1 } },
|
||||
include: { user: true },
|
||||
orderBy: { posted: 'desc' }
|
||||
})
|
||||
|
||||
const liked = await prisma.liked.findMany({
|
||||
where: { userId: 1 },
|
||||
select: { tweetId: true }
|
||||
})
|
||||
|
||||
const likedTweets = Object.keys(liked).map(
|
||||
key => liked[key].tweetId
|
||||
)
|
||||
|
||||
if (!profile || !tweets || tweets.length === 0) {
|
||||
return { status: 404 }
|
||||
}
|
||||
|
||||
const userTweets = tweets.map(tweet => {
|
||||
return {
|
||||
id: tweet.id,
|
||||
content: tweet.content,
|
||||
likes: tweet.likes,
|
||||
posted: timePosted(tweet.posted),
|
||||
url: tweet.url,
|
||||
avatar: tweet.user.avatar,
|
||||
handle: tweet.user.handle,
|
||||
name: tweet.user.name,
|
||||
liked: likedTweets.includes(tweet.id)
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
status: 200,
|
||||
body: { profile, tweets: userTweets }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue