├── server └── tsconfig.json ├── public └── favicon.ico ├── tsconfig.json ├── app.vue ├── .gitignore ├── nuxt.config.ts ├── assets └── css │ └── vello.css ├── package.json ├── README.md ├── pages ├── index │ └── tasks │ │ └── [id].vue └── index.vue ├── data └── board.json ├── stores └── boardStore.ts └── components └── BoardColumn.vue /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../.nuxt/tsconfig.server.json" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Code-Pop/build-trello-clone-with-nuxt-3/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /app.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Nuxt dev/build outputs 2 | .output 3 | .data 4 | .nuxt 5 | .nitro 6 | .cache 7 | dist 8 | 9 | # Node dependencies 10 | node_modules 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Misc 17 | .DS_Store 18 | .fleet 19 | .idea 20 | 21 | # Local env files 22 | .env 23 | .env.* 24 | !.env.example 25 | -------------------------------------------------------------------------------- /nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | ssr: false, 4 | css: ['~/assets/css/vello.css'], 5 | devtools: { enabled: true }, 6 | modules: ['@nuxt/ui', '@pinia/nuxt', '@vueuse/nuxt'], 7 | colorMode: { 8 | preference: 'light' 9 | } 10 | }) 11 | -------------------------------------------------------------------------------- /assets/css/vello.css: -------------------------------------------------------------------------------- 1 | .board { 2 | @apply flex flex-row items-start; 3 | } 4 | 5 | .board-wrapper { 6 | @apply p-4 h-full overflow-auto; 7 | } 8 | 9 | .column { 10 | @apply flex-1 p-4 mr-4 rounded bg-gray-200; 11 | min-width: 350px; 12 | } 13 | 14 | .column-header { 15 | @apply flex items-center justify-between mb-3 font-bold; 16 | } 17 | 18 | .task-bg { 19 | @apply absolute inset-0; 20 | background: rgba(0, 0, 0, 0.75); 21 | } 22 | 23 | .task-view { 24 | @apply flex flex-col flex-grow items-start justify-between px-4; 25 | } 26 | 27 | .task-wrapper { 28 | @apply max-w-2xl bg-gray-200 m-32 mx-auto py-4 rounded; 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nuxt-app", 3 | "private": true, 4 | "type": "module", 5 | "scripts": { 6 | "build": "nuxt build", 7 | "dev": "nuxt dev", 8 | "generate": "nuxt generate", 9 | "preview": "nuxt preview", 10 | "postinstall": "nuxt prepare" 11 | }, 12 | "devDependencies": { 13 | "@nuxt/devtools": "latest", 14 | "nuxt": "^3.8.2", 15 | "vue": "^3.3.10", 16 | "vue-router": "^4.2.5" 17 | }, 18 | "dependencies": { 19 | "@nuxt/ui": "^2.11.0", 20 | "@pinia/nuxt": "^0.5.1", 21 | "@vueuse/core": "^10.7.0", 22 | "@vueuse/nuxt": "^10.7.0", 23 | "pinia": "^2.1.7", 24 | "uuid": "^9.0.1" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nuxt 3 Minimal Starter 2 | 3 | Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more. 4 | 5 | ## Setup 6 | 7 | Make sure to install the dependencies: 8 | 9 | ```bash 10 | # npm 11 | npm install 12 | 13 | # pnpm 14 | pnpm install 15 | 16 | # yarn 17 | yarn install 18 | 19 | # bun 20 | bun install 21 | ``` 22 | 23 | ## Development Server 24 | 25 | Start the development server on `http://localhost:3000`: 26 | 27 | ```bash 28 | # npm 29 | npm run dev 30 | 31 | # pnpm 32 | pnpm run dev 33 | 34 | # yarn 35 | yarn dev 36 | 37 | # bun 38 | bun run dev 39 | ``` 40 | 41 | ## Production 42 | 43 | Build the application for production: 44 | 45 | ```bash 46 | # npm 47 | npm run build 48 | 49 | # pnpm 50 | pnpm run build 51 | 52 | # yarn 53 | yarn build 54 | 55 | # bun 56 | bun run build 57 | ``` 58 | 59 | Locally preview production build: 60 | 61 | ```bash 62 | # npm 63 | npm run preview 64 | 65 | # pnpm 66 | pnpm run preview 67 | 68 | # yarn 69 | yarn preview 70 | 71 | # bun 72 | bun run preview 73 | ``` 74 | 75 | Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. 76 | -------------------------------------------------------------------------------- /pages/index/tasks/[id].vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 43 | -------------------------------------------------------------------------------- /data/board.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "task-board", 3 | "columns": [ 4 | { 5 | "id": "74c49bb3-f5c4-478d-b87a-ca401c5cbe51", 6 | "name": "todo", 7 | "tasks": [ 8 | { 9 | "id": "0335e09e-c472-4d25-a2a4-2673510c379b", 10 | "name": "task #1", 11 | "description": "" 12 | }, 13 | { 14 | "id": "8a928845-26d0-4462-8ae6-bb7a4b7dc294", 15 | "name": "task #2", 16 | "description": "" 17 | } 18 | ] 19 | }, 20 | { 21 | "id": "46aa0edc-f299-4350-8828-c0017a06a4d5", 22 | "name": "in-progress", 23 | "tasks": [ 24 | { 25 | "id": "69a1120e-f5e5-437d-9319-f410610a49c8", 26 | "name": "task #3", 27 | "description": "" 28 | } 29 | ] 30 | }, 31 | { 32 | "id": "f1953dbe-b295-48bf-af0c-312d1eaa1c04", 33 | "name": "complete", 34 | "tasks": [ 35 | { 36 | "id": "6e7ed610-e788-4640-a55c-c96088f4d0d6", 37 | "name": "task #4", 38 | "description": "" 39 | }, 40 | { 41 | "id": "e3ea69ba-9a4f-4164-af74-78b3cfcf8630", 42 | "name": "task #5", 43 | "description": "" 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 48 | -------------------------------------------------------------------------------- /stores/boardStore.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from 'uuid' 2 | import { defineStore } from 'pinia' 3 | import { useStorage } from '@vueuse/core' 4 | import boardData from '~/data/board.json' 5 | 6 | export const useBoardStore = defineStore('boardStore', () => { 7 | const board = useStorage('board', boardData) 8 | 9 | /** 10 | * Tasks 11 | */ 12 | const getTask = computed(() => { 13 | return taskId => { 14 | for (const column of board.value.columns) { 15 | const task = column.tasks.find(task => task.id === taskId) 16 | if (task) return task 17 | } 18 | } 19 | }) 20 | 21 | function addTask({ columnIndex, taskName }) { 22 | board.value.columns[columnIndex].tasks.push({ 23 | id: uuid(), 24 | name: taskName, 25 | description: '' 26 | }) 27 | } 28 | 29 | function deleteTask(taskId) { 30 | for (const column of board.value.columns) { 31 | const taskIndex = column.tasks.findIndex(task => task.id === taskId) 32 | 33 | if (taskIndex !== -1) { 34 | column.tasks.splice(taskIndex, 1) 35 | return 36 | } 37 | } 38 | } 39 | 40 | function moveTask({ 41 | fromTaskIndex, 42 | toTaskIndex, 43 | fromColumnIndex, 44 | toColumnIndex 45 | }) { 46 | const task = board.value.columns[fromColumnIndex].tasks.splice( 47 | fromTaskIndex, 48 | 1 49 | )[0] 50 | 51 | board.value.columns[toColumnIndex].tasks.splice(toTaskIndex, 0, task) 52 | } 53 | 54 | /** 55 | * Columns 56 | */ 57 | function addColumn(columnName) { 58 | board.value.columns.push({ 59 | name: columnName, 60 | tasks: [] 61 | }) 62 | } 63 | 64 | function deleteColumn(columnIndex) { 65 | board.value.columns.splice(columnIndex, 1) 66 | } 67 | 68 | function moveColumn({ fromColumnIndex, toColumnIndex }) { 69 | const column = board.value.columns.splice(fromColumnIndex, 1)[0] 70 | board.value.columns.splice(toColumnIndex, 0, column) 71 | } 72 | 73 | return { 74 | /* State */ 75 | board, 76 | /* Getters */ 77 | getTask, 78 | /* Actions*/ 79 | addColumn, 80 | addTask, 81 | deleteColumn, 82 | deleteTask, 83 | moveColumn, 84 | moveTask 85 | } 86 | }) 87 | -------------------------------------------------------------------------------- /components/BoardColumn.vue: -------------------------------------------------------------------------------- 1 | 73 | 74 | 134 | --------------------------------------------------------------------------------