Skip to content

STARDEV06/Voting-management

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Poll App

A simple single-page poll application. Users create a poll, get a short link, share it, and vote. Results appear immediately after voting.

Stack

  • Backend: Laravel 11 (PHP), SQLite, DDD + Clean Architecture
  • Frontend: Vue 3, Vuex, Vue Router, Axios, Vite

Project Structure

/
├── backend/    # Laravel API
└── frontend/   # Vue 3 SPA

Setup & Launch

Prerequisites

  • PHP >= 8.2
  • Composer
  • Node.js >= 18
  • npm

Backend

cd backend

# 1. Install PHP dependencies
composer install

# 2. Copy environment file (already configured for SQLite)
cp .env.example .env

# 3. Generate app key
php artisan key:generate

# 4. Run migrations (creates polls, options, votes tables)
php artisan migrate

# 5. Start the development server
php artisan serve

The API will be available at http://localhost:8000.


Frontend

cd frontend

# 1. Install dependencies
npm install

# 2. Start the dev server
npm run dev

The app will be available at http://localhost:5173.


API Endpoints

Method URL Description
POST /api/polls Create a poll
GET /api/polls/{short_code} Get poll data (+ voted status by IP)
POST /api/polls/{short_code}/vote Cast a vote

POST /api/polls

{
  "title": "Favorite color?",
  "options": ["Red", "Blue", "Green"]
}

Response 201:

{ "short_code": "aBc123" }

POST /api/polls/{short_code}/vote

{ "option_id": 2 }

Response 200:

{
  "votes": [
    { "option_id": 1, "option": "Red", "count": 3 },
    { "option_id": 2, "option": "Blue", "count": 5 }
  ]
}

Returns 409 Conflict if the IP has already voted.


Architecture Notes

Backend (DDD / Clean Architecture)

app/
├── Domain/Poll/
│   ├── Contracts/CodeGeneratorInterface.php   # Strategy interface for code generation
│   ├── Services/RandomCodeGenerator.php       # Default implementation
│   └── Factories/PollFactory.php              # Domain factory (injectable strategy)
├── Application/Poll/UseCases/
│   ├── CreatePollUseCase.php
│   ├── GetPollUseCase.php
│   └── VoteUseCase.php
├── Http/Controllers/Api/PollController.php
├── Http/Requests/
│   ├── CreatePollRequest.php
│   └── VoteRequest.php
└── Providers/PollServiceProvider.php          # Binds interface to implementation

Swapping the code generation strategy — inject a different CodeGeneratorInterface implementation via PollServiceProvider:

// e.g. bind a custom NanoIdGenerator instead
$this->app->bind(CodeGeneratorInterface::class, NanoIdGenerator::class);

Frontend (Vue 3)

src/
├── api/index.js          # Axios instance
├── store/index.js        # Vuex store (poll, results, hasVoted)
├── router/index.js       # /create and /poll/:code routes
├── views/
│   ├── CreatePoll.vue    # Poll creation form
│   └── PollPage.vue      # Voting / results page
└── components/
    ├── VoteForm.vue      # Radio options + submit
    └── PollResults.vue   # Results with bar chart

Duplicate Vote Protection

Votes are deduplicated by (poll_id, ip_address) unique constraint in the database. A repeat vote returns 409 Conflict. On page load, the backend checks the IP and returns results immediately if already voted.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors