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:
2025-12-02 01:14:21 +00:00
parent 85c8a1650b
commit 54612a4782
7 changed files with 215 additions and 40 deletions

View File

@@ -2,7 +2,7 @@
import { memo, useState } from 'react'
import Link from 'next/link'
import { Edit2 } from 'lucide-react'
import { Edit2, Users } from 'lucide-react'
import Modal from './Modal'
import ListForm from './ListForm'
import DeleteListButton from './DeleteListButton'
@@ -15,6 +15,11 @@ interface List {
id: string
completed: boolean
}>
collaborators?: Array<{
id: string
userId: string
permission: string
}>
}
function ListCard({ list }: { list: List }) {
@@ -22,6 +27,7 @@ function ListCard({ list }: { list: List }) {
const completedCount = list.items.filter(item => item.completed).length
const totalCount = list.items.length
const progress = totalCount > 0 ? (completedCount / totalCount) * 100 : 0
const hasCollaborators = list.collaborators && list.collaborators.length > 0
const handleEditClick = (e: React.MouseEvent) => {
e.preventDefault()
@@ -45,6 +51,12 @@ function ListCard({ list }: { list: List }) {
style={{ backgroundColor: list.color }}
/>
<h3 className="font-semibold text-gray-900 truncate text-base sm:text-lg">{list.title}</h3>
{hasCollaborators && list.collaborators && (
<div className="flex items-center gap-1 text-gray-500 flex-shrink-0" title={`Shared with ${list.collaborators.length} ${list.collaborators.length === 1 ? 'person' : 'people'}`}>
<Users size={16} />
<span className="text-xs">{list.collaborators.length}</span>
</div>
)}
</div>
<div className="flex items-center gap-0.5 sm:gap-1 opacity-100 sm:opacity-0 sm:group-hover:opacity-100 transition-opacity flex-shrink-0" onClick={handleDeleteClick}>
<button