PRACTICAL 9: STATE MANAGEMENT USING PINIA

```

npm create vue@latest p9

Select:
Pinia: Yes
Vue Router: No
TypeScript: No
JSX: No
Vitest: No
ESLint: No
Prettier: No

cd p9
npm install
npm run dev

```

src/stores/counterStore.js

```

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() { this.count++ },
    decrement() { this.count-- },
    reset() { this.count = 0 }
  }
})

```

src/stores/todoStore.js

```

import { defineStore } from 'pinia'

export const useTodoStore = defineStore('todo', {
  state: () => ({ todos: [], nextId: 1 }),
  getters: {
    total: (state) => state.todos.length,
    completed: (state) => state.todos.filter(t => t.done).length
  },
  actions: {
    add(text) {
      this.todos.push({ id: this.nextId++, text, done: false })
    },
    remove(id) {
      this.todos = this.todos.filter(t => t.id !== id)
    },
    toggle(id) {
      const todo = this.todos.find(t => t.id === id)
      if (todo) todo.done = !todo.done
    }
  }
})

```

src/App.vue

```

<script setup>
import { ref } from 'vue'
import { useCounterStore } from './stores/counterStore'
import { useTodoStore } from './stores/todoStore'

const counter = useCounterStore()
const todo = useTodoStore()
const task = ref('')
</script>

<template>
  <main class="container">
    <h1>Pinia State Management</h1>

    <section>
      <h2>Counter</h2>
      <h1>{{ counter.count }}</h1>
      <p>Double: {{ counter.doubleCount }}</p>
      <button @click="counter.increment()">+</button>
      <button @click="counter.decrement()">-</button>
      <button @click="counter.reset()">Reset</button>
    </section>

    <section>
      <h2>Todo List</h2>
      <input v-model="task" placeholder="Enter a task">
      <button @click="todo.add(task); task = ''">Add</button>

      <p>Total: {{ todo.total }} | Completed: {{ todo.completed }}</p>

      <div v-for="t in todo.todos" :key="t.id" class="item">
        <span @click="todo.toggle(t.id)"
              :class="{ done: t.done }">{{ t.text }}</span>
        <button @click="todo.remove(t.id)">Delete</button>
      </div>
    </section>
  </main>
</template>

```

src/main.js

```

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import './style.css'

createApp(App).use(createPinia()).mount('#app')

```

src/style.css

```

* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background: #eef2ff;
  color: #1e293b;
}
.container {
  max-width: 650px;
  margin: 35px auto;
  padding: 25px;
}
h1 { color: #4f46e5; text-align: center; }
section {
  background: white;
  padding: 22px;
  margin: 20px 0;
  border-radius: 12px;
  box-shadow: 0 4px 15px #0001;
}
input {
  padding: 11px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
}
button {
  padding: 10px 15px;
  margin: 5px;
  background: #4f46e5;
  color: white;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
}
.item {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  margin: 8px 0;
  background: #f1f5f9;
  border-radius: 6px;
}
.done { text-decoration: line-through; color: green; }

```

Terminal

```

cd p9
npm run dev

```

Getters vs Regular Properties

```

State: Stores the actual data in Pinia.
Example: count, todos.

Getters: Compute values from the state and update reactively when state changes.
Example: doubleCount = count * 2.

Actions: Perform operations and modify the state.
Example: increment(), add(), remove(), toggle().

```