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
58 changes: 58 additions & 0 deletions app/teams/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
'use client'
import { TeamActivity } from '@/components/teams/TeamActivity'
import { TeamMembers } from '@/components/teams/TeamMember'
import { TeamDashboardHeader } from '@/components/teams/TeamDashboardHeader'
import TeamTask from '@/components/teams/TeamTask'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { useState } from 'react'
import { TeamTab } from '@/components/teams/TeamDashboardHeader'
const tabs = [
{
name: 'Tasks',
value: 'tasks',
content: <TeamTask />,
},
{
name: 'Activities',
value: 'activities',
content: <TeamActivity />,
},
{
name: 'Members',
value: 'members',
content: <TeamMembers />,
},
]
export default function TeamPage() {
const [activeTab, setActiveTab] = useState(tabs[0].value)

return (
<div className="flex pr-12">
<Tabs
defaultValue={tabs[0].value}
value={activeTab}
onValueChange={setActiveTab}
className="w-full px-12"
>
<TabsList className="bg-background w-full justify-start">
{tabs.map((tab) => (
<TabsTrigger
key={tab.value}
value={tab.value}
className="bg-background data-[state=active]:border-primary mr-6 h-full rounded-none border-b-2 border-transparent px-0 data-[state=active]:shadow-none"
>
<p className="text-left text-lg">{tab.name}</p>
</TabsTrigger>
))}
</TabsList>
<TeamDashboardHeader activeTab={activeTab as TeamTab} />

{tabs.map((tab) => (
<TabsContent key={tab.value} value={tab.value} className="mt-4">
{tab.content}
</TabsContent>
))}
</Tabs>
</div>
)
}
31 changes: 31 additions & 0 deletions components/UnderConstruction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react'

export function UnderConstruction() {
return (
<div className="flex min-h-screen flex-col px-4 py-12">
<div className="mb-8 flex flex-col items-center">
<svg
width="80"
height="80"
fill="none"
viewBox="0 0 80 80"
className="mb-4"
aria-hidden="true"
>
<rect width="80" height="80" rx="16" fill="#E5E7EB" />
<path
d="M20 60L60 20M20 20l40 40"
stroke="#9CA3AF"
strokeWidth="4"
strokeLinecap="round"
/>
</svg>
<h1 className="mb-2 text-2xl font-bold text-gray-800">Page Under Construction</h1>
<p className="max-w-md text-center text-gray-500">
This page is coming soon. We&apos;re working hard to bring you new features. Please check
back in the near future!
</p>
</div>
</div>
)
}
37 changes: 34 additions & 3 deletions components/app-sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import { Briefcase, ChartNetwork, Home, Inbox } from 'lucide-react'
import { Briefcase, ChartNetwork, Home, Users } from 'lucide-react'
import * as React from 'react'

import { NavMain } from '@/components/nav-main'

import { Sidebar, SidebarHeader, SidebarRail } from '@/components/ui/sidebar'

// This is sample data.
//TODO: Replace with real team data from API when backend integration is complete. Currently used for development and testing of team navigation.

const dummyTeamData = [
{
id: 2,
name: 'Design Team',
},
{
id: 3,
name: 'Development Team',
},
{
id: 4,
name: 'Marketing Team',
},
]

const data = {
navMain: [
{
Expand All @@ -22,7 +38,22 @@ const data = {
{
title: 'Teams',
url: '/teams',
icon: Inbox,
icon: Users,
isActive: true,
items: [
...dummyTeamData.map((team) => ({
title: team.name,
url: `/teams/${team.id}`,
})),
{
title: 'Create Team +',
url: '/teams/create',
},
{
title: 'Join Team +',
url: '/teams/join',
},
],
},
],
}
Expand Down
76 changes: 61 additions & 15 deletions components/nav-main.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,78 @@
'use client'
import { ChevronRight, type LucideIcon } from 'lucide-react'

import { type LucideIcon } from 'lucide-react'

import { SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar'
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
} from '@/components/ui/sidebar'
import Link from 'next/link'
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from './ui/collapsible'

export function NavMain({
items,
}: {
items: {
title: string
url: string
icon: LucideIcon
icon?: LucideIcon
isActive?: boolean
items?: {
title: string
url: string
}[]
}[]
}) {
return (
<SidebarMenu>
{items.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild isActive={item.isActive}>
<Link href={item.url}>
<item.icon />
<span>{item.title}</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
))}
{items.map((item) => {
const hasSubItems = item.items && item.items.length > 0
if (!hasSubItems) {
return (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild tooltip={item.title}>
<Link href={item.url}>
{item.icon && <item.icon />}
<span>{item.title}</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
)
}
return (
<Collapsible
key={item.title}
asChild
defaultOpen={item.isActive}
className="group/collapsible"
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton tooltip={item.title}>
{item.icon && <item.icon />}
<span>{item.title}</span>
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<Link href={subItem.url}>
<span>{subItem.title}</span>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
)
})}
</SidebarMenu>
)
}
58 changes: 58 additions & 0 deletions components/teams/TeamActivity.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react'
// import { UnderConstruction } from '../UnderConstruction'
import { CheckCircle, RefreshCw, UserPlus } from 'lucide-react'
import { TeamActivityCard } from './TeamActivityCard'

