Files
spsays-training/app/(app)/u/me/page.tsx
T
2026-06-15 23:54:34 +05:30

114 lines
3.4 KiB
TypeScript

"use client";
/**
* /u/me — owner Posts grid (the default tab).
*
* Grid-only — no Grid/Scroll toggle. Tapping a thumbnail jumps to
* /u/me/posts#post-<id> where the Instagram-style scroll feed renders
* the full passages.
*
* Editing the profile lives on its own page (/settings/profile), reached
* from the header's "Edit profile" button.
*/
import { useEffect, useState } from "react";
import { LayoutGrid } from "lucide-react";
import { useAuth } from "@/components/auth/auth-provider";
import { PostGridCard } from "@/components/social/post/post-grid-card";
import { ConfirmModal } from "@/components/ui/confirm-modal";
import { posts, SocialError, type Post } from "@/lib/social";
export default function MyProfilePage() {
const { user } = useAuth();
const [feed, setFeed] = useState<Post[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
// Post id pending confirmation — modal opens when non-null and runs
// the actual delete on confirm.
const [pendingDelete, setPendingDelete] = useState<string | null>(null);
useEffect(() => {
if (!user) return;
posts
.mine()
.then((rows) => setFeed(rows ?? []))
.catch((err) =>
setError(
err instanceof SocialError ? err.message : "Could not load posts.",
),
)
.finally(() => setLoading(false));
}, [user]);
// Card delete buttons stage an id; ConfirmModal runs `performDelete`
// when the user confirms. We throw on failure so the modal stays open
// with an inline error message.
async function performDelete() {
const id = pendingDelete;
if (!id) return;
const prev = feed;
setFeed((rows) => rows.filter((p) => p.id !== id));
try {
await posts.delete(id);
} catch (err) {
setFeed(prev);
const msg =
err instanceof SocialError ? err.message : "Could not delete.";
setError(msg);
throw new Error(msg);
}
}
function onPostUpdated(updated: Post) {
setFeed((rows) => rows.map((p) => (p.id === updated.id ? updated : p)));
}
if (!user) return null;
return (
<section>
{error ? (
<p className="text-sm text-destructive">{error}</p>
) : loading ? (
<p className="text-sm text-muted-foreground">Loading…</p>
) : feed.length === 0 ? (
<EmptyPosts />
) : (
<div className="grid grid-cols-2 gap-2 sm:gap-3">
{feed.map((p) => (
<PostGridCard
key={p.id}
post={p}
onDelete={(id) => setPendingDelete(id)}
onUpdated={onPostUpdated}
href={`/u/me/posts#post-${p.id}`}
/>
))}
</div>
)}
<ConfirmModal
open={!!pendingDelete}
onClose={() => setPendingDelete(null)}
title="Delete this post?"
message="The post will be removed permanently from your feed and from any collections it's in. This can't be undone."
confirmLabel="Delete post"
onConfirm={performDelete}
/>
</section>
);
}
function EmptyPosts() {
return (
<div className="flex flex-col items-center text-center gap-3 py-12 text-muted-foreground">
<LayoutGrid className="size-8" />
<p className="text-sm">
You haven&apos;t posted anything yet. Select any passage in the
knowledgebase and use the toolbar to share it to your feed.
</p>
</div>
);
}