Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions platforms/pictique/src/lib/fragments/Post/Post.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { ArrowLeftIcon, ArrowRightIcon, RecordIcon } from '@hugeicons/core-free-icons';
import { HugeiconsIcon } from '@hugeicons/svelte';
import type { HTMLAttributes } from 'svelte/elements';
import { Spring } from 'svelte/motion';

interface IPostProps extends HTMLAttributes<HTMLElement> {
avatar: string;
Expand Down Expand Up @@ -92,6 +93,20 @@
const img = event.target as HTMLImageElement;
img.src = 'https://picsum.photos/200';
}

const scale = new Spring(1, {
stiffness: 0.15,
damping: 0.25
});

async function handleLikeWithInteraction() {
scale.target = 1.4;
try {
await callback.like();
} finally {
setTimeout(() => (scale.target = 1), 150);
}
}
</script>

<article {...restProps} class={cn(['flex w-full flex-col gap-4', restProps.class])}>
Expand Down Expand Up @@ -168,14 +183,19 @@
{#if count}
<div class="flex gap-4">
<button
class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200"
onclick={callback.like}
class="group cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 transition-colors hover:bg-gray-200 active:bg-gray-300"
onclick={handleLikeWithInteraction}
>
<Like
size="24px"
color="var(--color-red-500"
fill={isLiked ? 'var(--color-red-500)' : 'white'}
/>
<div
style="transform: scale({scale.current}); display: flex; align-items: center; justify-content: center;"
>
<Like
size="24px"
color={'var(--color-red-500)'}
fill={isLiked ? 'var(--color-red-500)' : 'transparent'}
class="transition-all duration-300"
/>
</div>
</button>
<button
class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200"
Expand Down
40 changes: 30 additions & 10 deletions platforms/pictique/src/lib/fragments/PostModal/PostModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { HugeiconsIcon } from '@hugeicons/svelte';
import type { HTMLAttributes } from 'svelte/elements';
import { MessageInput } from '..';
import { Spring } from 'svelte/motion';

interface IPostProps extends HTMLAttributes<HTMLElement> {
avatar: string;
Expand Down Expand Up @@ -115,6 +116,20 @@
await callback.comment(commentValue);
commentValue = '';
};

const scale = new Spring(1, {
stiffness: 0.15,
damping: 0.25
});

async function handleLikeWithInteraction() {
scale.target = 1.4;
try {
await callback.like();
} finally {
setTimeout(() => (scale.target = 1), 150);
}
}
</script>

<article {...restProps} class={cn(['flex w-full gap-10', restProps.class])}>
Expand Down Expand Up @@ -195,7 +210,7 @@
<div class="flex w-full items-center justify-between md:hidden">
<div class="flex gap-4">
<button
class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200"
class="group cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 transition-colors hover:bg-gray-200 active:bg-gray-300"
onclick={callback.like}
>
<Like
Expand Down Expand Up @@ -289,18 +304,23 @@
<div class="flex w-full flex-col justify-between gap-3">
<div class="flex gap-4">
<button
class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200"
onclick={callback.like}
class="group cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 transition-colors hover:bg-gray-200 active:bg-gray-300"
onclick={handleLikeWithInteraction}
>
<Like
size="24px"
color="var(--color-red-500"
fill={isLiked ? 'var(--color-red-500)' : 'white'}
/>
<div
style="transform: scale({scale.current}); display: flex; align-items: center; justify-content: center;"
>
<Like
size="24px"
color={'var(--color-red-500)'}
fill={isLiked ? 'var(--color-red-500)' : 'transparent'}
class="transition-all duration-300"
/>
</div>
</button>
<button class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200">
<!-- <button class="cursor-pointer rounded-2xl bg-gray-100 px-4 py-3 hover:bg-gray-200">
<CommentIcon size="24px" color="black" fill="transparent" />
</button>
</button> -->
</div>
<p class="text-black/60">
{new Date(time).toLocaleDateString()}
Expand Down
4 changes: 2 additions & 2 deletions platforms/pictique/src/routes/(protected)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@
core concepts of the W3DS ecosystem.
</p>
<p>
<b>It is not a production-grade platform</b> and may lack full reliability, performance,
and security guarantees.
<b>It is not a production-grade platform</b> and may lack full reliability, performance, and
security guarantees.
</p>
<p>
We <b>strongly recommend</b> that you avoid sharing <b>sensitive or private content</b>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,13 @@
{@const nextMessage = index < messages.length - 1 ? messages[index + 1] : null}
{@const isHeadNeeded = Boolean(
!prevMessage ||
prevMessage.isOwn !== msg.isOwn ||
(prevMessage.senderId && msg.senderId && prevMessage.senderId !== msg.senderId)
prevMessage.isOwn !== msg.isOwn ||
(prevMessage.senderId && msg.senderId && prevMessage.senderId !== msg.senderId)
)}
{@const isTimestampNeeded = Boolean(
!nextMessage ||
nextMessage.isOwn !== msg.isOwn ||
(nextMessage.senderId && msg.senderId && nextMessage.senderId !== msg.senderId)
nextMessage.isOwn !== msg.isOwn ||
(nextMessage.senderId && msg.senderId && nextMessage.senderId !== msg.senderId)
)}
<ChatMessage
isOwn={msg.isOwn}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,25 @@
import { page } from '$app/state';
import { PostModal, Profile } from '$lib/fragments';
import { selectedPost } from '$lib/store/store.svelte';
import { createComment } from '$lib/stores/comments';
import { comments as commentsStore, createComment, fetchComments } from '$lib/stores/comments';
import { toggleLike } from '$lib/stores/posts';
import type { PostData, userProfile } from '$lib/types';
import { Modal } from '$lib/ui';
import { apiClient, getAuthId } from '$lib/utils/axios';
import { onMount } from 'svelte';

interface Comment {
id: string;
text: string;
createdAt: string;
author: {
id: string;
handle: string;
name: string;
avatarUrl: string;
};
}

let profileId = $derived(page.params.id);
let profile = $state<userProfile | null>(null);
let error = $state<string | null>(null);
Expand All @@ -22,7 +34,6 @@
return response.data;
}
});

