diff --git a/README.md b/README.md index de8dd1f..acf6cab 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,64 @@ # Taskly -Taskly is a simple task management application built with Laravel, Inertia.js, and Vue.js. It allows users to create and manage tasks within teams. +Taskly is a modern, collaborative task management application for teams. It allows teams to create, organize, and track tasks dynamically on an interactive Kanban board. + +This project was bootstrapped from the official [Laravel Vue Starter Kit](https://github.com/laravel/vue-starter-kit). + +## Features + +- **Interactive Kanban Board:** Drag-and-drop tasks between columns, rename columns, and adjust task priority sequences. +- **Advanced Task Filters:** Filter bar for finding tasks by: + - Search keywords (debounced title & description search). + - Assignee (filtered by specific team members or unassigned tasks). + - Tags (multi-select filter). + - Due Dates (shortcuts like Today, This Week, Overdue, or custom exact dates and date ranges). +- **Task Details & Collaboration:** Task editing with rich description styling (Tiptap editor), comments with threaded replies, and a detailed activity log timeline. +- **Workload Dashboard:** Team workspace overview featuring task metrics, urgent "To Handle Now" tasks, column breakdowns, and a recent activity feed (with direct links back to tasks). + +## Tech Stack + +- **Backend:** Laravel 12 (PHP >= 8.2), Inertia.js V3 +- **Frontend:** Vue 3 +- **Styling:** Tailwind CSS & Shadcn +- **CI/CD:** GitHub Actions workflow for automated testing, linting and deployment. +- **Deployment:** Docker, with a production-ready Dockerfile included in the repository. ## Installation -### Pre-requirements - -- PHP >= 8.5 -- Composer -- Node.js >= 24 -- NPM >= 11.6.2 - -### Installation steps - -1. Clone the project repository -2. Install dependencies and initialize the environment: - ``` - composer run setup - ``` - This script : - - installs the PHP and JavaScript dependencies - - configures the .env file - - generates the Laravel application key -3. Start the development server : - ``` - composer run dev - ``` - You can access the application at : http://localhost:8000. - -## Project Presentation - -The application is a **team-based task manager**.\ -It contains **3 teams and 6 users**. Each user belongs to a team.\ -Test accounts are available : -| User | EEmail | Password | -| ----------- | ------------------- | ------------ | -| User 1 | test1@example.com | password | -| User 2 | test2@example.com | password | -| ... | test{N}@example.com | password | -| User 6 | test6@example.com | password | - -You can also create your own account. +### Prerequisites + +Make sure you have the following installed on your local system: +- **PHP** >= 8.2 +- **Composer** +- **Node.js** >= 20 +- **NPM** + +### Getting Started + +1. **Clone the repository** to your local environment. +2. **Install dependencies and seed the database:** + ```bash + composer run setup + ``` + *This command installs Composer and JavaScript dependencies, initializes your `.env` configuration, generates the app key, and runs migrations with database seeds.* + +3. **Start the development server:** + ```bash + composer run dev + ``` + *This starts the Artisan server and the Vite dev server concurrently.* + +4. Open [http://localhost:8000](http://localhost:8000) in your browser. + +## Seeded Test Accounts + +The seeded database contains **3 teams** and **6 users**. Each user is pre-assigned to a team: + +| Team | User | Email | Password | +| :--- | :--- | :--- | :--- | +| **Team 1** | User 1, 2, 3 | `test1@example.com` to `test3@example.com` | `password` | +| **Team 2** | User 4, 5 | `test4@example.com` & `test5@example.com` | `password` | +| **Team 3** | User 6 | `test6@example.com` | `password` | + +*Note: You can also register a new account and create a custom team from the login page.* + diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index ed4e47e..28db218 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -16,7 +16,7 @@ import { dashboard } from '@/routes'; import { index } from '@/routes/tasks'; import { type NavItem } from '@/types'; import { Link } from '@inertiajs/vue3'; -import { BookOpen, Folder, LayoutGrid, ListCheck, Tag } from 'lucide-vue-next'; +import { Folder, LayoutGrid, ListCheck, Tag } from 'lucide-vue-next'; import AppLogo from './AppLogo.vue'; const mainNavItems: NavItem[] = [ @@ -40,14 +40,9 @@ const mainNavItems: NavItem[] = [ const footerNavItems: NavItem[] = [ { title: 'Github Repo', - href: 'https://github.com/laravel/vue-starter-kit', + href: 'https://github.com/mateocarciu/Taskly', icon: Folder, - }, - { - title: 'Documentation', - href: 'https://laravel.com/docs/starter-kits#vue', - icon: BookOpen, - }, + } ]; diff --git a/resources/js/components/dashboard/DashboardAttentionCard.vue b/resources/js/components/dashboard/DashboardAttentionCard.vue index 5331558..d13d08d 100644 --- a/resources/js/components/dashboard/DashboardAttentionCard.vue +++ b/resources/js/components/dashboard/DashboardAttentionCard.vue @@ -49,6 +49,9 @@ onBeforeUnmount(() => { To Handle Now +

+ Tasks that need your immediate attention. +

{ class="relative max-h-64 space-y-2 overflow-y-auto sm:max-h-80 md:max-h-96" @scroll="updateAttentionScrollHint" > -
+
{

Discussion

- - - {{ dueDateLabel }} - - + {{ dueDateLabel }} +
+ +
- - {{ daysInColumnLabel }} - + + {{ daysInColumnLabel }} +
diff --git a/resources/js/components/tasks/TaskEditFormPanel.vue b/resources/js/components/tasks/TaskEditFormPanel.vue index c08584d..92f4d4d 100644 --- a/resources/js/components/tasks/TaskEditFormPanel.vue +++ b/resources/js/components/tasks/TaskEditFormPanel.vue @@ -43,11 +43,12 @@ const onTagsUpdated = (tags: Tag[]) => { diff --git a/resources/js/components/tasks/TaskItem.vue b/resources/js/components/tasks/TaskItem.vue index 78f71a2..91f3b12 100644 --- a/resources/js/components/tasks/TaskItem.vue +++ b/resources/js/components/tasks/TaskItem.vue @@ -2,7 +2,6 @@ import TagBadge from '@/components/tags/TagBadge.vue'; import TaskDeleteDialog from '@/components/tasks/TaskDeleteDialog.vue'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; -import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent } from '@/components/ui/card'; import { useInitials } from '@/composables/useInitials'; @@ -45,7 +44,7 @@ const deleteTask = () => { @click.stop="emit('edit', task)" class="group relative cursor-pointer border-border transition-all hover:border-primary/40 hover:bg-accent/5 hover:shadow-sm" > - +

{

-
- -
- +
+
- + {{ task.days_in_column === 0 ? 'Today' : `${task.days_in_column}d` }} - +
- - + {{ new Date(task.due_date).toLocaleDateString( 'en-US', { day: 'numeric', month: 'short' }, ) }} - +