feat: update components for multi-user support
- Add sharing indicator to ListCard showing collaborator count - Add permission badge and share button to ListDetailView - Disable editing in ItemForm for viewers with visual feedback - Add permission checks to item detail and edit pages - Hide edit/delete buttons for viewers on item detail page - Pass permission and collaborator data through component hierarchy - Update navigation to include profile and invitations links (already done in previous tasks) Implements task 15 from user-auth-and-sharing spec
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import { notFound } from 'next/navigation'
|
||||
import { getItem } from '@/lib/actions'
|
||||
import { canEditList } from '@/lib/permissions'
|
||||
import { auth } from '@/auth'
|
||||
import ItemDetail from '@/components/ItemDetail'
|
||||
import Link from 'next/link'
|
||||
import { ArrowLeft, Edit } from 'lucide-react'
|
||||
@@ -16,12 +18,29 @@ interface PageProps {
|
||||
}
|
||||
|
||||
export default async function ItemDetailPage({ params }: PageProps) {
|
||||
const item = await getItem(params.itemId)
|
||||
|
||||
if (!item || item.listId !== params.id) {
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
const itemData = await getItem(params.itemId)
|
||||
|
||||
if (!itemData || itemData.listId !== params.id) {
|
||||
notFound()
|
||||
}
|
||||
|
||||
// Type assertion for the item with list relation
|
||||
const item = itemData as typeof itemData & {
|
||||
list: {
|
||||
title: string
|
||||
color: string
|
||||
ownerId: string
|
||||
}
|
||||
}
|
||||
|
||||
// Check if user can edit this list
|
||||
const canEdit = await canEditList(session.user.id, params.id)
|
||||
|
||||
return (
|
||||
<main className="container mx-auto px-4 sm:px-6 py-6 sm:py-8 max-w-4xl">
|
||||
{/* Header Actions */}
|
||||
@@ -35,21 +54,40 @@ export default async function ItemDetailPage({ params }: PageProps) {
|
||||
</Link>
|
||||
|
||||
<div className="flex items-center gap-2 w-full sm:w-auto">
|
||||
<ToggleItemButton itemId={item.id} completed={item.completed} />
|
||||
<Link
|
||||
href={`/list/${params.id}/item/${params.itemId}/edit`}
|
||||
className="flex items-center gap-2 px-4 sm:px-5 py-2.5 sm:py-3 bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white rounded-lg transition-colors tap-target text-sm sm:text-base font-medium"
|
||||
>
|
||||
<Edit size={18} className="flex-shrink-0" />
|
||||
<span>Edit</span>
|
||||
</Link>
|
||||
<DeleteItemButton itemId={item.id} listId={params.id} />
|
||||
{canEdit && (
|
||||
<>
|
||||
<ToggleItemButton itemId={item.id} completed={item.completed} />
|
||||
<Link
|
||||
href={`/list/${params.id}/item/${params.itemId}/edit`}
|
||||
className="flex items-center gap-2 px-4 sm:px-5 py-2.5 sm:py-3 bg-blue-500 hover:bg-blue-600 active:bg-blue-700 text-white rounded-lg transition-colors tap-target text-sm sm:text-base font-medium"
|
||||
>
|
||||
<Edit size={18} className="flex-shrink-0" />
|
||||
<span>Edit</span>
|
||||
</Link>
|
||||
<DeleteItemButton itemId={item.id} listId={params.id} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Item Detail */}
|
||||
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-5 sm:p-6 lg:p-8">
|
||||
<ItemDetail item={item} listTitle={item.list.title} />
|
||||
<ItemDetail
|
||||
item={{
|
||||
id: item.id,
|
||||
title: item.title,
|
||||
description: item.description,
|
||||
completed: item.completed,
|
||||
priority: item.priority,
|
||||
dueDate: item.dueDate,
|
||||
tags: item.tags,
|
||||
notes: item.notes,
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
listId: item.listId,
|
||||
}}
|
||||
listTitle={item.list.title}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user