async function fetchProfile() {
try {
loading = true;
Expand Down Expand Up @@ -59,10 +70,14 @@
}
}

function handlePostClick(post: PostData) {
console.log(post);
async function handlePostClick(post: PostData) {
selectedPost.value = post;
// goto("/profile/post");
try {
// Trigger the store to fetch comments for this specific post
await fetchComments(post.id);
} catch (err) {
console.error('Error loading comments:', err);
}
}

onMount(fetchProfile);
Expand Down Expand Up @@ -130,15 +145,33 @@
text={selectedPost.value?.caption ?? ''}
count={selectedPost.value?.count ?? { likes: 0, comments: 0 }}
{ownerProfile}
isLiked={ownerProfile
? ((selectedPost.value as any)?.likedBy?.some(
(user: any) => user.id === ownerProfile.id
) ?? false)
: false}
callback={{
like: async () => {
await toggleLike(selectedPost.value?.id ?? '');
if (!selectedPost.value?.id) return;
try {
const result = await toggleLike(selectedPost.value.id);
if (selectedPost.value && result?.likedBy) {
(selectedPost.value as any).likedBy = result.likedBy;
}
} catch (err) {
console.error('Failed to toggle like:', err);
}
},
comment: async (comment) => {
if (!selectedPost.value) return;
await createComment(selectedPost.value?.id, comment);
try {
await createComment(selectedPost.value.id, comment);
} catch (err) {
console.error('Failed to create comment:', err);
}
}
}}
comments={$commentsStore}
time={selectedPost.value?.time ?? ''}
/>
</Modal>
Expand Down