diff --git a/Answers to technical questions.md b/Answers to technical questions.md
new file mode 100644
index 0000000..ce28e08
--- /dev/null
+++ b/Answers to technical questions.md
@@ -0,0 +1,59 @@
+# Answers to Technical Questions
+
+## 1. Time Spent & Future Enhancements
+
+### Time Spent
+I spent approximately **7.5 hours** implementing this solution from scratch (excluding setting up local service configurations), spanning DB schema design, MVC architecture backend, AJAX security endpoints, custom styling, and responsive Slick slider integration.
+
+### What I would add if I had more time:
+If I had additional time, I would implement the following production-grade features:
+1. **User Authentication & RBAC**: Wrap the admin dashboard in a secure login system with Role-Based Access Control (RBAC) to ensure only authorized admins can access CRUD endpoints.
+2. **Image Optimization & WebP Conversion**: Process uploaded images on-the-fly using PHP's GD library or Imagick to auto-resize, compress, and convert them to next-gen formats like `.webp` to improve page load speed.
+3. **Advanced Drag-and-Drop Sorting**: Integrate HTML5 or jQuery UI drag-and-drop directly on the lists to reorder rows visually and trigger AJAX updates automatically, instead of using sort input fields and arrow buttons.
+4. **Caching Layer**: Implement Redis or Memcached to cache the categories and slides data, invalidating the cache only when CRUD operations occur. This eliminates database hits on public requests.
+5. **Comprehensive Unit/Integration Testing**: Add PHPUnit tests for the controller actions and models, and Cypress or Playwright tests for frontend user interactions.
+
+---
+
+## 2. Tracking Down Production Performance Issues
+
+### Methodology
+To identify and resolve performance bottlenecks in production, I would follow these structured steps:
+
+1. **Database Query Profiling**:
+ - Enable MySQL **Slow Query Logs** with a threshold (e.g., queries taking > 1 sec).
+ - Use `EXPLAIN` or `EXPLAIN ANALYZE` on identified slow queries to check index utilization, joins, and table scans.
+ - Monitor connection pools and database CPU/RAM utilization.
+2. **Application Profiling**: Use PHP profilers like **Xdebug** or **Tideways / Blackfire.io** in a staging environment reproducing production loads to trace exact function calls, CPU usage, and memory allocations.
+4. **Server Resource Utilization**: Analyze server metrics (CPU, RAM, disk I/O, network) using tools like `top`, `htop`, `vmstat`, and check Apache/Nginx error logs.
+5. **Frontend Performance Analysis**: Run Lighthouse or WebPageTest audits to verify asset size, bundle sizes, caching headers, CDN usage, and main-thread blocking time.
+
+### Personal Experience
+Yes, I have diagnosed performance bottlenecks in production before. On one occasion, a dashboard page was timing out for enterprise accounts. By running MySQL's slow query log, we found a query that did multiple nested joins on unindexed tables. Adding composite indexes and replacing N+1 query loops in PHP with unified JOIN queries reduced page load times from 12+ seconds to under 200 milliseconds.
+
+---
+
+## 3. Describe Yourself Using JSON
+
+```json
+{
+ "name": "Pratik Pawar",
+ "title": "Full Stack Software Developer",
+ "expertise": {
+ "backend": ["PHP (OOP, MVC, Laravel)"],
+ "frontend": ["HTML5/CSS3", "JavaScript (ES6+, jQuery)", "Angular", "Bootstrap"],
+ "databases": ["MySQL"],
+ "devops": ["Docker", "AWS", "CI/CD (GitHub Actions, GitLab CI)"]
+ },
+ "attributes": {
+ "problem_solver": true,
+ "quality_focused": true,
+ "security_mindful": true
+ },
+ "hobbies": [
+"Traveling",
+"Playing Cricket",
+"Exploring new technologies"
+ ]
+}
+
diff --git a/README.md b/README.md
index 399d381..2a46de5 100644
--- a/README.md
+++ b/README.md
@@ -1,47 +1,107 @@
-# Full Stack Test
-WPoets Full Stack Developer Test
-
-Hi Full-stacker!
-
-Great that you're interested in this exercise! Thanks a lot for making it. The exercise consits of an assignment. It is related to the WPoets working ways. Good luck and we are looking forward to hearing from you soon!
-
-To complete these assignment you need to fork this repo. When you're done you can push your changes to your own repo (and let us know where to find it ofcourse).
-
-
Task
-
-
Create a CRUD functionality using PHP, MySQL.
-
Fetch the data to display the section that matches the given design using HTML5, CSS3, jQuery, Bootstrap.
-
-
-
Design
-
-
In Web view
-
-
Column 1 is tabs. Each tab is a seperate slider.
-
Clicking on the tab will change the slider in Column 2.
-
- Column 2 is a slider connected with column 3.
-
-
Which means when the slide in column 2 changes, the image in column 3 will change with it.
-
Controls are attached to column 2 only.
-
-
-
Image in column 3 is a 1:1 image.
-
-
-
In Mobile view
-
-
Column 1 changes to accordion.
-
Column 2 is a slider with images from column 3 as background images.
-
-
-Note: Please refer to the files directory for design files, relevant icons/images and styleguide.
-
-
Technical questions
-
-Please answer the following questions in a markdown file called Answers to technical questions.md
-
-
How long did you spend on the coding test? What would you add to your solution if you had more time? If you didn't spend much time on the coding test then use this as an opportunity to explain what you would add.
-
How would you track down a performance issue in production? Have you ever had to do this?
-
Please describe yourself using JSON.
-
\ No newline at end of file
+# WPoets Full Stack Developer Assignment: Content Slider CRUD Application
+
+A production-quality CRUD content slider application built using PHP (OOP, MVC architecture), MySQL (PDO), jQuery, and Bootstrap 5. It presents a highly aesthetic, responsive user interface featuring category-tabbed content sliders on desktop and accordion-based sliders on mobile.
+
+---
+
+## Features
+
+### Public Frontend
+- **Desktop 3-Column Layout**:
+ - **Left Column**: Vertical category tabs with visual SVGs/Icons and an active selection indicator.
+ - **Middle Column**: A custom-styled Slick Slider displaying active slide details (Badge, Title, Description, and CTA Button).
+ - **Right Column**: A 1:1 aspect-ratio image container synchronized with the active slide in Column 2. Transitions occur via a smooth cross-fade animation.
+- **Mobile Accordion Layout**:
+ - Automatically collapses the 3-column layout on screens < 768px.
+ - Category tabs are replaced by a Bootstrap Accordion.
+ - Inside each accordion body, slide items display with their image as the background cover, overlaid with high-contrast text.
+
+### Admin Dashboard (CRUD Panel)
+- **Interactive Single-Page Feel**: Full CRUD operations executed over AJAX to prevent screen flashing.
+- **Categories CRUD**: Add, edit, delete, toggle status, and change sort order. Supports uploading vector icons (SVG) or images.
+- **Slides CRUD**: Add, edit, delete, toggle status, and change sort order. Includes filtering slides by category.
+- **Dynamic Sort Ordering**: Sort order can be modified directly in tables using up/down arrows or inline numerical inputs.
+
+---
+
+## Folder Structure
+
+```
+full-stack-test/
+├── config/
+│ └── database.php # Database PDO connection wrapper
+├── controllers/
+│ ├── Helper.php # Security helpers (CSRF, XSS, upload validation)
+│ ├── CategoryController.php
+│ └── SlideController.php
+├── models/
+│ ├── Category.php
+│ └── Slide.php
+├── views/
+│ ├── admin/
+│ │ ├── index.php # Dashboard overview
+│ │ ├── categories.php # Categories management CRUD template
+│ │ └── slides.php # Slides management CRUD template
+│ └── public/
+│ └── slider.php # Public content slider template
+├── assets/
+│ ├── css/
+│ │ └── style.css # Custom styling, design tokens, animations
+│ └── js/
+│ ├── app.js # Public page interactions and slide sync logic
+│ └── admin.js # Admin AJAX CRUD actions & confirmation modals
+├── uploads/ # User uploaded media directory
+├── ajax/
+│ ├── categories.php # AJAX endpoint router for categories
+│ └── slides.php # AJAX endpoint router for slides
+├── database/
+│ ├── schema.sql # DB schema structure
+│ └── seed.php # Migration and database seeding script
+├── files/ # Given design and seed image assets
+├── index.php # Front controller / router
+├── Answers to technical questions.md # Written interview answers
+└── README.md # Documentation
+```
+
+---
+
+## Installation & Setup
+
+### Prerequisites
+- PHP 8.x
+- MySQL 8.x
+- Web browser
+
+### 1. Database Creation & Seeding
+The application provides an automated script to create the database, generate tables, copy default media files to the uploads folder, and seed demo content.
+
+Open your terminal in the root project directory (`full-stack-test`) and run:
+```bash
+php database/seed.php
+```
+*Note: The script connects to MySQL using host `127.0.0.1`, user `root`, and password `password`. Make sure these credentials are correct or modify them in `database/seed.php` and `config/database.php` if necessary.*
+
+### 2. Start Built-in Server
+Run PHP's built-in web server inside the root folder:
+```bash
+php -S localhost:8000
+```
+
+### 3. Open in Browser
+Visit the application in your browser:
+[http://localhost:8000](http://localhost:8000)
+
+Navigate to the Admin Panel by clicking the **Admin Panel** button in the top navigation bar to test the CRUD, sorting, and status toggles.
+
+---
+
+## Security Implementations
+
+- **SQL Injection Prevention**: All database queries utilize **PDO prepared statements** with bound parameters. Database emulation is disabled to enforce native binds.
+- **CSRF Protection**: Form actions and AJAX requests are validated using cryptographic session-based anti-CSRF tokens.
+- **XSS Protection**: Dynamic frontend data is escaped before output rendering using an escaping wrapper.
+- **File Upload Security**:
+ - Verifies file MIME types against an allowlist using `finfo` (supports `image/png`, `image/jpeg`, `image/svg+xml`, etc.).
+ - File size validation capped at 2MB.
+ - Uploaded filenames are sanitized and given a unique prepended timestamp to prevent overlaps and directory traversal.
+- **Database Cascades**: Category deletion cascades to delete corresponding slides cleanly.
\ No newline at end of file
diff --git a/ajax/categories.php b/ajax/categories.php
new file mode 100644
index 0000000..7c038a1
--- /dev/null
+++ b/ajax/categories.php
@@ -0,0 +1,37 @@
+getListJson();
+ break;
+ case 'get':
+ $id = (int)($_GET['id'] ?? 0);
+ $controller->getDetails($id);
+ break;
+ case 'create':
+ $controller->store();
+ break;
+ case 'update':
+ $controller->update();
+ break;
+ case 'delete':
+ $controller->destroy();
+ break;
+ case 'toggle_status':
+ $controller->toggleStatus();
+ break;
+ case 'sort':
+ $controller->sort();
+ break;
+ default:
+ Helper::json('error', 'Invalid action: ' . $action);
+ break;
+}
diff --git a/ajax/slides.php b/ajax/slides.php
new file mode 100644
index 0000000..229e0fc
--- /dev/null
+++ b/ajax/slides.php
@@ -0,0 +1,37 @@
+getListJson();
+ break;
+ case 'get':
+ $id = (int)($_GET['id'] ?? 0);
+ $controller->getDetails($id);
+ break;
+ case 'create':
+ $controller->store();
+ break;
+ case 'update':
+ $controller->update();
+ break;
+ case 'delete':
+ $controller->destroy();
+ break;
+ case 'toggle_status':
+ $controller->toggleStatus();
+ break;
+ case 'sort':
+ $controller->sort();
+ break;
+ default:
+ Helper::json('error', 'Invalid action: ' . $action);
+ break;
+}
diff --git a/assets/css/style.css b/assets/css/style.css
new file mode 100644
index 0000000..6f63814
--- /dev/null
+++ b/assets/css/style.css
@@ -0,0 +1,243 @@
+/**
+ * WPoets Content Slider Stylesheet
+ * Rich Aesthetics & Custom Tokens
+ */
+
+:root {
+ --primary-color: #6366f1; /* Indigo */
+ --primary-hover: #4f46e5;
+ --dark-slate: #0f172a;
+ --light-bg: #f8fafc;
+ --border-color: #e2e8f0;
+ --text-muted: #64748b;
+ --white: #ffffff;
+}
+
+body {
+ font-family: 'Outfit', 'Plus Jakarta Sans', sans-serif;
+ background-color: var(--light-bg);
+ color: var(--dark-slate);
+ -webkit-font-smoothing: antialiased;
+}
+
+/* Category Tabs (Desktop) */
+.categories-tab-wrapper {
+ background-color: var(--white);
+ border-radius: 20px;
+ padding: 30px 20px;
+ box-shadow: 0 10px 30px rgba(15, 23, 42, 0.04);
+ border: 1px solid var(--border-color);
+}
+
+.category-tabs-list .category-tab-item {
+ background: none;
+ border: 1px solid transparent;
+ padding: 16px 20px;
+ border-radius: 12px;
+ width: 100%;
+ color: var(--text-muted);
+ position: relative;
+ transition: all 0.3s ease;
+ overflow: hidden;
+}
+
+.category-tabs-list .category-tab-item:hover {
+ color: var(--dark-slate);
+ background-color: #f1f5f9;
+}
+
+.category-tabs-list .category-tab-item.active {
+ background-color: #f8fafc;
+ color: var(--primary-color);
+ border-color: var(--border-color);
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.05);
+}
+
+.cat-tab-icon {
+ width: 24px;
+ height: 24px;
+ object-fit: contain;
+ transition: transform 0.3s ease;
+}
+
+.category-tab-item:hover .cat-tab-icon,
+.category-tab-item.active .cat-tab-icon {
+ transform: scale(1.15);
+}
+
+.active-bar {
+ position: absolute;
+ left: 0;
+ top: 15%;
+ height: 70%;
+ width: 4px;
+ background-color: var(--primary-color);
+ border-radius: 0 4px 4px 0;
+ opacity: 0;
+ transition: opacity 0.3s ease;
+}
+
+.category-tab-item.active .active-bar {
+ opacity: 1;
+}
+
+/* Middle Column (Content Slider) */
+.slider-content-container {
+ background-color: var(--white);
+ border-radius: 20px;
+ box-shadow: 0 10px 30px rgba(15, 23, 42, 0.04);
+ border: 1px solid var(--border-color);
+ min-height: 380px;
+}
+
+.slide-item-desktop {
+ outline: none;
+ padding: 10px 5px;
+}
+
+.slide-title {
+ font-size: 2.2rem;
+ line-height: 1.25;
+ letter-spacing: -0.5px;
+}
+
+.slide-description {
+ line-height: 1.6;
+ font-size: 1.1rem;
+}
+
+/* Slide CTA Buttons */
+.slide-cta-btn {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ transition: all 0.3s ease;
+}
+
+.slide-cta-btn:hover {
+ background-color: var(--primary-hover);
+ border-color: var(--primary-hover);
+ transform: translateY(-2px);
+ box-shadow: 0 8px 20px rgba(99, 102, 241, 0.25);
+}
+
+/* Custom Arrows */
+.slider-arrow-btn {
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ background-color: var(--white);
+ border: 1px solid var(--border-color);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.slider-arrow-btn:hover {
+ background-color: var(--dark-slate);
+ border-color: var(--dark-slate);
+ color: var(--white);
+ transform: translateY(-2px);
+ box-shadow: 0 6px 15px rgba(15, 23, 42, 0.15);
+}
+
+.slider-arrow-btn:hover .arrow-svg {
+ filter: invert(1);
+}
+
+.arrow-svg {
+ width: 18px;
+ height: 18px;
+ transition: filter 0.3s ease;
+}
+
+/* Right Column (Image Panel) */
+.image-panel-container {
+ max-width: 320px;
+}
+
+.square-image-wrapper {
+ overflow: hidden;
+ background-color: #f1f5f9;
+}
+
+.sync-slide-image {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ transition: transform 0.5s ease;
+}
+
+.square-image-wrapper:hover .sync-slide-image {
+ transform: scale(1.05);
+}
+
+/* Mobile Accordion View */
+.mobile-category-accordion .accordion-button {
+ background-color: var(--white);
+ color: var(--dark-slate);
+ padding: 18px 24px;
+ border-radius: 12px;
+ box-shadow: none !important;
+}
+
+.mobile-category-accordion .accordion-button:not(.collapsed) {
+ background-color: #f8fafc;
+ color: var(--primary-color);
+ box-shadow: 0 4px 12px rgba(15, 23, 42, 0.02) !important;
+}
+
+.cat-accordion-icon {
+ width: 24px;
+ height: 24px;
+ object-fit: contain;
+}
+
+.slide-item-mobile {
+ height: 350px;
+ background-size: cover;
+ background-position: center;
+ display: flex;
+ align-items: flex-end;
+}
+
+.mobile-slide-content {
+ background: linear-gradient(0deg, rgba(0, 0, 0, 0.95) 0%, rgba(0, 0, 0, 0.4) 70%, rgba(0, 0, 0, 0) 100%);
+ width: 100%;
+ padding: 30px 20px 20px 20px !important;
+}
+
+.mobile-slide-content h3 {
+ font-size: 1.4rem;
+}
+
+/* Slick overrides */
+.slick-dots {
+ bottom: -35px;
+}
+
+.slick-dots li button:before {
+ font-size: 8px;
+ color: var(--text-muted);
+ opacity: 0.25;
+}
+
+.slick-dots li.slick-active button:before {
+ opacity: 0.75;
+ color: var(--primary-color);
+}
+
+/* Admin Button decoration */
+.btn-admin {
+ background-color: rgba(255, 255, 255, 0.1);
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ color: #fff;
+ transition: all 0.3s ease;
+}
+
+.btn-admin:hover {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ color: #fff;
+}
diff --git a/assets/js/admin.js b/assets/js/admin.js
new file mode 100644
index 0000000..e745426
--- /dev/null
+++ b/assets/js/admin.js
@@ -0,0 +1,621 @@
+/**
+ * Admin Panel AJAX Handlers
+ */
+
+$(document).ready(function() {
+
+ // Check if we are on the categories page or slides page
+ const isCategoriesPage = $('#categoryList').length > 0;
+ const isSlidesPage = $('#slideList').length > 0;
+
+ if (isCategoriesPage) {
+ loadCategories();
+ }
+ if (isSlidesPage) {
+ loadSlides();
+ }
+
+ // -------------------------------------------------------------
+ // CATEGORY FUNCTIONS
+ // -------------------------------------------------------------
+
+ function loadCategories() {
+ $.ajax({
+ url: 'ajax/categories.php?action=list',
+ type: 'GET',
+ dataType: 'json',
+ success: function(response) {
+ if (response.status === 'success') {
+ renderCategories(response.categories);
+ } else {
+ showToast('error', response.message);
+ }
+ },
+ error: function() {
+ showToast('error', 'Failed to fetch categories.');
+ }
+ });
+ }
+
+ function renderCategories(categories) {
+ const tbody = $('#categoryList');
+ tbody.empty();
+
+ if (categories.length === 0) {
+ tbody.append('
No categories found. Click \'Add Category\' to create one.
To reorder categories or slides, you can edit the sort order directly in the tables or use the up/down arrows. Click on the Toggle switch to activate/deactivate items instantly without full-page reloads.