Refactor: Posts Page and Preview

This commit is contained in:
Donatas Kirda 2024-05-14 00:28:54 +03:00
parent a9cc16e2e6
commit 8419bc248f
Signed by: bloodwiing
GPG Key ID: 63020D8D3F4A164F
6 changed files with 240 additions and 57 deletions

97
src/comp/page/post.svelte Normal file
View File

@ -0,0 +1,97 @@
<script>
import moment from "moment";
import Mention from "$comp/mention.svelte";
import Comment from "$comp/comment.svelte";
import UserItem from "$comp/useritem.svelte";
import { buildCommentTree } from "$lib/client/nodetree";
import { getNamedId, gotoNamedId } from "$lib/util";
import { onMount } from "svelte";
import Rating from "$comp/rating.svelte";
/**
* @type {import("$types/base").Post}
*/
export let post;
/**
* @type {import("$types/base").CommentTreeNode[] | null}
*/
export let commentTree = null;
</script>
<style lang="scss">
.body {
width: 100%;
}
.post {
display: flex;
flex-direction: column;
gap: 16px
}
.postHead {
display: flex;
flex-flow: column nowrap;
gap: 8px;
align-items: center;
& > .date {
color: var(--white-dim);
}
}
.commentList {
display: flex;
flex-flow: column nowrap;
gap: 16px;
}
.comments {
display: flex;
flex-flow: column nowrap;
gap: 32px;
}
.commentsHead {
width: 100%;
border-bottom: 2px solid var(--accent-dim);
margin-top: 32px;
}
</style>
<div class="body">
<article class="post">
<div class="postHead">
<UserItem user={post.author} iconSize={28}></UserItem>
<h1 class="typeTitle">{post.name}</h1>
<span class="date">{moment(post.postDate).fromNow()}</span>
</div>
<p class="postContent">
{post.content}
</p>
<Rating rating={post.rating}></Rating>
</article>
<!-- <UserItem user={post.author}></UserItem>
<p>{post.content}</p> -->
<!-- <Message message={post}></Message> -->
{#if commentTree}
<section class="comments">
<h3 class="commentsHead typeName">Comments</h3>
<div class="commentList">
{#each commentTree as reply}
<Comment commentNode={reply}></Comment>
{/each}
</div>
</section>
{/if}
</div>

View File

@ -1,17 +1,28 @@
<script> <script>
import { getNamedId } from '$lib/util'; import moment from 'moment';
import Avatar from './avatar.svelte'; import { getNamedId } from '$lib/util';
import GlowFX from './fx/glowfx.svelte'; import Avatar from './avatar.svelte';
import PerspectiveFX from './fx/perspectivefx.svelte'; import GlowFX from './fx/glowfx.svelte';
import Mention from './mention.svelte'; import PerspectiveFX from './fx/perspectivefx.svelte';
import Rating from './rating.svelte'; import Mention from './mention.svelte';
import RatingVertical from './ratingvertical.svelte'; import Rating from './rating.svelte';
import Useritem from './useritem.svelte'; import RatingVertical from './ratingvertical.svelte';
import Useritem from './useritem.svelte';
import { goto } from '$app/navigation';
import { error } from '@sveltejs/kit';
import { createEventDispatcher } from 'svelte';
/** /**
* @type {import('$types/base').Post} * @type {import('$types/base').Post}
*/ */
export let post; export let post;
/**
* @type {boolean}
*/
export let opened = false;
const dispatch = createEventDispatcher();
</script> </script>
<style type="scss"> <style type="scss">
@ -38,7 +49,10 @@
} }
.postCard { .postCard {
display: block; display: flex;
flex-flow: column nowrap;
width: 100%;
text-decoration: none; text-decoration: none;
@ -69,17 +83,26 @@
.sidePad { .sidePad {
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
padding: 18px 0px; padding-top: 14px;
gap: 16px; gap: 16px;
} }
.mention { .mentionBar {
text-decoration: none; display: flex;
color: var(--accent); flex-flow: row nowrap;
padding: 0em 0.2em; gap: 8px;
background: var(--accent-dim); align-items: center;
border-radius: 0.2em;
& > .dot {
font-size: 0.4em;
color: var(--white-dim);
}
& > .date {
color: var(--white-dim);
}
} }
</style> </style>
<div class="postContainer"> <div class="postContainer">
@ -87,14 +110,20 @@
<Avatar size={32}></Avatar> <Avatar size={32}></Avatar>
<RatingVertical rating={post.rating}></RatingVertical> <RatingVertical rating={post.rating}></RatingVertical>
</div> </div>
<GlowFX borderRadius={18} opacity={0.7} style="flex: 1;"> <GlowFX borderRadius={18} opacity={0.7} style="flex: 1;">
<div class="postCardOutline"> <div class="postCardOutline" style={opened ? "opacity: 0.0;" : "opacity: 1.0;"}>
<a class="postCard" href="/posts/{getNamedId(post.id, post.name)}"> <button class="postCard" on:click={() => {dispatch('previewPost', {post: post});}}>
<Mention user={post.author}></Mention> <div class="mentionBar">
<Mention user={post.author}></Mention>
<span class="dot typeContent"></span>
<span class="date typeContent">{moment(post.postDate).fromNow()}</span>
</div>
<h6 class="title taviraj-regular">{post.name}</h6> <h6 class="title taviraj-regular">{post.name}</h6>
<p>{post.category.name}</p> <p class="typeContent">{post.category.name}</p>
<p>{post.content}</p> <p class="typeContent">{post.content}</p>
</a> </button>
</div> </div>
</GlowFX> </GlowFX>
</div> </div>

View File

@ -1,22 +1,105 @@
<script> <script>
import Postcard from './postcard.svelte'; import { goto } from '$app/navigation';
import { buildCommentTree } from '$lib/client/nodetree';
import { getNamedId } from '$lib/util';
import Post from './page/post.svelte';
import PostCard from './postcard.svelte';
/** /**
* @type {import("$types/base").Post[]} * @type {import("$types/base").Post[]}
*/ */
export let posts = []; export let posts = [];
/** @type {import("$types/base").Post | null} */
$: currentPreview = null;
/** @type {boolean[]} */
$: hidden = Array(posts.length).fill(false);
function previewPost(/** @type {CustomEvent<>} */ e) {
/** @type {import("$types/base").Post} */
const post = e.detail.post;
currentPreview = post;
posts.forEach((p, index) => {
hidden[index] = p == post;
});
}
function dismiss() {
currentPreview = null;
hidden = Array(posts.length).fill(false);
}
function expand() {
if (currentPreview == null) return;
goto(`/posts/${getNamedId(currentPreview.id, currentPreview.name)}`, {
replaceState: false
});
}
</script> </script>
<style> <style lang="scss">
.postList { .postList {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
} }
.postPreview {
display: flex;
position: fixed;
width: 100vw;
height: 100vh;
align-items: center;
justify-content: center;
background: #0a0a0a80;
backdrop-filter: blur(3px);
opacity: 0.0;
pointer-events: none;
top: 0;
left: 0;
&[data-visible] {
opacity: 1.0;
pointer-events: unset;
}
}
.preview {
width: 80vw;
display: flex;
flex-flow: column nowrap;
background: var(--background);
padding: 32px;
border-radius: 16px;
pointer-events: all;
box-shadow: 0px 0px 16px var(--accent-dim);
outline: 2px solid var(--accent-dim);
}
</style> </style>
<div class="postList"> <div class="postList">
{#each posts as post} {#each posts as post, index}
<Postcard post={post}></Postcard> <PostCard post={post} on:previewPost={previewPost} opened={hidden[index]}></PostCard>
{/each} {/each}
</div> </div>
<button class="postPreview" data-visible={currentPreview != null || null} on:click={dismiss}>
<button class="preview" on:click={expand}>
{#if currentPreview}
<Post post={currentPreview} commentTree={null}></Post>
{/if}
</button>
</button>

View File

View File

@ -23,6 +23,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
padding: 32px;
} }
</style> </style>

View File

@ -1,9 +1,7 @@
<script> <script>
import Comment from "$comp/comment.svelte"; import Post from "$comp/page/post.svelte";
import Mention from "$comp/mention.svelte";
import UserItem from "$comp/useritem.svelte";
import { buildCommentTree } from "$lib/client/nodetree"; import { buildCommentTree } from "$lib/client/nodetree";
import { getNamedId, gotoNamedId } from "$lib/util"; import { gotoNamedId } from "$lib/util";
import { onMount } from "svelte"; import { onMount } from "svelte";
/** /**
@ -15,36 +13,11 @@
export let data; export let data;
$: post = data.post; $: post = data.post;
$: commentTree = buildCommentTree(data.comments); $: commentTree = buildCommentTree(data.comments);
onMount(() => { onMount(() => {
gotoNamedId(post.id, post.name); gotoNamedId(post.id, post.name);
}) });
</script> </script>
<style> <Post post={post} commentTree={commentTree}></Post>
.post {
display: flex;
flex-direction: column;
}
h1 {
margin: 0;
text-align: center;
}
</style>
<div class="post">
<h1 class="taviraj-light">{post.name}</h1>
<UserItem user={post.author}></UserItem>
<p>{post.content}</p>
<div>
{#each commentTree as reply}
<Comment commentNode={reply}></Comment>
{/each}
</div>
</div>