// TODO: Replace with actual data fetching hook
const teamActivities = [
{
id: 1,
icon: CheckCircle,
date: '2024-07-01',
title: 'Finished the Task',
description: 'The team successfully completed the homepage redesign task.',
user: 'Anuj',
},
{
id: 2,
icon: RefreshCw,
date: '2024-07-02',
title: 'Updated Task Status',
description: 'The status of the API integration task was updated to "In Progress".',
user: 'Shobhan',
},
{
id: 3,
icon: UserPlus,
date: '2024-07-03',
title: 'Got a Task Assigned',
description: 'You were assigned to the bug fix task for the login page.',
user: 'Mayank',
},
]

function Activity() {
return (
<div className="grid grid-cols-1 gap-4">
{teamActivities.map((activity) => (
<TeamActivityCard
key={activity.id}
icon={activity.icon}
title={activity.title}
description={activity.description}
date={activity.date}
user={activity.user}
/>
))}
</div>
)
}

export function TeamActivity() {
return (
<div>
<Activity />
{/* <UnderConstruction /> */}
</div>
)
}
37 changes: 37 additions & 0 deletions components/teams/TeamActivityCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react'
import type { LucideIcon } from 'lucide-react'

type TeamActivityCardProps = {
icon: LucideIcon
date: string
title: string
description: string
user: string
}

export function TeamActivityCard({
icon: Icon,
date,
title,
description,
user,
}: TeamActivityCardProps) {
return (
<div className="flex items-center justify-between rounded-lg border border-gray-200 bg-white px-4 py-3 shadow-sm">
<div className="flex items-center gap-3">
<span className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100">
<Icon className="h-5 w-5 text-gray-500" />
</span>
<div>
<div className="font-medium text-gray-900">
<span className="mr-1 text-lg font-semibold">{title}</span>
</div>
<div className="text-xs text-gray-500">
{user} {description}
</div>
</div>
</div>
<div className="ml-4 text-xs whitespace-nowrap text-gray-400">{date}</div>
</div>
)
}
35 changes: 35 additions & 0 deletions components/teams/TeamDashboardHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { SearchIcon, SlidersHorizontal } from 'lucide-react'
import { Input } from '../ui/input'
import { Button } from '../ui/button'

export type TeamTab = 'tasks' | 'members' | 'activities'

type TeamDashboardHeaderProps = {
activeTab: TeamTab
}
export function TeamDashboardHeader({ activeTab }: TeamDashboardHeaderProps) {
return (
<div className="flex justify-between">
<div className="mt-4 flex space-x-4">
<div className="flex h-10 items-center space-x-4 rounded-md border border-neutral-300 px-4">
<SearchIcon />
<Input
className="h-8 border-none shadow-none focus:border-none focus:shadow-none focus:ring-0 focus:outline-none focus-visible:border-none focus-visible:shadow-none focus-visible:ring-0 focus-visible:outline-none"
placeholder="Search Task"
/>
</div>
<div className="flex items-center space-x-2">
<SlidersHorizontal size={20} />
<p>Filters</p>
</div>
</div>
{activeTab === 'tasks' ? (
<Button>Settings</Button>
) : activeTab === 'members' ? (
<Button>Add Member</Button>
) : (
''
)}
</div>
)
}
Loading