
Enterprise CRM Platform for Advertising Sales
Mission-critical platform serving 15+ sales team members. Built complex dashboards, filtering systems, and PDF generation. My biggest technical challenge: delivering enterprise features under tight deadlines.
THE CONTEXT
Summit Media's advertising sales team was managing campaigns across 20+ industries using spreadsheets and a legacy platform. Creating proposals, tracking versions, and generating reports was manual and error-prone.
The stakes: Ad sales is revenue. Slow tools slow down the entire sales process.
THE CHALLENGE (And Why It Was Brutal)
This was my biggest technical challenge to date:
- β° Tight deadlines - Fast-paced, production-critical
- π― Solo frontend dev - I was responsible for implementing most of the UI/UX, translating provided mockups into a functional system
- π First-time everything - Most patterns were new to me
- π¨ Complex UI - 20+ industry filters, dynamic tables, conditional actions
- π Heavy API integration - Real-time data syncing
Translation: I had to learn while building, fast.
WHAT I BUILT
Core Features:
1. Campaign Management System
- Create, track, and manage campaigns across multiple industries
- Real-time cost estimation and proposal generation
- Version control for proposals (sales teams iterate constantly)
2. Advanced Filtering System
- 20+ industry categories with nested filters
- Search across campaigns, proposals, and cost estimation
- Instant results with performance optimization
3. Dynamic Table System with Smart Actions
This was the heart of the CRM and my proudest technical achievement:
The Challenge: Different campaign statuses require different actions. A draft proposal needs "Create Proposal," an approved proposal needs "Create CE," a completed campaign needs "Create Job Order"βand the UI had to make this intuitive.
What I Built:
- Multiple interconnected tables (Campaigns, Proposals, Cost Estimate, Job Orders)
- Status-driven action system - buttons and options that dynamically change based on campaign state
- Complex conditional logic determining what actions are available
- Real-time status updates reflected across all related tables
Example Flow:
Draft β [Edit | Create Proposal]
β
Proposal β [Create another version | Create CE | Edit | Generate PDF]
β
Cost Estimate β [Create another version | Create Job Order | Generate PDF]
β
Job Order β [Publish | Add Notes | Start Campaign | Stop Campaign]
β
Completed β [Generate Invoice | Archive | View Report]
Each status transition triggered different API calls, updated multiple tables, and recalculated related data in real-time.
Technical Complexity:
- Conditional rendering based on user permissions AND campaign status
- Optimistic UI updates (show changes immediately, sync with backend)
- Cascading updates (changing one campaign affects related proposals, job orders)
- State synchronization across multiple table views
4. PDF Generation
- One-click proposal and invoice exports
- Professional formatting with company branding
- Dynamic content based on campaign configuration
THE TECHNICAL DEEP DIVE
My Responsibilities:
β
Frontend Architecture - Component structure and routing
β
UI/UX Implementation - Pixel-perfect from Figma designs
β
API Integration - RESTful endpoints, state synchronization
β
Business Logic - Calculations, validations, conditional flows
β
State Management - Pinia for complex, multi-view data
Hardest Technical Problems:
Problem 1: Status-Dependent Action System
The most complex part was managing actions that depend on:
- Campaign status (Draft, In Progress, For Proposal, Proposal Sent, etc)
- Related data state (Does this campaign have a proposal? cost estimate?)
I built a computed action system that evaluates all conditions and renders only valid actions:
// Simplified example of the pattern I used
const availableActions = computed(() => {
const actions = [];
if (campaign.status === "draft" && hasPermission("edit")) {
actions.push({ label: "Edit", handler: editCampaign });
}
if (campaign.status === "approved" && !campaign.hasJobOrder) {
actions.push({ label: "Create Job Order", handler: createJobOrder });
}
// ... many more conditions
return actions;
});
This kept the UI clean while handling incredibly complex business logic.
Problem 2: Real-Time Data Synchronization
Multiple users editing campaigns simultaneously required:
- Optimistic updates (show changes immediately)
- Conflict resolution when data changes server-side
- Automatic table refreshes without losing user context (filters, sort, pagination)
Solution: Built a smart polling system that checks for updates without disrupting user workflow.
Problem 3: Performance with Large Datasets
Rendering 100+ campaigns with filters, search, and dynamic actions without lag required:
- Virtual scrolling for large tables
- Debounced search inputs (wait 300ms after typing stops)
- Optimized computed properties (cache results, only recalculate when dependencies change)
- Lazy loading related data (load job orders only when row is expanded)
Problem 4: Complex Form Validation
Campaign creation had interdependent fields:
- Industry selection β determines available ad types
- Location selection β determines pricing structure
- Pricing changes β recalculates total cost in real-time
All while maintaining a smooth UX and clear error messages.
THE IMPACT
For the Sales Team:
- β Faster proposal creation (estimated 60% time savings)
- β Better version tracking (no more "Final_v3_REAL_Final.xlsx")
- β Clear action visibility - always know what you can do next
- β Professional PDF exports for clients
- β Real-time pipeline visibility across all campaigns
For Me:
This project leveled me up as a developer:
- Learned to work under pressure without sacrificing quality
- Gained confidence in complex state management (Pinia for multi-view data)
- Mastered conditional logic at scale (status-driven UIs are everywhere now)
- Understood how frontend decisions impact business (slow CRM = lost revenue)
- Discovered I thrive in fast-paced environments (tight deadlines became my fuel)
TECH STACK
- Frontend: Vue 3 (Composition API), Nuxt 3
- State Management: Pinia
- UI: Tailwind CSS
- Tables: Custom-built with virtual scrolling
- PDF: API-generated PDFs with in-app modal viewer
- API: RESTful integration with Node.js backend
WHAT THIS TAUGHT ME
1. You Don't Need to Know Everything to Start
Most patterns were new to me:
- Complex state management across multiple views
- Conditional action systems
- Virtual scrolling for performance
- Real-time data synchronization
I used AI tools (Claude, ChatGPT) to accelerate learning, but I made sure to understand every solution, not just copy-paste. I'd ask "Why does this pattern work?" not just "Give me the code."
2. Clean Code Under Pressure is Possible
Even with tight deadlines, I prioritized:
- Meaningful component names (
CampaignActionButtonnotButton2) - Clear state structure (organized Pinia stores by feature)
- Comments on complex logic (especially the status-action mapping)
Why? Other devs need to maintain this. Rushing today creates problems tomorrow. Plus, clean code is faster to debug when (not if) bugs appear.
3. Frontend Impacts Revenue
A slow, buggy CRM doesn't just annoy usersβit costs money:
- Slow filters = sales team wastes time
- Broken action buttons = proposals don't get sent
- Confusing UI = mistakes in pricing
This shifted how I think about performance and UX as business priorities, not just nice-to-haves.
4. Complex UIs Need Simple Patterns
The status-action system could have been a nightmare of nested if statements. Instead, I built a declarative pattern that made adding new statuses or actions predictable and safe.
Key principle: Make the complex logic look simple in the code.
THE BIGGER PICTURE
This CRM manages 100+ campaigns for 15+ sales team members across 20+ industries.
But more than that, it taught me:
- How to deliver under pressure
- How to learn while building
- How frontend choices impact real business outcomes
- That I love complex, high-stakes projects
This is the project that made me want to learn backendβbecause I kept thinking, "How does the API handle this? Could I build a better sync system?"
Now I'm learning Node.js, Express, and database design to answer those questions.