Compare commits

..

39 Commits

Author SHA1 Message Date
Claude
6641dddfe6 🔧 Fix Django template syntax error in base.html
- Remove nested {% block title %} tags causing TemplateSyntaxError
- Fix Open Graph and Twitter meta tag blocks
- Use absolute URLs for social media image previews
- Resolves Internal Server Error on Railway deployment

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 17:18:02 +05:30
Claude
bf8cc1817e Add rich link previews + event page integration
- Add comprehensive Open Graph meta tags for rich social sharing
- Generate social media assets (og-image.png, favicons)
- Implement Twitter Card support for enhanced Twitter sharing
- Add SEO meta tags for improved search engine visibility
- Create event page with JotForm integration (/event/)
- Add customizable meta blocks for individual page optimization

🔗 Links now show rich previews with title, description, and branded image
📱 Professional favicons across all devices and platforms

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-15 17:09:29 +05:30
Claude
2ffd0aae50 📋 Add Agent Request Template for streamlined agent creation
- Create docs/AGENT_REQUEST_TEMPLATE.md with simple form for agent requests
- Include examples for both webhook and direct access agents
- List all available categories and form field types
- Add cross-references from CLAUDE.md and AGENT_CREATION.md
- Streamline future agent creation with standardized input format
- Reduce back-and-forth and prevent missing information

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 09:08:41 +05:30
Claude
d84086f6a8 📚 Restructure documentation with dedicated agent creation guide
- Create docs/AGENT_CREATION.md with comprehensive agent creation guide
- Reduce CLAUDE.md from 480 to 273 lines (43% reduction)
- Update all agent counts to current status (8 agents, 6 categories)
- Fix outdated information and remove duplicate content
- Add clear navigation between documentation files
- Separate concerns: CLAUDE.md for Django/project, AGENT_CREATION.md for agents
- Better maintainability and discoverability of information

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 09:04:15 +05:30
Claude
7a0d906bcc 🎨 Fix marketplace button consistency and update documentation
- Remove icon from SWOT Analysis Expert Try Now button for consistency
- All marketplace buttons now use standard "Try Now →" format
- Add documentation warnings about marketplace button consistency
- Prevent future icon inconsistencies in agent creation process

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 08:57:06 +05:30
Claude
cf33065315 Add SWOT Analysis Expert + streamline agent creation process
- Add SWOT Analysis Expert direct access agent (free, JotForm integration)
- Use existing 'analysis' category instead of creating new category
- Remove 10+ redundant create_* management commands for cleaner codebase
- Update CLAUDE.md with simplified JSON + populate_agents workflow
- Emphasize using existing categories to avoid proliferation
- Clean up agent creation architecture for Railway scalability
- All agents now follow unified JSON config approach

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-07 08:49:53 +05:30
Claude
2aea35f2d9 Add Lean Six Sigma Expert agent with Railway integration
- Add Business Consulting category to Railway config
- Create System 2 direct access agent with JotForm integration
- Add dedicated template with full-screen iframe layout
- Implement view functions for payment processing and form display
- Update marketplace template with special Try Now routing
- Add URL routes for agent access and display pages
- Create JSON config for Railway deployment compatibility
- Ensure identical database state between local and production

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-06 08:56:56 +05:30
Claude
62f3dd2592 🎨 Remove agent count display from marketplace stats
- Clean up marketplace stats section by removing agent count
- Now only shows search results and category filters when relevant
- Provides cleaner, less cluttered user interface

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-05 09:58:07 +05:30
Claude
54d64f5927 Streamline user experience with cleaner UI and improved authentication flow
- Remove special styling for career navigator button, unify all Try Now buttons
- Clean up authentication messaging system to prevent message confusion
- Replace immediate success messages with direct redirections for smoother UX
- Add session-based post-login messaging for better redirect handling
- Improve login page with verification resend button and cleaner message display
- Remove redundant payment success messages for free agents

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-05 09:22:13 +05:30
Claude
bc662e6af0 🎯 Implement dynamic agent configuration system for ultimate scalability
BREAKTHROUGH: Configuration-driven agent management that scales to 100+ agents

## New System Architecture:
- **JSON Configuration Files**: All agents defined in version-controlled JSON
- **Dynamic Loading**: populate_agents.py reads from config files automatically
- **Zero Code Changes**: Add new agents by creating JSON files only
- **Automatic Railway Sync**: Single command ensures database consistency

## File Structure:
- agents/configs/categories/categories.json - All categories
- agents/configs/agents/*.json - Individual agent configurations
- agents/configs/README.md - Complete documentation

## Key Benefits:
 **Ultimate Scalability**: Add 1000+ agents without touching code
 **Version Control**: All agent definitions tracked in git
 **Railway Consistency**: Single command syncs local and production
 **Developer Experience**: JSON files are easier than Python commands
 **Validation**: Built-in error handling and field validation
 **Documentation**: Self-documenting with clear examples

## Migration Path:
- Extracted all 6 existing agents to JSON configurations
- Updated populate_agents.py to load dynamically from configs
- Maintained backward compatibility
- Added comprehensive documentation

## Usage:
```bash
# Add new agent: Create JSON file in agents/configs/agents/
# Deploy to Railway: python manage.py populate_agents
# Result: Agent automatically appears in marketplace
```

This solves the original issue: "if we create another will it show on railway also???"
Answer: YES - just create JSON file and run populate_agents\!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-05 08:38:59 +05:30
Claude
be0eecbafd 🚀 Add unified populate_agents command for scalable agent management
- Create comprehensive populate_agents.py that handles ALL agents and categories
- Includes all 6 agents: 4 webhook + 2 direct access with complete configurations
- Eliminates need for individual agent creation commands
- Ensures database consistency between local and Railway environments
- Features detailed progress reporting and verification
- Scales to 100+ agents without additional commands
- Replaces individual management commands with unified approach

Benefits:
- Single command creates entire agent ecosystem
- Idempotent - safe to run multiple times
- Comprehensive form schemas for webhook agents
- Proper direct access configuration for JotForm agents
- Solves Railway marketplace missing agent issues

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 23:52:11 +05:30
Claude
9131e33eeb 🤖 Add AI Brand Strategist agent creation management command
- Create create_ai_brand_strategist_agent.py to enable Railway deployment
- Includes proper Marketing & Advertising category creation
- Configures direct access with JotForm integration
- Sets correct access_url_name and display_url_name for embedded interface
- Tested locally and creates agent with proper configuration
- Fixes missing agent in Railway marketplace

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 23:44:17 +05:30
Claude
01eb67cde1 📚 Update documentation with comprehensive agent creation guidelines
- Add AI Brand Strategist to current agents list with embedded interface details
- Completely rewrite "Adding New Agents" section with clear system distinctions
- Document two distinct agent systems: Webhook vs Direct Access
- Add step-by-step implementation guides for both agent types
- Include complete code examples for templates, views, and URL routing
- Add key differences comparison table for quick reference
- Include common mistakes section to prevent development issues
- Update system status to reflect current 6-agent state
- Update URL structure documentation with new routes
- Prevent future architecture confusion with clear patterns

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 23:40:20 +05:30
Claude
d8b8420319 🧠 Add AI Brand Strategist embedded interface with Quantum Tasks header
- Create dedicated template with header + JotForm iframe
- Add ai_brand_strategist_view() and ai_brand_strategist_access() functions
- Add dedicated URL routes /ai-brand-strategist/ and /ai-brand-strategist/access/
- Update marketplace buttons to use dedicated routes for consistent UX
- Both CyberSec Career Navigator and AI Brand Strategist now show embedded forms
- Follows established direct access agent architecture pattern

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 23:36:35 +05:30
Claude
6fae2686c5 🚀 Implement scalable direct access architecture for 100+ agents
## Complete Scalable Architecture Implementation

**Problem Solved**: CyberSec Career Navigator was broken (empty form → JotForm URL webhook)
**Solution**: Built generic direct access architecture for unlimited external form agents

## New Architecture Features

**🎯 Direct Access Agents (External Forms):**
- Generic view functions work for ANY direct access agent
- Database-driven routing via access_url_name/display_url_name fields
- Template automatically detects and redirects to external forms
- Zero code changes needed for new direct access agents

**🔧 Webhook Agents (Dynamic Processing):**
- Existing webhook agents work exactly as before (unchanged)
- Dynamic form generation and N8N processing preserved
- Zero impact on current functionality

## Files Added/Modified

**Views** ():
- `direct_access_handler()` - Generic payment & access processing
- `direct_access_display()` - Generic external form display

**URLs** ():
- Generic routing: `<slug>/access/` and `<slug>/display/`
- Works for any agent with access_url_name configured

**Template** ():
- Conditional logic: `{% if agent.access_url_name %}`
- Direct access → "Start Consultation" button → External form
- Webhook → Dynamic form (unchanged)

**Migration** ():
- Adds access_url_name and display_url_name fields to Agent model

**Agent Config** ():
- Updated to use generic direct access URLs

## Scalability Achievement

**Ready for 100+ Agents:**
-  New webhook agent: Database record with empty access_url_name
-  New direct access agent: Database record with generic access_url_name
-  Zero code changes needed for new agents
-  Template automatically handles both types
-  Database-driven routing eliminates hardcoded URLs

## Expected Results

**After Railway Deployment:**
- CyberSec Career Navigator: "Start Consultation (FREE)" → Direct JotForm
- All webhook agents: Continue working exactly as before
- System ready for unlimited agents of both types

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 22:46:00 +05:30
Claude
10f7e0d11e 🔧 Add missing model fields and fake migration for Railway schema sync
## Critical Model/Database Sync Fix

**Problem**: Railway database has access_url_name/display_url_name columns but Django model didn't define them.

**Solution**:
 Add missing fields to Agent model with proper Django field definitions
 Create fake migration to sync with existing Railway database schema
 Avoid DuplicateColumn errors on Railway deployment

## Changes Made

**Agent Model** ():
- Added
- Added

**Migration** ():
- Fake migration that does nothing (columns already exist on Railway)
- Marks migration as applied without attempting to create existing columns

## Error Fixed
 Was: Invalid field name(s) for model Agent: 'access_url_name', 'display_url_name'
 Now: Model defines fields that match existing Railway database columns

## Result
- Django model matches Railway PostgreSQL schema
- Agent creation commands will work (fields are now valid)
- populate_agents will succeed and create all 5 agents
- Railway marketplace will finally show agents

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 16:36:00 +05:30
Claude
fb085f215a 🔧 Add missing access_url_name fields to all agent creation commands
## Critical Agent Creation Fix
- Railway PostgreSQL requires access_url_name and display_url_name fields
- ae303c2 agent creation commands were missing these required fields
- Added empty string defaults to all 5 agent creation commands

## Commands Updated
 create_social_ads_agent.py - Added access_url_name/display_url_name
 create_job_posting_agent.py - Added access_url_name/display_url_name
 create_pdf_summarizer_agent.py - Added access_url_name/display_url_name
 create_five_whys_agent.py - Added access_url_name/display_url_name
 create_cybersec_career_agent.py - Added access_url_name/display_url_name

## Error Fixed
 Was: null value in column 'access_url_name' violates not-null constraint
 Now: All agent creation commands provide required fields

## Result
- populate_agents will succeed on Railway deployment
- All 5 agents will be created successfully
- Railway marketplace will show working agents

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 16:30:31 +05:30
Claude
f10a097d9c 🔧 Fix Railway migration DuplicateColumn error with smart column check
## Migration Fix for Railway Database
- Railway PostgreSQL already has access_url_name/display_url_name columns
- Previous migration tried to add existing columns → DuplicateColumn error
- New migration checks if columns exist before adding them

## Smart Migration Logic
 Check information_schema for existing columns
 Add columns only if they don't exist
 Skip if columns already present (Railway case)
 Works for both fresh and existing databases

## Error Fixed
 Was: column 'access_url_name' of relation 'agents_agent' already exists
 Now: Migration succeeds regardless of existing schema state

## Result
- Railway deployment will complete successfully
- populate_agents will run and create all 5 agents
- Marketplace will show agents again

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 16:20:52 +05:30
Claude
54d7d3e506 🔧 Fix Railway database schema mismatch for agent creation
## Critical Database Fix
- Add migration for missing access_url_name and display_url_name fields
- Railway PostgreSQL has these fields as NOT NULL from newer schema
- ae303c2 agent creation commands don't provide these fields
- Migration makes fields optional with empty string defaults

## Error Fixed
 Was: null value in column 'access_url_name' violates not-null constraint
 Now: Fields are optional, agent creation will succeed

## Result
- populate_agents command will now work on Railway
- All 5 agents should appear in production marketplace
- No more database constraint violations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 16:15:46 +05:30
Claude
efdceb8730 🚨 EMERGENCY: Remove destructive database flush from Railway
Critical production fix:
- Remove 'python manage.py flush --noinput' from Railway startup
- Prevent further database destruction on deployment
- Current Railway database is completely empty (no agents, no users)
- This fix will stop future data loss

Next deployment will run populate_agents without wiping existing data.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 16:10:55 +05:30
Claude
ae303c2621 🔧 Fix payment message persistence and add expired session popup
- Fix wallet payment messages showing on login page by clearing messages before redirects
- Remove misleading "Payment processed\!" message for free agents
- Implement minimalist expired session popup for 5 Whys agent
- Add auto-detection of expired sessions on page load with payment confirmation
- Streamline authentication flow messages for better UX
- Remove logout confirmation message to prevent persistence

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 20:57:27 +05:30
Claude
b9c6264b0e 🧹 Improve email verification UX on login page
• Remove always-visible 'Resend email verification' link from login page
• Add contextual resend link only when user needs email verification
• Clean login page with only relevant links (forgot password, register)
• Better user experience - show resend option exactly when needed
• Enable HTML rendering in messages for proper link display

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 19:26:45 +05:30
Claude
3e1136acfa 💰 Remove 50 AED welcome bonus from user registration
• Remove automatic 50 AED wallet bonus for new users
• Update registration success message to remove bonus reference
• Users now start with 0 AED balance (model default)
• Cleaner registration process without misleading bonuses
• Users must top up wallet to use paid agents

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 19:19:11 +05:30
Claude
962d58d37e 🚫 Hide pricing page completely from all users
• Remove pricing link from navigation for all users
• Redirect pricing page access to AI marketplace
• Clean navigation with only essential pages:
  - Home
  - AI Digital Branding
  - AI Marketplace
• Graceful handling if anyone tries to access pricing directly

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 15:54:04 +05:30
Claude
40574db8b0 🗃️ Implement complete Railway database recreation
• Add database flush to Railway startup for complete reset
• Remove manual fix scripts - using clean recreation approach
• Fresh database will have correct agent values from populate_agents
• Guarantees Railway matches local environment exactly

Process:
1. flush --noinput (clear all data)
2. migrate --run-syncdb (create fresh tables)
3. populate_agents (correct agent values)
4. reset_admin (fresh admin user)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:57:49 +05:30
Claude
be6a04c60b 🔧 Add simple agent fix command for Railway deployment
• Create minimal management command to fix agent values
• Fix CyberSec Career Navigator: 12 AED → 0 AED
• Fix 5 Whys agent: 50 messages → 20 messages, ensure 15 AED
• Add to Railway deployment process for automatic fix
• Simplest possible solution - runs on every deploy

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:48:12 +05:30
Claude
fa29584d90 🔄 Add Railway database sync script
• Script to update Railway agents with correct local values
• Fix CyberSec Career Navigator price (12 AED → 0 AED)
• Fix 5 Whys agent message limit (50 → 20) and session time
• Sync all agent prices and message limits

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:44:28 +05:30
Claude
ecb0d1bdd9 📦 Add reportlab dependency for PDF export functionality
• Fix Railway deployment failure: ModuleNotFoundError reportlab
• Required for chat PDF export feature in 5 Whys agent
• Add reportlab==4.2.5 to requirements.txt

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:30:17 +05:30
Claude
d32bbe6606 🔐 Hide pricing page from authenticated users navigation
• Remove pricing link for logged-in users
• Cleaner navigation experience for authenticated users
• Pricing only shown to visitors who need it

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:23:58 +05:30
Claude
a73633aebc 🤖 Transform digital branding page to emphasize AI capabilities
• Rename navigation menu to "AI Digital Branding"
• Update hero section with AI-powered branding focus
• Balance AI emphasis with proven marketing expertise
• Enhance trust indicators with ROI and performance metrics
• Transform service offerings to highlight smart automation
• Integrate AI throughout SOSTAC+RACE framework
• Focus on intelligent solutions and data-driven results
• Maintain credibility while showcasing AI innovation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 14:22:19 +05:30
Claude
942bbcdd40 🎨 Enhance 5 Whys agent response formatting for professional appearance
Improved agent responses to match the formatting quality of other agents
with structured, engaging content using markdown and professional styling.

## Changes:

### 📝 Enhanced Welcome Message:
- Added markdown headers and emojis for engagement
- Structured sections: 'How It Works' and 'Getting Started'
- Clear bullet points and bold emphasis for key concepts
- Professional yet friendly tone

### 🔧 Improved N8N Webhook Instructions:
- Detailed formatting requirements (headers, bold, lists, emojis)
- Clear content guidelines for systematic 5 Whys guidance
- Instructions for structured but conversational responses
- Focus on interactive guidance vs final reports

### 💻 JavaScript Markdown Processing:
- Added formatMarkdownContent() function for consistent formatting
- Processes headers (##, ###), bold text (**text**), bullet points
- Handles both new real-time messages and existing messages on load
- Shared formatting logic for consistency

### 🎨 Enhanced CSS & Template:
- Better message bubble styling for structured content
- Improved typography and spacing for readability
- Support for formatted headers, lists, and emphasis
- Added data attributes for content processing

## Expected User Experience:
- **Before**: Plain text responses lacking visual hierarchy
- **After**: Professional, structured responses with clear sections,
  bullet points, bold emphasis, and engaging emojis

The 5 Whys agent now provides responses that match the quality and
formatting standards of other premium agents in the platform.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 13:54:23 +05:30
Claude
641d676f2f 🎉 Complete 5 Whys agent enhancements with session management and UI improvements
## Major Features Added:

### 🕒 Session Time Limits (2hr → 30min)
- Updated ChatSession model: expires_at, extend_session methods
- Changed session creation and extension logic
- Updated JavaScript timing calculations
- Fixed timing indicator functionality with real-time server data

### 💬 Message Limits (50 → 20)
- Added message_limit field to Agent model with migration
- Implemented auto-completion when message limit reached
- Only count user messages (not agent responses) toward limit
- Enhanced error messaging for limit exceeded

### 📥 Chat Download System
- Added PDF and TXT export functionality using ReportLab
- Download buttons in chat header for active sessions
- Comprehensive export with session metadata and formatting
- New API endpoints: /agents/api/chat/export/{session_id}/

### 📋 Previous Sessions Management
- Created Previous Sessions widget showing last 5 non-active sessions
- Download access for all completed sessions with messages
- Session status indicators ( Completed,  Expired,  Abandoned)
- Clean sidebar organization with session history

### 🎨 UI/UX Improvements
- Moved session info from main chat to sidebar for cleaner interface
- Increased chat height: 600px → 800px (mobile: 500px → 650px)
- Added Current Session widget with status, ID, and start time
- Enhanced sidebar layout with proper component stacking
- Responsive design with mobile optimizations

### 🔧 Session Indicators System
- Real-time session status API with server-side data
- Progress bars for time remaining and message usage
- Warning notifications for approaching limits
- Automatic updates every 30 seconds

### 💰 Payment Flow Fixes
- Fixed charging system to actually deduct wallet balance
- Each new session charges 15 AED for 20 messages + 30 minutes
- Proper error handling for insufficient balance
- Session cleanup on payment failures

## Technical Implementation:

**Backend Changes:**
- Enhanced ChatSession model with 30-minute duration
- Message counting logic (user messages only)
- Auto-completion on limit reached
- Session status API endpoint
- PDF/TXT export with ReportLab

**Frontend Changes:**
- Comprehensive sidebar widget system
- Real-time indicator updates with server sync
- Download functionality with loading states
- Session history display with status icons
- Responsive layout improvements

**Database:**
- Added message_limit field to Agent model
- Updated ChatSession expiration logic
- Efficient queries for session history

## User Experience:
 Clear session limits (20 messages, 30 minutes)
 Automatic session completion with preserved history
 Easy download access for all previous sessions
 Transparent pricing (15 AED per session)
 Clean, organized interface with more chat space
 Real-time feedback on session progress

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 13:28:39 +05:30
Claude
e6ab0d0f37 🎨 Fix 5 Whys agent layout to match other agent templates
- Move 'How it works' widget to sidebar position (below wallet card)
- Add wallet card component to chat template layout
- Use consistent grid layout: main chat widget + sidebar
- Maintains chat functionality while improving UI consistency
- Now matches standard agent template structure

Fixes layout inconsistency where 'How it works' was at bottom instead of sidebar.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-03 09:31:23 +05:30
Claude
7f3b678d39 🔐 Add email verification bypass for testing environments
- Add REQUIRE_EMAIL_VERIFICATION setting (default: True)
- Skip email verification when setting is False
- Auto-verify users and provide welcome bonus when bypassed
- Updated .env.example with documentation
- Allows testing on Railway without email setup until final domain

Perfect for Railway deployment until email/domain configuration is ready.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 13:04:16 +05:30
Claude
7120bfdf98 🤖 Add populate_agents management command for Railway deployment
- Create unified command that calls all individual agent creation commands
- Used by Railway's startCommand to populate production database
- Idempotent design - safe to run multiple times
- Shows detailed summary and environment-specific guidance
- Fixes Railway deployment issue where agents marketplace was empty

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 12:55:29 +05:30
Claude
3fac20fe28 🎯 Complete dual integration architecture with JotForm and digital branding
- Add CyberSec Career Navigator with JotForm white-label integration
- Implement direct access agent system alongside webhook agents
- Add digital branding services page with SOSTAC+RACE methodology
- Create dual integration patterns: webhook vs direct access flows
- Clean up unused form API endpoints for streamlined architecture
- Add career navigator management command and templates
- Update marketplace with conditional logic for different agent types
- Fix UI consistency issues (remove category labels, fix animations)
- Update documentation to reflect new dual architecture

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 10:47:16 +05:30
Claude
d750857e4e Implement chat session timeout system
- Add expires_at field to ChatSession model with 2-hour default
- Sessions automatically expire after 2 hours of inactivity
- Active conversations extend session by 2 hours per message
- Add session expiration checks in chat views
- Create cleanup management command for expired sessions
- Add session status indicators in chat UI
- Fix null safety for existing sessions without expiration

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 15:45:16 +05:30
Claude
ab2360a91d 💬 Implement complete chat-based agent system with 5 Whys Analysis
🏗️ **Database Extensions:**
- Add agent_type field to Agent model (form/chat distinction)
- Create ChatSession model for conversation management
- Create ChatMessage model for message storage with metadata
- Add database indexes for performance optimization

🎨 **Frontend Implementation:**
- Create agent_chat.html template with modern chat interface
- Implement real-time messaging UI with message bubbles
- Add typing indicators and loading states
- Responsive design for mobile and desktop
- Empty states and error handling

🔧 **Backend Logic:**
- Extend agent_detail_view to route chat vs form agents
- Implement chat_agent_view for chat interface rendering
- Add start_chat_session API endpoint with session management
- Add send_chat_message API endpoint with webhook integration
- Add get_chat_history and end_chat_session endpoints
- Session-based fee charging system

🤖 **5 Whys Agent:**
- Create "Analysis & Problem Solving" category
- Implement 5 Whys Analysis chat-based agent (15 AED)
- Interactive problem-solving methodology guidance
- N8N webhook integration for AI responses

 **Interactive Features:**
- JavaScript ChatInterface class for real-time communication
- Auto-session creation and management
- Message validation and error handling
- Automatic scrolling and UI state management
- CSRF protection and security measures

🔗 **API Integration:**
- Chat-specific API endpoints with RESTful design
- Webhook payload formatting for N8N integration
- Session ID tracking and conversation continuity
- Metadata storage for webhook responses

🛡️ **Security & UX:**
- Login required for chat agents
- Wallet balance validation before session creation
- Session isolation per user and agent
- Comprehensive error handling and user feedback

**New URLs:**
- /agents/api/chat/start/ - Start new chat session
- /agents/api/chat/send/ - Send chat message
- /agents/api/chat/history/<session_id>/ - Get chat history
- /agents/api/chat/end/ - End chat session
- /agents/five-whys-analysis/ - 5 Whys chat interface

**Backward Compatibility:**
- Existing form-based agents (Social Ads, Job Posting, PDF) unchanged
- Admin interface updated to show agent types
- Marketplace displays both agent types seamlessly

🚀 Ready for interactive 5 Whys problem-solving conversations\!

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 09:39:43 +05:30
Claude
11d28a17d0 📚 Update documentation after GitHub push 2025-08-01 09:23:11 +05:30
62 changed files with 14988 additions and 663 deletions

View File

@ -4,6 +4,10 @@ DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com ALLOWED_HOSTS=localhost,127.0.0.1,your-domain.com
CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000 CSRF_TRUSTED_ORIGINS=http://localhost:8000,http://127.0.0.1:8000
# Email Verification
# Set to False to bypass email verification for testing (until final domain is ready)
REQUIRE_EMAIL_VERIFICATION=True
# Database Configuration # Database Configuration
# Default: SQLite (simple, reliable, no setup required) # Default: SQLite (simple, reliable, no setup required)
# Railway: Automatically uses PostgreSQL via DATABASE_URL # Railway: Automatically uses PostgreSQL via DATABASE_URL

156
CLAUDE.md
View File

@ -4,13 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview ## Project Overview
Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can purchase AI agent services through a web interface, with agent execution handled via N8N webhooks and payments processed through Stripe. Quantum Tasks AI is a Django-based AI agent marketplace platform. Users can access AI agent services through a web interface, with execution handled via two distinct systems: N8N webhook integrations and direct form access integrations.
**Key Architecture:** **Key Architecture:**
- **Django Framework**: Main web application using Django 5.2.4 - **Django Framework**: Main web application using Django 5.2.4
- **Agent System**: Database-driven agents app with marketplace and N8N webhook execution - **Agent System**: Database-driven agents app with dual integration systems:
- **Webhook Agents**: N8N integrations for complex processing
- **Direct Access Agents**: Form-based integrations (JotForm, etc.)
- **Authentication**: Custom user model with email verification - **Authentication**: Custom user model with email verification
- **Payments**: Stripe integration with wallet system - **Payments**: Stripe integration with wallet system (supports free agents)
- **Database**: SQLite for development, PostgreSQL for production (Railway) - **Database**: SQLite for development, PostgreSQL for production (Railway)
- **Static Files**: WhiteNoise for production static file serving - **Static Files**: WhiteNoise for production static file serving
@ -101,17 +103,27 @@ gunicorn netcop_hub.wsgi:application
### Agent System (agents app) ### Agent System (agents app)
**Key Files:** **Key Files:**
- `agents/models.py`: Agent, AgentCategory, AgentExecution models - `agents/models.py`: Agent, AgentCategory, AgentExecution, ChatSession models
- `agents/views.py`: REST API and web interface views - `agents/views.py`: Dual integration systems and web interface views
- `agents/templates/agents/`: Dynamic agent templates with form generation - `agents/templates/agents/`: Dynamic agent templates and marketplace
- `agents/management/commands/`: Agent creation and management commands - `agents/management/commands/`: Agent creation and management commands
- `templates/career_navigator.html`: Direct access form template
**Agent Flow:** **Dual Integration Systems:**
**System 1: Webhook Agents (N8N Integration)**
1. User browses marketplace (`/agents/`) 1. User browses marketplace (`/agents/`)
2. Selects agent and fills dynamic form (`/agents/{slug}/`) 2. Clicks "Try Now" → Agent detail page (`/agents/{slug}/`)
3. Form submission creates AgentExecution and calls N8N webhook 3. Fills dynamic form → Form submission calls `/agents/api/execute/`
4. N8N processes request and returns response via webhook 4. N8N webhook processes request and returns response
5. Results displayed with file upload support and real-time wallet updates 5. Results displayed with file upload support
**System 2: Direct Access Agents (Form Integration)**
1. User browses marketplace (`/agents/`)
2. Clicks special "Try Now" button → Direct access (`/agents/{slug}/access/`)
3. Payment processed → Redirect to form page (`/agents/{slug}/`)
4. Form displays embedded interface (JotForm, etc.)
5. User interacts directly with external form system
### Database Models ### Database Models
**User Management:** **User Management:**
@ -136,30 +148,21 @@ gunicorn netcop_hub.wsgi:application
- `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`: Stripe API keys - `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`: Stripe API keys
- `DATABASE_URL`: PostgreSQL connection string (Railway) - `DATABASE_URL`: PostgreSQL connection string (Railway)
**N8N Webhook URLs:** **Current System:**
Agent-specific webhook URLs are stored in the database with each agent. Current working agents (all tested and confirmed working): The platform supports **8 total agents** across **6 categories**:
- **4 Webhook Agents** (N8N integration): Social Ads Generator, Job Posting Generator, PDF Summarizer, 5 Whys Analyzer
- **4 Direct Access Agents** (External forms): CyberSec Career Navigator, AI Brand Strategist, Lean Six Sigma Expert, SWOT Analysis Expert
1. **Social Ads Generator** (social-ads-generator) - 6.00 AED For detailed agent information and creation instructions, see `docs/AGENT_CREATION.md`.
- Creates compelling social media advertisements
- Form fields: description, social_platform, include_emoji, language
- Webhook: N8N endpoint for social media ad generation
2. **Job Posting Generator** (job-posting-generator) - 10.00 AED
- Creates professional job postings
- Form fields: job_title, company_name, job_description, seniority_level, contract_type, location, language
- Webhook: N8N endpoint for job posting generation
3. **PDF Summarizer** (pdf-summarizer) - 8.00 AED
- Analyzes and summarizes PDF documents with file upload
- Form fields: pdf_file (file upload with drag-and-drop), summary_type
- Webhook: N8N endpoint for PDF processing with multipart file support
### URL Structure ### URL Structure
``` ```
/ # Homepage (core app) / # Homepage (core app)
/digital-branding/ # Digital branding services page
/auth/ # Authentication (login, register, etc.) /auth/ # Authentication (login, register, etc.)
/agents/ # Agent marketplace (agents app) /agents/ # Agent marketplace (agents app)
/agents/{slug}/ # Individual agent pages /agents/{slug}/ # Individual agent pages (webhook agents)
/agents/{slug}/access/ # Direct access agent payment processing
/wallet/ # Wallet management /wallet/ # Wallet management
/admin/ # Django admin /admin/ # Django admin
``` ```
@ -177,53 +180,16 @@ Agent-specific webhook URLs are stored in the database with each agent. Current
## Adding New Agents ## Adding New Agents
1. **Create management command** (recommended approach): For comprehensive agent creation instructions, see **`docs/AGENT_CREATION.md`**.
```python
# agents/management/commands/create_new_agent.py
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand): **Quick Summary:**
def handle(self, *args, **options): 1. Create JSON config in `agents/configs/agents/your-agent-name.json`
category, _ = AgentCategory.objects.get_or_create( 2. Run `python manage.py populate_agents`
slug='category-slug', 3. Agent appears in marketplace automatically
defaults={'name': 'Category Name', 'icon': '🤖'}
)
Agent.objects.get_or_create(
slug='agent-slug',
defaults={
'name': 'Agent Name',
'short_description': 'Brief description',
'description': 'Full description',
'category': category,
'price': 10.0,
'form_schema': {
'fields': [
{
'name': 'input_field',
'type': 'text',
'label': 'Input Field',
'required': True
}
]
},
'webhook_url': 'http://your-n8n-webhook-url'
}
)
```
2. **Run the command**: `python manage.py create_new_agent` The platform supports 2 agent types:
3. **Update N8N workflow** to handle the new agent - **Webhook Agents** - N8N integration with dynamic forms
4. **Agent will automatically appear** in marketplace with dynamic form generation - **Direct Access Agents** - External forms (JotForm, etc.) with embedded interfaces
**Supported Form Field Types:**
- `text`: Text input
- `textarea`: Multi-line text
- `select`: Dropdown with options
- `file`: File upload with drag-and-drop
- `url`: URL input with validation
- `checkbox`: Boolean checkbox
## Production Deployment ## Production Deployment
@ -270,23 +236,39 @@ class Command(BaseCommand):
## System Status ## System Status
**Current Status: ✅ STABLE WORKING SYSTEM** **Current Status: ✅ STABLE COMPREHENSIVE SYSTEM**
- All 3 agents confirmed working and tested - **8 agents** confirmed working and tested (4 webhook + 4 direct access)
- Clean agents-only architecture (workflows app completely removed) - **6 categories** with clean, logical organization
- Emergency recovery completed from optimization failures - **Dual integration architecture** with clear separation and documentation
- System restored to stable commit 657712f - **Streamlined agent creation** via JSON configs + `populate_agents` command
- **Scalable architecture** ready for 100+ agents
**Current Agents:**
- **Webhook Agents (4)**: Social Ads Generator, Job Posting Generator, PDF Summarizer, 5 Whys Analyzer
- **Direct Access Agents (4)**: CyberSec Career Navigator, AI Brand Strategist, Lean Six Sigma Expert, SWOT Analysis Expert
**Latest Changes:** **Latest Changes:**
- Removed workflows app completely for simplified architecture - **Added SWOT Analysis Expert** with proper category assignment (analysis)
- Enhanced agent marketplace with modern responsive design - **Streamlined agent creation process** to use only JSON + `populate_agents`
- Fixed all authentication-aware UI components - **Separated documentation** into focused files (`docs/AGENT_CREATION.md`)
- Implemented file upload support for PDF Summarizer - **Removed 10+ redundant management commands** for cleaner codebase
- Real-time wallet balance updates after agent execution - **Fixed marketplace consistency** and updated documentation
**Architecture Status:**
- **Error-free agent creation** via JSON configuration approach
- **Railway-ready deployment** with automatic agent population
- **Consistent UI standards** across all marketplace components
- **Comprehensive documentation** prevents common development mistakes
**Future Development:** **Future Development:**
- Optimization work available in feature/optimization-backup branch - **New agents** should follow patterns in `docs/AGENT_CREATION.md`
- Safe to add new agents via database-driven approach - **Use existing categories first** to avoid unnecessary proliferation
- Performance optimizations should be applied incrementally with testing - **JSON + populate_agents** is the only supported creation method
--- ---
Last updated: Last updated: 2025-08-01 01:37:09 Last updated: 2025-01-08
## Documentation
- **Quick Agent Requests**: See `docs/AGENT_REQUEST_TEMPLATE.md` for simple agent request template
- **Agent Creation**: See `docs/AGENT_CREATION.md` for comprehensive agent creation guide
- **Project Overview**: This file (CLAUDE.md) for Django development and architecture

View File

@ -1,5 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import AgentCategory, Agent, AgentExecution from .models import AgentCategory, Agent, AgentExecution, ChatSession, ChatMessage
@admin.register(AgentCategory) @admin.register(AgentCategory)
class AgentCategoryAdmin(admin.ModelAdmin): class AgentCategoryAdmin(admin.ModelAdmin):
@ -10,8 +10,8 @@ class AgentCategoryAdmin(admin.ModelAdmin):
@admin.register(Agent) @admin.register(Agent)
class AgentAdmin(admin.ModelAdmin): class AgentAdmin(admin.ModelAdmin):
list_display = ['name', 'category', 'price', 'is_active', 'created_at'] list_display = ['name', 'category', 'agent_type', 'price', 'is_active', 'created_at']
list_filter = ['category', 'is_active', 'created_at'] list_filter = ['category', 'agent_type', 'is_active', 'created_at']
search_fields = ['name', 'description', 'short_description'] search_fields = ['name', 'description', 'short_description']
prepopulated_fields = {'slug': ('name',)} prepopulated_fields = {'slug': ('name',)}
readonly_fields = ['created_at', 'updated_at'] readonly_fields = ['created_at', 'updated_at']
@ -22,3 +22,21 @@ class AgentExecutionAdmin(admin.ModelAdmin):
list_filter = ['status', 'created_at', 'agent__category'] list_filter = ['status', 'created_at', 'agent__category']
search_fields = ['agent__name', 'user__email'] search_fields = ['agent__name', 'user__email']
readonly_fields = ['created_at', 'completed_at'] readonly_fields = ['created_at', 'completed_at']
@admin.register(ChatSession)
class ChatSessionAdmin(admin.ModelAdmin):
list_display = ['session_id', 'agent', 'user', 'status', 'fee_charged', 'created_at']
list_filter = ['status', 'agent__category', 'created_at']
search_fields = ['session_id', 'agent__name', 'user__email']
readonly_fields = ['session_id', 'created_at', 'updated_at', 'completed_at']
@admin.register(ChatMessage)
class ChatMessageAdmin(admin.ModelAdmin):
list_display = ['session', 'message_type', 'content_preview', 'timestamp']
list_filter = ['message_type', 'timestamp']
search_fields = ['session__session_id', 'content']
readonly_fields = ['timestamp']
def content_preview(self, obj):
return obj.content[:50] + "..." if len(obj.content) > 50 else obj.content
content_preview.short_description = 'Content Preview'

113
agents/configs/README.md Normal file
View File

@ -0,0 +1,113 @@
# Agent Configuration System
This directory contains JSON configuration files for dynamically creating agents and categories in the Quantum Tasks AI platform.
## Directory Structure
```
agents/configs/
├── categories/
│ └── categories.json # All agent categories
├── agents/
│ ├── ai-brand-strategist.json # Direct access agent
│ ├── cybersec-career-navigator.json # Direct access agent
│ ├── five-whys-analysis.json # Chat webhook agent
│ ├── job-posting-generator.json # Form webhook agent
│ ├── pdf-summarizer.json # File upload webhook agent
│ └── social-ads-generator.json # Form webhook agent
└── README.md # This file
```
## How It Works
1. **Categories** are defined in `categories/categories.json`
2. **Agents** are defined in individual JSON files in `agents/`
3. Run `python manage.py populate_agents` to create all agents from configs
4. **Adding new agents** is as simple as creating a new JSON file
## Adding New Agents
### Step 1: Create JSON Configuration File
Create a new file in `agents/` directory, e.g., `email-writer.json`:
```json
{
"slug": "email-writer",
"name": "Email Writer",
"short_description": "AI-powered professional email writing assistant",
"description": "Generate professional emails for any purpose with AI assistance.",
"category": "marketing",
"price": 3.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "email_type",
"type": "select",
"label": "Email Type",
"required": true,
"options": [
{"value": "business", "label": "Business Email"},
{"value": "marketing", "label": "Marketing Email"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/email-writer",
"access_url_name": "",
"display_url_name": ""
}
```
### Step 2: Run Population Command
```bash
python manage.py populate_agents
```
### Step 3: Agent Appears Automatically
The agent will now appear in the marketplace with the configured settings.
## Agent Types
### Webhook Agents (N8N Integration)
- Set `system_type`: `"webhook"`
- Include detailed `form_schema` with fields
- Set `webhook_url` to N8N endpoint
- Leave `access_url_name` and `display_url_name` empty
### Direct Access Agents (External Forms)
- Set `system_type`: `"direct_access"`
- Set `form_schema`: `{"fields": []}`
- Set `webhook_url` to external form URL (JotForm, etc.)
- Set `access_url_name`: `"agents:direct_access_handler"`
- Set `display_url_name`: `"agents:direct_access_display"`
## Field Types for Webhook Agents
- `text`: Single-line text input
- `textarea`: Multi-line text input
- `select`: Dropdown with options array
- `file`: File upload with drag-and-drop
- `url`: URL input with validation
- `checkbox`: Boolean checkbox
## Benefits
**Scalable**: Add 100+ agents without code changes
**Version Controlled**: All agent definitions in git
**Consistent**: Ensures local and Railway databases match
**Simple**: Just create JSON file and run command
**Validated**: Built-in validation and error handling
## Railway Deployment
On Railway, just run:
```bash
python manage.py populate_agents
```
All agents defined in JSON files will be created automatically, ensuring Railway marketplace shows all agents consistently.

View File

@ -0,0 +1,16 @@
{
"slug": "ai-brand-strategist",
"name": "AI Brand Strategist",
"short_description": "Get AI-powered brand strategy insights and recommendations for your business",
"description": "Transform your brand with AI-driven strategic insights. Get expert guidance on brand positioning, messaging, visual identity, and competitive differentiation.",
"category": "marketing",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/01986502acd276b48e3d5f39337046c8d9b6",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -0,0 +1,16 @@
{
"slug": "cybersec-career-navigator",
"name": "CyberSec Career Navigator",
"short_description": "Get personalized cybersecurity career guidance from AI expert Jessica",
"description": "Navigate your cybersecurity career path with expert AI guidance. Get personalized advice on certifications, job roles, skills development, and career progression.",
"category": "career-education",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/019865a942ab7fa5b5b743a5fd2abe09e345",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -0,0 +1,14 @@
{
"slug": "five-whys-analysis",
"name": "5 Whys Analysis",
"short_description": "Interactive problem-solving using the proven 5 Whys methodology",
"description": "Systematically find root causes through guided 5 Whys methodology. Perfect for troubleshooting operational problems, understanding failures, and identifying systemic issues.",
"category": "analysis",
"price": 15.0,
"agent_type": "chat",
"system_type": "webhook",
"form_schema": null,
"webhook_url": "http://localhost:5678/webhook/5-whys-web",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -0,0 +1,55 @@
{
"slug": "job-posting-generator",
"name": "Job Posting Generator",
"short_description": "Create professional job postings that attract top talent",
"description": "Generate comprehensive and attractive job postings with AI-powered content creation. Perfect for HR teams and recruiters.",
"category": "human-resources",
"price": 10.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "job_title",
"type": "text",
"label": "Job Title",
"required": true
},
{
"name": "company_name",
"type": "text",
"label": "Company Name",
"required": true
},
{
"name": "job_description",
"type": "textarea",
"label": "Job Description",
"required": true,
"rows": 5
},
{
"name": "seniority_level",
"type": "select",
"label": "Seniority Level",
"required": true,
"options": [
{"value": "", "label": "Select level..."},
{"value": "entry", "label": "Entry Level"},
{"value": "junior", "label": "Junior"},
{"value": "mid", "label": "Mid Level"},
{"value": "senior", "label": "Senior"}
]
},
{
"name": "location",
"type": "text",
"label": "Location",
"required": true
}
]
},
"webhook_url": "http://localhost:5678/webhook/43f84411-eaaa-488c-9b1f-856e90d0aaf6",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -0,0 +1,16 @@
{
"slug": "lean-six-sigma-expert",
"name": "Lean Six Sigma Expert",
"short_description": "Get expert guidance on Lean Six Sigma methodologies and process improvement strategies",
"description": "Optimize your business processes with expert Lean Six Sigma consultation. Our AI-powered expert provides comprehensive guidance on process improvement, waste reduction, quality enhancement, and operational excellence. Get personalized recommendations for implementing Lean Six Sigma methodologies in your organization.",
"category": "consulting",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/01987b8843ae71129342f62a93d2c605efad",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -0,0 +1,38 @@
{
"slug": "pdf-summarizer",
"name": "PDF Summarizer",
"short_description": "Extract and summarize content from PDF documents with AI analysis",
"description": "Upload PDF documents and get comprehensive AI-powered summaries, key insights, and analysis. Perfect for processing reports and research papers.",
"category": "document-processing",
"price": 8.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "pdf_file",
"type": "file",
"label": "Upload PDF Document",
"required": true,
"accept": ".pdf",
"max_size": "10MB"
},
{
"name": "analysis_type",
"type": "select",
"label": "Analysis Type",
"required": true,
"default": "summary",
"options": [
{"value": "", "label": "Select analysis type..."},
{"value": "summary", "label": "Document Summary"},
{"value": "key_points", "label": "Key Points Extraction"},
{"value": "detailed_analysis", "label": "Detailed Analysis"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/simple-pdf-processor",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -0,0 +1,49 @@
{
"slug": "social-ads-generator",
"name": "Social Ads Generator",
"short_description": "Create compelling social media advertisements optimized for different platforms",
"description": "Generate engaging social media advertisements with AI-powered content generation. Optimized for Facebook, Instagram, LinkedIn, Twitter, TikTok, and YouTube.",
"category": "marketing",
"price": 6.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "description",
"type": "textarea",
"label": "Describe what you'd like to generate",
"placeholder": "Describe the product, service, or campaign",
"required": true,
"rows": 4
},
{
"name": "social_platform",
"type": "select",
"label": "For Social Media Platform",
"required": true,
"options": [
{"value": "", "label": "Select a platform..."},
{"value": "facebook", "label": "Facebook"},
{"value": "instagram", "label": "Instagram"},
{"value": "linkedin", "label": "LinkedIn"},
{"value": "twitter", "label": "X (Twitter)"}
]
},
{
"name": "include_emoji",
"type": "select",
"label": "Include Emoji",
"required": true,
"options": [
{"value": "", "label": "Select an option..."},
{"value": "yes", "label": "Yes"},
{"value": "no", "label": "No"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/2dc234d8-7217-454a-83e9-81afe5b4fe2d",
"access_url_name": "",
"display_url_name": ""
}

View File

@ -0,0 +1,16 @@
{
"slug": "swot-analysis-expert",
"name": "SWOT Analysis Expert",
"short_description": "Strategic business analysis consultation",
"description": "Get expert SWOT analysis to evaluate your business strengths, weaknesses, opportunities, and threats with professional strategic insights.",
"category": "analysis",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/019880edcf997a41a2b4c50daa850a50a0b9",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}

View File

@ -0,0 +1,38 @@
[
{
"slug": "analysis",
"name": "Analysis & Problem Solving",
"description": "AI-powered analysis tools for problem-solving and decision making",
"icon": "🧠"
},
{
"slug": "career-education",
"name": "Career & Education",
"description": "Professional career guidance and educational resources",
"icon": "🎓"
},
{
"slug": "document-processing",
"name": "Document Processing",
"description": "AI-powered document analysis and processing tools",
"icon": "📄"
},
{
"slug": "human-resources",
"name": "Human Resources",
"description": "HR automation and talent management solutions",
"icon": "💼"
},
{
"slug": "marketing",
"name": "Marketing & Advertising",
"description": "AI-powered marketing tools and advertising solutions",
"icon": "📢"
},
{
"slug": "consulting",
"name": "Business Consulting",
"description": "Professional business consultation and strategy services",
"icon": "💼"
}
]

View File

@ -0,0 +1,30 @@
from django.core.management.base import BaseCommand
from django.utils import timezone
from agents.models import ChatSession
class Command(BaseCommand):
help = 'Mark expired chat sessions as expired'
def handle(self, *args, **options):
now = timezone.now()
# Find active sessions that have expired
expired_sessions = ChatSession.objects.filter(
status='active',
expires_at__lt=now
)
count = expired_sessions.count()
if count > 0:
# Mark them as expired
expired_sessions.update(
status='expired',
completed_at=now
)
self.stdout.write(
self.style.SUCCESS(f'✅ Marked {count} expired sessions as expired')
)
else:
self.stdout.write('✅ No expired sessions found')

View File

@ -1,130 +0,0 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create job posting generator agent'
def handle(self, *args, **options):
# Get or use existing HR category
hr_category, created = AgentCategory.objects.get_or_create(
slug='human-resources',
defaults={
'name': 'Human Resources',
'description': 'AI-powered HR and recruitment tools',
'icon': '💼'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {hr_category.name}'))
else:
self.stdout.write(f'Category already exists: {hr_category.name}')
# Create Job Posting Generator agent
job_posting_agent, created = Agent.objects.get_or_create(
slug='job-posting-generator',
defaults={
'name': 'Job Posting Generator',
'short_description': 'Create professional job postings that attract top talent',
'description': 'Generate comprehensive and attractive job postings with AI-powered content creation. Perfect for HR teams and recruiters looking to create compelling job descriptions that attract qualified candidates. Supports multiple languages, locations, and contract types.',
'category': hr_category,
'price': 10.0,
'form_schema': {
'fields': [
{
'name': 'job_title',
'type': 'text',
'label': 'Job Title',
'placeholder': 'e.g., Senior Full Stack Developer',
'required': True,
'help_text': 'The position title for the job posting'
},
{
'name': 'company_name',
'type': 'text',
'label': 'Company Name',
'placeholder': 'e.g., Quantum Technologies Inc.',
'required': True,
'help_text': 'Name of the hiring company'
},
{
'name': 'job_description',
'type': 'textarea',
'label': 'Job Description',
'placeholder': 'Describe the role, responsibilities, and what makes this opportunity exciting...',
'required': True,
'rows': 5,
'help_text': 'Detailed description of the role, responsibilities, and company culture'
},
{
'name': 'seniority_level',
'type': 'select',
'label': 'Seniority Level',
'required': True,
'options': [
{'value': '', 'label': 'Select seniority level...'},
{'value': 'entry', 'label': 'Entry Level'},
{'value': 'junior', 'label': 'Junior'},
{'value': 'mid', 'label': 'Mid Level'},
{'value': 'senior', 'label': 'Senior'},
{'value': 'lead', 'label': 'Lead'},
{'value': 'principal', 'label': 'Principal'},
{'value': 'executive', 'label': 'Executive'}
],
'help_text': 'Experience level required for this position'
},
{
'name': 'contract_type',
'type': 'select',
'label': 'Contract Type',
'required': True,
'options': [
{'value': '', 'label': 'Select contract type...'},
{'value': 'full-time', 'label': 'Full-time'},
{'value': 'part-time', 'label': 'Part-time'},
{'value': 'contract', 'label': 'Contract'},
{'value': 'freelance', 'label': 'Freelance'},
{'value': 'internship', 'label': 'Internship'},
{'value': 'temporary', 'label': 'Temporary'}
],
'help_text': 'Type of employment contract'
},
{
'name': 'location',
'type': 'text',
'label': 'Location',
'placeholder': 'e.g., Dubai, UAE (Remote)',
'required': True,
'help_text': 'Job location, include if remote work is available'
},
{
'name': 'language',
'type': 'select',
'label': 'Language',
'required': False,
'default': 'English',
'options': [
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Primary language for the job posting'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/43f84411-eaaa-488c-9b1f-856e90d0aaf6'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {job_posting_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {job_posting_agent.name}')
self.stdout.write(self.style.SUCCESS('Job Posting Generator setup completed successfully'))
self.stdout.write(f'Agent ID: {job_posting_agent.id}')
self.stdout.write(f'Agent Slug: {job_posting_agent.slug}')
self.stdout.write(f'Price: {job_posting_agent.price} AED')

View File

@ -1,104 +0,0 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create PDF summarizer agent'
def handle(self, *args, **options):
# Get or create Document Processing category
doc_category, created = AgentCategory.objects.get_or_create(
slug='document-processing',
defaults={
'name': 'Document Processing',
'description': 'AI-powered document analysis and processing tools',
'icon': '📄'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {doc_category.name}'))
else:
self.stdout.write(f'Category already exists: {doc_category.name}')
# Create PDF Summarizer agent
pdf_summarizer_agent, created = Agent.objects.get_or_create(
slug='pdf-summarizer',
defaults={
'name': 'PDF Summarizer',
'short_description': 'Extract and summarize content from PDF documents with AI analysis',
'description': 'Upload PDF documents and get comprehensive AI-powered summaries, key insights, and analysis. Perfect for processing reports, research papers, contracts, and other documents. Supports multiple analysis types including summary, key points extraction, and sentiment analysis.',
'category': doc_category,
'price': 8.0,
'form_schema': {
'fields': [
{
'name': 'pdf_file',
'type': 'file',
'label': 'Upload PDF Document',
'required': True,
'accept': '.pdf',
'max_size': '10MB',
'help_text': 'Select a PDF file to analyze (max 10MB)'
},
{
'name': 'analysis_type',
'type': 'select',
'label': 'Analysis Type',
'required': True,
'default': 'summary',
'options': [
{'value': '', 'label': 'Select analysis type...'},
{'value': 'summary', 'label': 'Document Summary'},
{'value': 'key_points', 'label': 'Key Points Extraction'},
{'value': 'detailed_analysis', 'label': 'Detailed Analysis'},
{'value': 'sentiment', 'label': 'Sentiment Analysis'},
{'value': 'questions', 'label': 'Generate Questions'},
{'value': 'action_items', 'label': 'Extract Action Items'}
],
'help_text': 'Choose the type of analysis to perform on the document'
},
{
'name': 'language',
'type': 'select',
'label': 'Document Language',
'required': False,
'default': 'auto',
'options': [
{'value': 'auto', 'label': 'Auto-detect'},
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Specify document language for better analysis accuracy'
},
{
'name': 'output_length',
'type': 'select',
'label': 'Summary Length',
'required': False,
'default': 'medium',
'options': [
{'value': 'short', 'label': 'Short (1-2 paragraphs)'},
{'value': 'medium', 'label': 'Medium (3-5 paragraphs)'},
{'value': 'long', 'label': 'Long (detailed summary)'}
],
'help_text': 'Choose the desired length of the analysis output'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/simple-pdf-processor'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {pdf_summarizer_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {pdf_summarizer_agent.name}')
self.stdout.write(self.style.SUCCESS('PDF Summarizer setup completed successfully'))
self.stdout.write(f'Agent ID: {pdf_summarizer_agent.id}')
self.stdout.write(f'Agent Slug: {pdf_summarizer_agent.slug}')
self.stdout.write(f'Price: {pdf_summarizer_agent.price} AED')

View File

@ -1,151 +0,0 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create sample agents for testing'
def handle(self, *args, **options):
# Create categories
ai_category, _ = AgentCategory.objects.get_or_create(
slug='ai-tools',
defaults={
'name': 'AI Tools',
'description': 'AI-powered automation tools',
'icon': '🤖'
}
)
data_category, _ = AgentCategory.objects.get_or_create(
slug='data-analysis',
defaults={
'name': 'Data Analysis',
'description': 'Data processing and analysis tools',
'icon': '📊'
}
)
web_category, _ = AgentCategory.objects.get_or_create(
slug='web-scraping',
defaults={
'name': 'Web Scraping',
'description': 'Web data extraction tools',
'icon': '🕷️'
}
)
# Create sample agents
Agent.objects.get_or_create(
slug='pdf-analyzer',
defaults={
'name': 'PDF Content Analyzer',
'short_description': 'Extract and analyze content from PDF documents',
'description': 'This agent processes PDF files and extracts meaningful insights including summaries, keywords, and sentiment analysis. Perfect for document processing workflows.',
'category': ai_category,
'price': 5.00,
'form_schema': {
'fields': [
{
'name': 'pdf_url',
'type': 'url',
'label': 'PDF URL',
'placeholder': 'https://example.com/document.pdf',
'required': True
},
{
'name': 'analysis_type',
'type': 'select',
'label': 'Analysis Type',
'options': [
{'value': 'summary', 'label': 'Summary'},
{'value': 'keywords', 'label': 'Keywords'},
{'value': 'sentiment', 'label': 'Sentiment Analysis'}
],
'required': True
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/pdf-analyzer'
}
)
Agent.objects.get_or_create(
slug='website-scraper',
defaults={
'name': 'Website Data Scraper',
'short_description': 'Extract structured data from any website',
'description': 'Advanced web scraping agent that can extract specific data from websites using CSS selectors or XPath. Handles JavaScript-rendered content and returns clean, structured data.',
'category': web_category,
'price': 3.00,
'form_schema': {
'fields': [
{
'name': 'website_url',
'type': 'url',
'label': 'Website URL',
'placeholder': 'https://example.com',
'required': True
},
{
'name': 'selectors',
'type': 'textarea',
'label': 'CSS Selectors (one per line)',
'placeholder': 'h1.title\n.price\n.description',
'required': True
},
{
'name': 'wait_for_js',
'type': 'checkbox',
'label': 'Wait for JavaScript to load',
'required': False
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/website-scraper'
}
)
Agent.objects.get_or_create(
slug='data-analyzer',
defaults={
'name': 'CSV Data Analyzer',
'short_description': 'Analyze and visualize CSV data with insights',
'description': 'Upload CSV files and get comprehensive data analysis including statistics, trends, and visualizations. Perfect for business intelligence and data exploration.',
'category': data_category,
'price': 4.50,
'form_schema': {
'fields': [
{
'name': 'csv_url',
'type': 'url',
'label': 'CSV File URL',
'placeholder': 'https://example.com/data.csv',
'required': True
},
{
'name': 'analysis_columns',
'type': 'text',
'label': 'Columns to Analyze (comma-separated)',
'placeholder': 'sales,revenue,date',
'required': False
},
{
'name': 'chart_type',
'type': 'select',
'label': 'Chart Type',
'options': [
{'value': 'line', 'label': 'Line Chart'},
{'value': 'bar', 'label': 'Bar Chart'},
{'value': 'pie', 'label': 'Pie Chart'},
{'value': 'scatter', 'label': 'Scatter Plot'}
],
'required': False
}
]
},
'webhook_url': 'https://your-n8n-instance.com/webhook/data-analyzer'
}
)
self.stdout.write(self.style.SUCCESS('Sample agents created successfully'))
self.stdout.write(f'Created categories: {AgentCategory.objects.count()}')
self.stdout.write(f'Created agents: {Agent.objects.count()}')

View File

@ -1,101 +0,0 @@
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Create social ads agent for testing'
def handle(self, *args, **options):
# Create Marketing category
marketing_category, created = AgentCategory.objects.get_or_create(
slug='marketing',
defaults={
'name': 'Marketing & Advertising',
'description': 'AI-powered marketing and advertising tools',
'icon': '📢'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created category: {marketing_category.name}'))
else:
self.stdout.write(f'Category already exists: {marketing_category.name}')
# Create Social Ads Generator agent
social_ads_agent, created = Agent.objects.get_or_create(
slug='social-ads-generator',
defaults={
'name': 'Social Ads Generator',
'short_description': 'Create compelling social media advertisements optimized for different platforms',
'description': 'Generate engaging social media advertisements with AI-powered content generation. Optimized for Facebook, Instagram, LinkedIn, Twitter, TikTok, and YouTube. Includes platform-specific formatting, emoji support, and multi-language capabilities.',
'category': marketing_category,
'price': 6.0,
'form_schema': {
'fields': [
{
'name': 'description',
'type': 'textarea',
'label': 'Describe what you\'d like to generate',
'placeholder': 'Describe the product, service, or campaign you want to create an ad for. Include key features, target audience, and any specific messaging you want to emphasize.',
'required': True,
'rows': 4,
'help_text': 'Provide clear, specific information about your product or service for better ad copy'
},
{
'name': 'social_platform',
'type': 'select',
'label': 'For Social Media Platform',
'required': True,
'options': [
{'value': '', 'label': 'Select a platform...'},
{'value': 'facebook', 'label': 'Facebook'},
{'value': 'instagram', 'label': 'Instagram'},
{'value': 'linkedin', 'label': 'LinkedIn'},
{'value': 'twitter', 'label': 'X (Twitter)'},
{'value': 'tiktok', 'label': 'TikTok'},
{'value': 'youtube', 'label': 'YouTube'}
],
'help_text': 'Choose the social media platform for optimization'
},
{
'name': 'include_emoji',
'type': 'select',
'label': 'Include Emoji',
'required': True,
'options': [
{'value': '', 'label': 'Select an option...'},
{'value': 'yes', 'label': 'Yes'},
{'value': 'no', 'label': 'No'}
],
'help_text': 'Whether to include emojis in the ad copy'
},
{
'name': 'language',
'type': 'select',
'label': 'Language',
'required': False,
'default': 'English',
'options': [
{'value': 'English', 'label': 'English'},
{'value': 'Arabic', 'label': 'Arabic (العربية)'},
{'value': 'Spanish', 'label': 'Spanish (Español)'},
{'value': 'French', 'label': 'French (Français)'},
{'value': 'German', 'label': 'German (Deutsch)'},
{'value': 'Chinese', 'label': 'Chinese (中文)'}
],
'help_text': 'Select the primary language for the ad copy'
}
]
},
'webhook_url': 'http://localhost:5678/webhook/2dc234d8-7217-454a-83e9-81afe5b4fe2d'
}
)
if created:
self.stdout.write(self.style.SUCCESS(f'Created agent: {social_ads_agent.name}'))
else:
self.stdout.write(f'Agent already exists: {social_ads_agent.name}')
self.stdout.write(self.style.SUCCESS('Social Ads Agent setup completed successfully'))
self.stdout.write(f'Agent ID: {social_ads_agent.id}')
self.stdout.write(f'Agent Slug: {social_ads_agent.slug}')
self.stdout.write(f'Price: {social_ads_agent.price} AED')

View File

@ -0,0 +1,142 @@
import json
import os
from pathlib import Path
from django.core.management.base import BaseCommand
from agents.models import AgentCategory, Agent
class Command(BaseCommand):
help = 'Dynamically populate all agents and categories from JSON configuration files'
def handle(self, *args, **options):
self.stdout.write(self.style.SUCCESS('🚀 Dynamically populating agents from configuration files...'))
self.stdout.write('')
# Track creation statistics
categories_created = 0
agents_created = 0
config_base_path = Path(__file__).parent.parent.parent / 'configs'
# Load and create categories
categories_file = config_base_path / 'categories' / 'categories.json'
if not categories_file.exists():
self.stdout.write(self.style.ERROR(f'❌ Categories file not found: {categories_file}'))
return
with open(categories_file, 'r', encoding='utf-8') as f:
categories_data = json.load(f)
categories = {}
for category_data in categories_data:
category, created = AgentCategory.objects.get_or_create(
slug=category_data['slug'],
defaults={
'name': category_data['name'],
'description': category_data['description'],
'icon': category_data['icon']
}
)
categories[category_data['slug']] = category
if created:
categories_created += 1
self.stdout.write(f'✅ Created category: {category.name}')
else:
self.stdout.write(f' Category exists: {category.name}')
self.stdout.write('')
# Load and create agents from JSON files
agents_dir = config_base_path / 'agents'
if not agents_dir.exists():
self.stdout.write(self.style.ERROR(f'❌ Agents directory not found: {agents_dir}'))
return
# Get all JSON files in agents directory
agent_files = list(agents_dir.glob('*.json'))
if not agent_files:
self.stdout.write(self.style.WARNING('⚠️ No agent configuration files found'))
return
self.stdout.write(f'📁 Found {len(agent_files)} agent configuration files')
self.stdout.write('')
# Process each agent configuration file
for agent_file in sorted(agent_files):
try:
with open(agent_file, 'r', encoding='utf-8') as f:
agent_data = json.load(f)
# Validate required fields
required_fields = ['slug', 'name', 'category', 'price', 'agent_type']
missing_fields = [field for field in required_fields if field not in agent_data]
if missing_fields:
self.stdout.write(self.style.ERROR(f'❌ Missing fields in {agent_file.name}: {missing_fields}'))
continue
# Get category
category_slug = agent_data['category']
if category_slug not in categories:
self.stdout.write(self.style.ERROR(f'❌ Unknown category "{category_slug}" in {agent_file.name}'))
continue
category = categories[category_slug]
# Create agent
agent, created = Agent.objects.get_or_create(
slug=agent_data['slug'],
defaults={
'name': agent_data['name'],
'short_description': agent_data.get('short_description', ''),
'description': agent_data.get('description', ''),
'category': category,
'price': agent_data['price'],
'agent_type': agent_data['agent_type'],
'form_schema': agent_data.get('form_schema'),
'webhook_url': agent_data.get('webhook_url', ''),
'access_url_name': agent_data.get('access_url_name', ''),
'display_url_name': agent_data.get('display_url_name', '')
}
)
if created:
agents_created += 1
system_type = agent_data.get('system_type', 'webhook')
self.stdout.write(f'✅ Created agent: {agent.name} ({system_type.title()})')
self.stdout.write(f' 💰 Price: {agent.price} AED')
self.stdout.write(f' 📁 Config: {agent_file.name}')
else:
self.stdout.write(f' Agent exists: {agent.name} (from {agent_file.name})')
except json.JSONDecodeError as e:
self.stdout.write(self.style.ERROR(f'❌ Invalid JSON in {agent_file.name}: {e}'))
continue
except Exception as e:
self.stdout.write(self.style.ERROR(f'❌ Error processing {agent_file.name}: {e}'))
continue
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('🎉 Dynamic population completed successfully!'))
self.stdout.write('')
self.stdout.write(f'📊 Summary:')
self.stdout.write(f' Categories created: {categories_created}')
self.stdout.write(f' Agents created: {agents_created}')
self.stdout.write(f' Configuration files processed: {len(agent_files)}')
self.stdout.write('')
# Final verification
total_categories = AgentCategory.objects.filter(is_active=True).count()
total_agents = Agent.objects.filter(is_active=True).count()
webhook_agents = Agent.objects.filter(is_active=True, access_url_name='').count()
direct_agents = Agent.objects.filter(is_active=True).exclude(access_url_name='').count()
self.stdout.write(f'🔍 Final verification:')
self.stdout.write(f' Total categories: {total_categories}')
self.stdout.write(f' Total agents: {total_agents}')
self.stdout.write(f' Webhook agents: {webhook_agents}')
self.stdout.write(f' Direct access agents: {direct_agents}')
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('✅ Database is now consistent and ready!'))
self.stdout.write('')
self.stdout.write('🚀 To add new agents:')
self.stdout.write(' 1. Create new JSON file in agents/configs/agents/')
self.stdout.write(' 2. Run this command again')
self.stdout.write(' 3. Agent will automatically appear in marketplace!')

View File

@ -0,0 +1,160 @@
# Generated by Django 5.2.4 on 2025-08-01 04:01
import django.db.models.deletion
import uuid
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0001_initial"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name="agent",
name="agent_type",
field=models.CharField(
choices=[("form", "Form-based"), ("chat", "Chat-based")],
default="form",
help_text="Agent interaction type",
max_length=10,
),
),
migrations.AlterField(
model_name="agent",
name="form_schema",
field=models.JSONField(
blank=True, help_text="JSON schema for agent input form", null=True
),
),
migrations.CreateModel(
name="ChatSession",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"session_id",
models.CharField(
help_text="Unique session identifier",
max_length=100,
unique=True,
),
),
(
"status",
models.CharField(
choices=[
("active", "Active"),
("completed", "Completed"),
("abandoned", "Abandoned"),
("failed", "Failed"),
],
default="active",
max_length=20,
),
),
(
"context_data",
models.JSONField(
default=dict, help_text="Session context and progress tracking"
),
),
("fee_charged", models.DecimalField(decimal_places=2, max_digits=10)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("completed_at", models.DateTimeField(blank=True, null=True)),
(
"agent",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="chat_sessions",
to="agents.agent",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"ordering": ["-created_at"],
},
),
migrations.CreateModel(
name="ChatMessage",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"message_type",
models.CharField(
choices=[
("user", "User Message"),
("agent", "Agent Response"),
("system", "System Message"),
],
max_length=10,
),
),
("content", models.TextField()),
(
"metadata",
models.JSONField(
default=dict,
help_text="Additional message data like webhook responses",
),
),
("timestamp", models.DateTimeField(auto_now_add=True)),
(
"session",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="messages",
to="agents.chatsession",
),
),
],
options={
"ordering": ["timestamp"],
},
),
migrations.AddIndex(
model_name="chatsession",
index=models.Index(
fields=["session_id"], name="agents_chat_session_0d9cb4_idx"
),
),
migrations.AddIndex(
model_name="chatsession",
index=models.Index(
fields=["user", "-created_at"], name="agents_chat_user_id_f8983d_idx"
),
),
migrations.AddIndex(
model_name="chatmessage",
index=models.Index(
fields=["session", "timestamp"], name="agents_chat_session_e8eaed_idx"
),
),
]

View File

@ -0,0 +1,40 @@
# Generated by Django 5.2.4 on 2025-08-01 10:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
(
"agents",
"0002_agent_agent_type_alter_agent_form_schema_chatsession_and_more",
),
]
operations = [
migrations.AddField(
model_name="chatsession",
name="expires_at",
field=models.DateTimeField(
blank=True,
help_text="Session expiration time (2 hours from last activity)",
null=True,
),
),
migrations.AlterField(
model_name="chatsession",
name="status",
field=models.CharField(
choices=[
("active", "Active"),
("completed", "Completed"),
("expired", "Expired"),
("abandoned", "Abandoned"),
("failed", "Failed"),
],
default="active",
max_length=20,
),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 5.2.4 on 2025-08-03 04:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0003_chatsession_expires_at_alter_chatsession_status"),
]
operations = [
migrations.AddField(
model_name="agent",
name="message_limit",
field=models.IntegerField(
default=50,
help_text="Maximum messages per chat session (for chat agents)",
),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.2.4 on 2025-08-04 11:05
from django.db import migrations
def fake_migration(apps, schema_editor):
"""
Fake migration - Railway database already has access_url_name and display_url_name columns
but Django model didn't have them defined. Now model has fields, so we just need to
mark this migration as applied without doing anything.
"""
pass
class Migration(migrations.Migration):
dependencies = [
("agents", "0004_add_message_limit"),
]
operations = [
migrations.RunPython(fake_migration, fake_migration),
]

View File

@ -0,0 +1,42 @@
# Generated by Django 5.2.4 on 2025-08-04 17:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("agents", "0005_auto_20250804_1105"),
]
operations = [
migrations.AddField(
model_name="agent",
name="access_url_name",
field=models.CharField(
blank=True,
default="",
help_text="URL name for direct access agents",
max_length=100,
),
),
migrations.AddField(
model_name="agent",
name="display_url_name",
field=models.CharField(
blank=True,
default="",
help_text="URL name for agent display page",
max_length=100,
),
),
migrations.AlterField(
model_name="chatsession",
name="expires_at",
field=models.DateTimeField(
blank=True,
help_text="Session expiration time (30 minutes from last activity)",
null=True,
),
),
]

View File

@ -17,6 +17,11 @@ class AgentCategory(models.Model):
return self.name return self.name
class Agent(models.Model): class Agent(models.Model):
AGENT_TYPE_CHOICES = [
('form', 'Form-based'),
('chat', 'Chat-based'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200) name = models.CharField(max_length=200)
slug = models.SlugField(unique=True) slug = models.SlugField(unique=True)
@ -24,8 +29,12 @@ class Agent(models.Model):
description = models.TextField() description = models.TextField()
category = models.ForeignKey(AgentCategory, on_delete=models.CASCADE, related_name='agents') category = models.ForeignKey(AgentCategory, on_delete=models.CASCADE, related_name='agents')
price = models.DecimalField(max_digits=10, decimal_places=2) price = models.DecimalField(max_digits=10, decimal_places=2)
form_schema = models.JSONField(help_text="JSON schema for agent input form") agent_type = models.CharField(max_length=10, choices=AGENT_TYPE_CHOICES, default='form', help_text="Agent interaction type")
form_schema = models.JSONField(help_text="JSON schema for agent input form", null=True, blank=True)
webhook_url = models.URLField(help_text="n8n webhook URL for execution") webhook_url = models.URLField(help_text="n8n webhook URL for execution")
message_limit = models.IntegerField(default=50, help_text="Maximum messages per chat session (for chat agents)")
access_url_name = models.CharField(max_length=100, blank=True, default='', help_text="URL name for direct access agents")
display_url_name = models.CharField(max_length=100, blank=True, default='', help_text="URL name for agent display page")
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
@ -62,3 +71,79 @@ class AgentExecution(models.Model):
def __str__(self): def __str__(self):
return f"{self.agent.name} - {self.user.email} - {self.status}" return f"{self.agent.name} - {self.user.email} - {self.status}"
class ChatSession(models.Model):
STATUS_CHOICES = [
('active', 'Active'),
('completed', 'Completed'),
('expired', 'Expired'),
('abandoned', 'Abandoned'),
('failed', 'Failed'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session_id = models.CharField(max_length=100, unique=True, help_text="Unique session identifier")
agent = models.ForeignKey(Agent, on_delete=models.CASCADE, related_name='chat_sessions')
user = models.ForeignKey('authentication.User', on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='active')
context_data = models.JSONField(default=dict, help_text="Session context and progress tracking")
fee_charged = models.DecimalField(max_digits=10, decimal_places=2)
expires_at = models.DateTimeField(null=True, blank=True, help_text="Session expiration time (30 minutes from last activity)")
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
completed_at = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
# Set expires_at to 30 minutes from now if not set
if not self.expires_at:
from django.utils import timezone
from datetime import timedelta
self.expires_at = timezone.now() + timedelta(minutes=30)
super().save(*args, **kwargs)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['session_id']),
models.Index(fields=['user', '-created_at']),
]
def __str__(self):
return f"{self.agent.name} - {self.user.email} - {self.session_id}"
def is_expired(self):
from django.utils import timezone
if not self.expires_at:
return False # Sessions without expiration date are considered active
return timezone.now() > self.expires_at
def extend_session(self):
"""Extend session by 30 minutes from now"""
from django.utils import timezone
from datetime import timedelta
self.expires_at = timezone.now() + timedelta(minutes=30)
self.updated_at = timezone.now()
self.save()
class ChatMessage(models.Model):
MESSAGE_TYPE_CHOICES = [
('user', 'User Message'),
('agent', 'Agent Response'),
('system', 'System Message'),
]
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
session = models.ForeignKey(ChatSession, on_delete=models.CASCADE, related_name='messages')
message_type = models.CharField(max_length=10, choices=MESSAGE_TYPE_CHOICES)
content = models.TextField()
metadata = models.JSONField(default=dict, help_text="Additional message data like webhook responses")
timestamp = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['timestamp']
indexes = [
models.Index(fields=['session', 'timestamp']),
]
def __str__(self):
return f"{self.session.session_id} - {self.message_type} - {self.timestamp}"

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,42 @@ document.body.setAttribute('data-user-balance', '{{ user.wallet_balance }}');
</h3> </h3>
</div> </div>
<div class="widget-content"> <div class="widget-content">
<form id="agentForm" method="POST" enctype="multipart/form-data" data-agent-id="{{ agent.id }}"> {% if agent.access_url_name and agent.display_url_name %}
<!-- Direct Access Agent - External Form -->
<div class="direct-access-info">
<div class="section-container">
<h4 class="section-subtitle">{{ agent.category.icon }} {{ agent.name }} - External Consultation</h4>
<p style="color: #6b7280; margin-bottom: var(--spacing-lg);">
This consultation will redirect you to our specialized external form for personalized guidance.
</p>
{% if user.is_authenticated %}
{% if agent.price == 0 %}
<a href="{% url 'agents:direct_access_handler' agent.slug %}" class="btn btn-primary btn-full">
{{ agent.category.icon }} Start {{ agent.name }} Consultation (FREE)
</a>
{% elif user.wallet_balance >= agent.price %}
<a href="{% url 'agents:direct_access_handler' agent.slug %}" class="btn btn-primary btn-full">
{{ agent.category.icon }} Start {{ agent.name }} Consultation ({{ agent.price }} AED)
</a>
{% else %}
<div style="background: #fef2f2; color: #dc2626; padding: var(--spacing-md); border-radius: var(--radius-md); margin-bottom: var(--spacing-md); font-size: 14px; font-weight: 500; text-align: center;">
Insufficient balance! You need {{ agent.price }} AED.
</div>
<a href="{% url 'wallet:wallet' %}" class="btn btn-primary btn-full" style="text-decoration: none;">
💰 Top Up Wallet
</a>
{% endif %}
{% else %}
<a href="{% url 'authentication:login' %}" class="btn btn-primary btn-full">
🔐 Login to Continue
</a>
{% endif %}
</div>
</div>
{% else %}
<!-- Webhook Agent - Dynamic Form -->
<form id="agentForm" method="POST" enctype="multipart/form-data" data-agent-id="{{ agent.id }}">
{% csrf_token %} {% csrf_token %}
<!-- Dynamic Form Fields --> <!-- Dynamic Form Fields -->
@ -167,6 +202,7 @@ document.body.setAttribute('data-user-balance', '{{ user.wallet_balance }}');
{% endif %} {% endif %}
</div> </div>
</form> </form>
{% endif %}
</div> </div>
</div> </div>

View File

@ -6,6 +6,9 @@
{% block extra_css %} {% block extra_css %}
<link rel="stylesheet" href="{% static 'css/agent-base.css' %}"> <link rel="stylesheet" href="{% static 'css/agent-base.css' %}">
<link rel="stylesheet" href="{% static 'css/marketplace.css' %}"> <link rel="stylesheet" href="{% static 'css/marketplace.css' %}">
<style>
/* All Try Now buttons now use consistent styling from marketplace.css */
</style>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -49,12 +52,11 @@
<!-- Stats --> <!-- Stats -->
<div class="marketplace-stats"> <div class="marketplace-stats">
{% if search_query %} {% if search_query %}
Search results for "{{ search_query }}" • Search results for "{{ search_query }}"
{% if selected_category %} • {{ selected_category|capfirst }} category{% endif %}
{% elif selected_category %}
{{ selected_category|capfirst }} category
{% endif %} {% endif %}
{% if selected_category %}
{{ selected_category|capfirst }} category •
{% endif %}
{{ agents.count }} agent{{ agents.count|pluralize }} available
</div> </div>
<!-- Agents Grid --> <!-- Agents Grid -->
@ -72,12 +74,47 @@
<p class="agent-description">{{ agent.short_description }}</p> <p class="agent-description">{{ agent.short_description }}</p>
<div class="agent-footer"> <div class="agent-footer">
{% if user.is_authenticated %} {% if user.is_authenticated %}
<span class="agent-category">{{ agent.category.name }}</span> {% if agent.slug == 'cybersec-career-navigator' %}
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a> <a href="{% url 'agents:career_navigator_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'ai-brand-strategist' %}
<a href="{% url 'agents:ai_brand_strategist_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'lean-six-sigma-expert' %}
<a href="{% url 'agents:lean_six_sigma_expert_access' %}" class="try-btn">
Try Now →
</a>
{% elif agent.slug == 'swot-analysis-expert' %}
<a href="{% url 'agents:swot_analysis_expert_access' %}" class="try-btn">
Try Now →
</a>
{% else %}
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
{% endif %}
{% else %} {% else %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;"> {% if agent.slug == 'cybersec-career-navigator' %}
🔐 Login to Try <a href="{% url 'authentication:login' %}?next={% url 'agents:career_navigator_access' %}" class="try-btn login-required" style="width: 100%;">
</a> 🔐 Login to Try
</a>
{% elif agent.slug == 'ai-brand-strategist' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:ai_brand_strategist_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% elif agent.slug == 'lean-six-sigma-expert' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:lean_six_sigma_expert_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% elif agent.slug == 'swot-analysis-expert' %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:swot_analysis_expert_access' %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% else %}
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
🔐 Login to Try
</a>
{% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>

View File

@ -7,13 +7,36 @@ urlpatterns = [
# Web interface # Web interface
path('', views.agents_marketplace, name='marketplace'), path('', views.agents_marketplace, name='marketplace'),
# Direct access routes
path('career-navigator/', views.career_navigator_view, name='career_navigator'),
path('career-navigator/access/', views.career_navigator_access, name='career_navigator_access'),
path('ai-brand-strategist/', views.ai_brand_strategist_view, name='ai_brand_strategist'),
path('ai-brand-strategist/access/', views.ai_brand_strategist_access, name='ai_brand_strategist_access'),
path('lean-six-sigma-expert/', views.lean_six_sigma_expert_view, name='lean_six_sigma_expert'),
path('lean-six-sigma-expert/access/', views.lean_six_sigma_expert_access, name='lean_six_sigma_expert_access'),
path('swot-analysis-expert/', views.swot_analysis_expert_view, name='swot_analysis_expert'),
path('swot-analysis-expert/access/', views.swot_analysis_expert_access, name='swot_analysis_expert_access'),
# API endpoints - specific URLs first to avoid slug conflicts # API endpoints - specific URLs first to avoid slug conflicts
path('api/execute/', views.execute_agent, name='execute_agent'), path('api/execute/', views.execute_agent, name='execute_agent'),
path('api/executions/', views.execution_list, name='execution_list'), path('api/executions/', views.execution_list, name='execution_list'),
path('api/executions/<uuid:execution_id>/', views.execution_detail, name='execution_detail'), path('api/executions/<uuid:execution_id>/', views.execution_detail, name='execution_detail'),
# Chat API endpoints
path('api/chat/start/', views.start_chat_session, name='start_chat_session'),
path('api/chat/send/', views.send_chat_message, name='send_chat_message'),
path('api/chat/history/<str:session_id>/', views.get_chat_history, name='get_chat_history'),
path('api/chat/session/<str:session_id>/status/', views.get_session_status, name='get_session_status'),
path('api/chat/end/', views.end_chat_session, name='end_chat_session'),
path('api/chat/export/<str:session_id>/', views.export_chat, name='export_chat'),
path('api/', views.agent_list, name='agent_list'), path('api/', views.agent_list, name='agent_list'),
path('api/<slug:slug>/', views.agent_detail, name='agent_detail_api'), path('api/<slug:slug>/', views.agent_detail, name='agent_detail_api'),
# Generic direct access routes (must be before agent detail)
path('<slug:slug>/access/', views.direct_access_handler, name='direct_access_handler'),
path('<slug:slug>/display/', views.direct_access_display, name='direct_access_display'),
# Agent detail page (must be last to avoid conflicts) # Agent detail page (must be last to avoid conflicts)
path('<slug:slug>/', views.agent_detail_view, name='detail'), path('<slug:slug>/', views.agent_detail_view, name='detail'),
] ]

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@ def validate_password_strength(password):
is_common = password.lower() in common_passwords is_common = password.lower() in common_passwords
if not (has_length and has_lower and has_upper and has_digit and has_special) or is_common: if not (has_length and has_lower and has_upper and has_digit and has_special) or is_common:
return ["Password must be at least 8 characters with uppercase, lowercase, number, and special character"] return ["Password must have 8+ characters, uppercase, lowercase, number, and special character"]
return [] return []
@ -89,10 +89,17 @@ def handle_ratelimited(request, exception):
@ratelimit(key='ip', rate='5/m', method=UNSAFE, block=False) @ratelimit(key='ip', rate='5/m', method=UNSAFE, block=False)
def login_view(request): def login_view(request):
"""User login view with rate limiting (5 attempts per minute per IP)""" """User login view with rate limiting (5 attempts per minute per IP)"""
# Handle post-login session messages
if 'post_login_message' in request.session:
messages.info(request, request.session.pop('post_login_message'))
# Check if rate limited # Check if rate limited
if getattr(request, 'limited', False): if getattr(request, 'limited', False):
logger.warning(f"Login rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}") # Use session to avoid repeated rate limit messages
messages.error(request, 'Too many login attempts. Please try again in a few minutes.') if not request.session.get('rate_limit_shown'):
logger.warning(f"Login rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.error(request, 'Too many login attempts. Please wait before trying again.')
request.session['rate_limit_shown'] = True
return render(request, 'authentication/login.html') return render(request, 'authentication/login.html')
if request.method == 'POST': if request.method == 'POST':
@ -101,12 +108,16 @@ def login_view(request):
user = authenticate(request, username=email, password=password) user = authenticate(request, username=email, password=password)
if user is not None: if user is not None:
# Check if email is verified # Check if email is verified (only if email verification is required)
if not user.email_verified: if settings.REQUIRE_EMAIL_VERIFICATION and not user.email_verified:
messages.warning(request, 'Please verify your email address before logging in. Check your inbox for the verification link.') messages.warning(request, 'Please verify your email address before logging in. Check your inbox for the verification link.')
return render(request, 'authentication/login.html') # Store resend URL in context for template
context = {'show_resend_verification': True}
return render(request, 'authentication/login.html', context)
login(request, user) login(request, user)
# Clear rate limit flag on successful login
request.session.pop('rate_limit_shown', None)
# Redirect to 'next' parameter if provided, otherwise homepage # Redirect to 'next' parameter if provided, otherwise homepage
next_url = request.GET.get('next') or request.POST.get('next') next_url = request.GET.get('next') or request.POST.get('next')
if next_url: if next_url:
@ -114,6 +125,8 @@ def login_view(request):
return redirect('core:homepage') return redirect('core:homepage')
else: else:
messages.error(request, 'Invalid email or password') messages.error(request, 'Invalid email or password')
# Clear rate limit flag on any POST attempt (failed login)
request.session.pop('rate_limit_shown', None)
return render(request, 'authentication/login.html') return render(request, 'authentication/login.html')
@ -154,15 +167,25 @@ def register_view(request):
email=email, email=email,
password=password1 password=password1
) )
# Don't automatically login - require email verification first
# Send verification email # Handle email verification based on settings
if send_verification_email(user): if settings.REQUIRE_EMAIL_VERIFICATION:
messages.success(request, 'Account created successfully! Please check your email to verify your account.') # Don't automatically login - require email verification first
# Send verification email
if send_verification_email(user):
messages.success(request, 'Account created. Check your email to verify.')
else:
messages.warning(request, 'Account created. Email verification failed - try again later.')
return redirect('authentication:login')
else: else:
messages.warning(request, 'Account created but verification email could not be sent. You can request a new one after logging in.') # Skip email verification - auto-verify and login
user.email_verified = True
return redirect('authentication:login') user.save()
login(request, user)
messages.success(request, f'Welcome {user.username}!')
return redirect('core:homepage')
except Exception as e: except Exception as e:
logger.error(f"Error creating account for {email}: {str(e)}") logger.error(f"Error creating account for {email}: {str(e)}")
messages.error(request, 'Error creating account') messages.error(request, 'Error creating account')
@ -173,7 +196,6 @@ def register_view(request):
def logout_view(request): def logout_view(request):
"""User logout view""" """User logout view"""
logout(request) logout(request)
messages.success(request, 'You have been logged out successfully')
return redirect('core:homepage') return redirect('core:homepage')
@ -325,7 +347,7 @@ def reset_password_view(request, token):
# Mark token as used # Mark token as used
reset_token.mark_as_used() reset_token.mark_as_used()
messages.success(request, 'Your password has been reset successfully. You can now log in.') messages.success(request, 'Password reset. You can now log in.')
return redirect('authentication:login') return redirect('authentication:login')
return render(request, 'authentication/reset_password.html', {'token': token}) return render(request, 'authentication/reset_password.html', {'token': token})
@ -347,7 +369,7 @@ def verify_email_view(request, token):
# Mark token as used # Mark token as used
verification_token.mark_as_used() verification_token.mark_as_used()
messages.success(request, 'Email verified successfully! You can now log in.') messages.success(request, 'Email verified. You can now log in.')
return redirect('authentication:login') return redirect('authentication:login')
@ -372,7 +394,7 @@ def resend_verification_view(request):
# Send new verification email # Send new verification email
if send_verification_email(user): if send_verification_email(user):
messages.success(request, 'Verification email sent. Please check your inbox.') messages.success(request, 'Verification email sent.')
else: else:
messages.error(request, 'Unable to send verification email at this time.') messages.error(request, 'Unable to send verification email at this time.')

View File

@ -5,7 +5,9 @@ app_name = 'core'
urlpatterns = [ urlpatterns = [
path('', views.homepage_view, name='homepage'), path('', views.homepage_view, name='homepage'),
path('digital-branding/', views.digital_branding_view, name='digital_branding'),
path('pricing/', views.pricing_view, name='pricing'), path('pricing/', views.pricing_view, name='pricing'),
path('contact/', views.contact_form_view, name='contact_form'), path('contact/', views.contact_form_view, name='contact_form'),
path('event/', views.event_view, name='event'),
path('health/', views.health_check_view, name='health_check'), path('health/', views.health_check_view, name='health_check'),
] ]

View File

@ -39,30 +39,30 @@ def homepage_view(request):
return render(request, 'core/homepage.html', {'featured_agents': [], 'user_balance': 0}) return render(request, 'core/homepage.html', {'featured_agents': [], 'user_balance': 0})
@ratelimit(key='ip', rate='60/m', method='GET', block=False) @ratelimit(key='ip', rate='60/m', method='GET', block=False)
def pricing_view(request): def pricing_view(request):
"""Pricing page for non-logged-in users with rate limiting""" """Pricing page - redirect to marketplace"""
# Redirect all pricing page access to the AI marketplace
return redirect('agents:marketplace')
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def digital_branding_view(request):
"""Digital branding services page with rate limiting"""
# Check if rate limited # Check if rate limited
if getattr(request, 'limited', False): if getattr(request, 'limited', False):
logger.warning(f"Pricing page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}") logger.warning(f"Digital branding page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.warning(request, 'Too many requests. Please wait a moment before refreshing.') messages.warning(request, 'Too many requests. Please wait a moment before refreshing.')
# If user is already logged in, redirect to wallet top-up
if request.user.is_authenticated:
return redirect('wallet:wallet_topup')
try: try:
# Get sample agents to show pricing context from database
sample_agents = Agent.objects.filter(is_active=True).select_related('category')[:4]
context = { context = {
'sample_agents': sample_agents, 'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0,
} }
return render(request, 'core/pricing.html', context) return render(request, 'core/digital_branding.html', context)
except Exception as e: except Exception as e:
logger.error(f"Pricing view error: {e}") logger.error(f"Digital branding view error: {e}")
messages.error(request, 'Unable to load pricing page. Please try again.') messages.error(request, 'Unable to load digital branding page. Please try again.')
return render(request, 'core/pricing.html', {'sample_agents': []}) return render(request, 'core/digital_branding.html', {})
def validate_contact_input(name, email, message, company=""): def validate_contact_input(name, email, message, company=""):
@ -214,6 +214,22 @@ def contact_form_view(request):
}, status=500) }, status=500)
@ratelimit(key='ip', rate='60/m', method='GET', block=False)
def event_view(request):
"""Event page view"""
# Check if rate limited
if getattr(request, 'limited', False):
logger.warning(f"Event page rate limit exceeded for IP {request.META.get('REMOTE_ADDR')}")
messages.warning(request, 'Too many requests. Please wait a moment before refreshing.')
context = {
'form_url': 'https://form.jotform.com/252214924850455',
'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0,
}
return render(request, 'core/event.html', context)
@ratelimit(key='ip', rate='60/m', method='GET', block=False) @ratelimit(key='ip', rate='60/m', method='GET', block=False)
def health_check_view(request): def health_check_view(request):
"""Simplified health check endpoint - no database dependency for startup""" """Simplified health check endpoint - no database dependency for startup"""

302
docs/AGENT_CREATION.md Normal file
View File

@ -0,0 +1,302 @@
# Agent Creation Guide
This guide provides comprehensive instructions for adding new agents to the Quantum Tasks AI platform.
## Overview
Quantum Tasks AI supports **TWO DISTINCT AGENT SYSTEMS**:
- **Webhook Agents** - N8N integrations for complex processing with dynamic forms
- **Direct Access Agents** - External form services (JotForm, Google Forms) with embedded interfaces
**⚡ RECOMMENDED APPROACH:** Use JSON configuration + `populate_agents` command for error-free, Railway-ready agent creation.
---
## Current Agent Status
**Total Agents: 8** (4 webhook + 4 direct access)
**Total Categories: 6**
### Webhook Agents (N8N Integration)
1. **Social Ads Generator** - 6.00 AED - Creates social media advertisements
2. **Job Posting Generator** - 10.00 AED - Creates professional job postings
3. **PDF Summarizer** - 8.00 AED - Analyzes and summarizes PDF documents
4. **5 Whys Analyzer** - 15.00 AED - Interactive chat-based root cause analysis
### Direct Access Agents (External Forms)
1. **CyberSec Career Navigator** - FREE - Career guidance consultation
2. **AI Brand Strategist** - FREE - Brand strategy consultation
3. **Lean Six Sigma Expert** - FREE - Process improvement consultation
4. **SWOT Analysis Expert** - FREE - Strategic business analysis
---
## 🏷️ Choose Existing Category First
**IMPORTANT:** Always use existing categories before creating new ones to avoid category proliferation.
### Available Categories:
- 🧠 **`analysis`** - Problem-solving, SWOT analysis, strategic analysis tools
- 🎓 **`career-education`** - Career guidance, educational resources, professional development
- 📄 **`document-processing`** - PDF analysis, file processing, document tools
- 💼 **`human-resources`** - Job postings, HR automation, talent management
- 📢 **`marketing`** - Social ads, branding, content marketing, advertising
- 💼 **`consulting`** - Business consultation, strategy services, expert advice
**Only create new categories when absolutely necessary and logically distinct.**
---
## 🚀 Agent Creation Workflow
### System 1: Webhook Agents (N8N Integration)
- **Use for:** Dynamic forms, server-side processing, file uploads, complex workflows
- **Examples:** Social Ads Generator, PDF Summarizer, Job Posting Generator
- **Flow:** Marketplace → Agent detail page → Dynamic form → N8N webhook → Results
### System 2: Direct Access Agents (External Forms)
- **Use for:** External form services (JotForm, Google Forms), consultation interfaces
- **Examples:** SWOT Analysis Expert, CyberSec Career Navigator, AI Brand Strategist
- **Flow:** Marketplace → Payment processing → Quantum Tasks header + embedded external form
---
## 📝 Implementation Steps
### Step 1: Create JSON Configuration
Create a new file in `agents/configs/agents/your-agent-name.json`:
#### Webhook Agent Example:
```json
{
"slug": "content-optimizer",
"name": "Content Optimizer",
"short_description": "AI-powered content optimization and enhancement",
"description": "Enhance your content for better engagement with AI-powered optimization suggestions, tone analysis, and improvement recommendations.",
"category": "marketing",
"price": 5.0,
"agent_type": "form",
"system_type": "webhook",
"form_schema": {
"fields": [
{
"name": "content",
"type": "textarea",
"label": "Content to Optimize",
"required": true
},
{
"name": "content_type",
"type": "select",
"label": "Content Type",
"required": true,
"options": [
{"value": "blog", "label": "Blog Post"},
{"value": "social", "label": "Social Media"},
{"value": "email", "label": "Email Marketing"}
]
}
]
},
"webhook_url": "http://localhost:5678/webhook/content-optimizer",
"access_url_name": "",
"display_url_name": ""
}
```
#### Direct Access Agent Example:
```json
{
"slug": "business-strategist",
"name": "Business Strategist",
"short_description": "Expert business strategy consultation",
"description": "Get professional business strategy insights and recommendations from experienced consultants to grow your business effectively.",
"category": "consulting",
"price": 0.0,
"agent_type": "form",
"system_type": "direct_access",
"form_schema": {
"fields": []
},
"webhook_url": "https://agent.jotform.com/your-form-id",
"access_url_name": "agents:direct_access_handler",
"display_url_name": "agents:direct_access_display"
}
```
### Step 2: Run populate_agents Command
```bash
# Development
source venv/bin/activate
python manage.py populate_agents
# Production (Railway)
python manage.py populate_agents # Runs automatically on deployment
```
### Step 3: Additional Setup (Direct Access Agents Only)
For direct access agents that need custom templates or marketplace integration:
#### 3a. Create Custom Template (optional):
```html
<!-- templates/your_agent_name.html -->
{% extends 'base.html' %}
{% load static %}
{% block title %}Your Agent Name - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
.main-container { max-width: none; padding: 0; height: calc(100vh - 80px); }
.iframe-container { width: 100%; height: 100%; }
.iframe-container iframe { width: 100%; height: 100%; border: none; display: block; }
.footer { display: none !important; }
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe src="{{ form_url }}" frameborder="0" scrolling="auto" title="Your Agent Name"></iframe>
</div>
{% endblock %}
```
#### 3b. Add Custom Views (if needed):
Add view functions to `agents/views.py` following the pattern of existing direct access agents.
#### 3c. Add URL Routes (if needed):
Add routes to `agents/urls.py` following the pattern of existing direct access agents.
#### 3d. Update Marketplace Template (if needed):
Add button logic to `agents/templates/agents/marketplace.html` for custom marketplace behavior.
**⚠️ Important**: Keep all "Try Now" buttons consistent with the format `Try Now →` (no icons or emojis).
### Step 4: Setup External Services
#### For Webhook Agents:
- Create N8N workflow at the webhook URL
- Configure webhook to accept JSON payload with `sessionId`, `message`, etc.
#### For Direct Access Agents:
- Create external form (JotForm, Google Forms, etc.)
- Ensure form URL is accessible and properly configured
---
## ✅ Benefits of This Approach
- ✅ **Single source of truth** - JSON configs define everything
- ✅ **Railway-ready immediately** - No manual database setup needed
- ✅ **Error-free** - No category creation mistakes or typos
- ✅ **Consistent** - All agents use same reliable creation process
- ✅ **Scalable** - Easy to add 100+ agents
- ✅ **Version controlled** - Configs are tracked in git
---
## 🔧 Supported Form Field Types (Webhook Agents)
- `text` - Single-line text input
- `textarea` - Multi-line text input
- `select` - Dropdown with options array
- `file` - File upload with drag-and-drop
- `url` - URL input with validation
- `checkbox` - Boolean checkbox
---
## ⚠️ Common Mistakes to Avoid
1. **Creating unnecessary categories** - Use existing ones first
2. **Missing system_type** - Include "webhook" or "direct_access"
3. **Wrong access_url_name** - Empty for webhook agents, populated for direct access
4. **Forgetting populate_agents** - Run after creating JSON config
5. **Complex custom commands** - Use JSON + populate_agents instead
6. **Adding icons to Try Now buttons** - Keep all marketplace buttons consistent with "Try Now →" format
---
## 🔄 Agent Management Commands
### Essential Commands:
```bash
# Populate all agents from JSON configs (main command)
python manage.py populate_agents
# Clean up expired chat sessions
python manage.py cleanup_expired_sessions
```
### Development Workflow:
1. Create JSON config file
2. Run `populate_agents`
3. Test agent functionality
4. Commit changes to git
5. Deploy to Railway (auto-runs populate_agents)
---
## 📊 Agent Configuration Reference
### Required JSON Fields:
- `slug` - URL-friendly identifier (kebab-case)
- `name` - Display name
- `short_description` - Brief description for marketplace
- `description` - Full description with details
- `category` - Must match existing category slug
- `price` - Price in AED (0.0 for free agents)
- `agent_type` - Always "form"
- `system_type` - "webhook" or "direct_access"
### System-Specific Fields:
#### Webhook Agents:
- `form_schema` - JSON schema defining form fields
- `webhook_url` - N8N webhook endpoint
- `access_url_name` - Empty string ""
- `display_url_name` - Empty string ""
#### Direct Access Agents:
- `form_schema` - Usually `{"fields": []}`
- `webhook_url` - External form URL (JotForm, etc.)
- `access_url_name` - "agents:direct_access_handler"
- `display_url_name` - "agents:direct_access_display"
---
## 🚀 Railway Deployment
When you commit changes to the repository:
1. ✅ **Railway auto-deploys** new code
2. ✅ **populate_agents runs automatically** on deployment
3. ✅ **New agents appear** in production marketplace
4. ✅ **Categories are created** if needed (but use existing ones first!)
5. ✅ **No manual database work** required
---
## 📞 Support & Documentation
- **Main Documentation**: See `CLAUDE.md` for project overview
- **Agent Issues**: Check Railway logs and database for agent status
- **Form Problems**: Verify external form URLs are accessible
- **Category Issues**: Use existing categories from the list above
---
## 🚀 Quick Agent Request
**For fast agent creation**, use the **Agent Request Template**:
👉 **See `docs/AGENT_REQUEST_TEMPLATE.md`** for a simple template to request new agents
Simply fill out the template and provide it to Claude Code for instant agent creation!
---
*Last updated: 2025-01-08*

View File

@ -0,0 +1,135 @@
# Agent Request Template
Use this template when requesting new agents to ensure all necessary information is provided for quick, error-free agent creation.
## How to Use This Template
1. **Copy the template below**
2. **Fill in all required fields**
3. **Provide to Claude Code** with the request "Create agent using this template"
4. **Claude will handle** JSON config creation, populate_agents execution, and deployment
---
## Agent Request Template
```markdown
## New Agent Request
**Agent Name**: [Enter the display name for the agent]
**Type**: [Webhook OR Direct Access]
**Category**: [Choose from: analysis, career-education, document-processing, human-resources, marketing, consulting]
**Price**: [X.XX AED or 0.0 for FREE]
**Short Description**: [Brief 1-line description for marketplace]
**Full Description**: [Detailed description of what the agent does and its benefits]
### For Webhook Agents Only:
**Form Fields**:
- Field 1: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
- Field 2: [name: field_name, type: text/textarea/select/file/url/checkbox, label: "Display Label", required: true/false]
- [Add more fields as needed]
**N8N Webhook URL**: [Your N8N webhook endpoint URL]
### For Direct Access Agents Only:
**External Form URL**: [JotForm, Google Forms, or other external form URL]
**Custom Template Needed**: [Yes/No - specify if you need custom styling/layout]
**Custom Views Needed**: [Yes/No - specify if you need special marketplace behavior]
### Optional Information:
**Special Requirements**: [Any unique features or customizations needed]
**Integration Notes**: [Any special setup or configuration details]
```
---
## Available Categories
**Choose from these existing categories** (avoid creating new ones):
- 🧠 **`analysis`** - Problem-solving, SWOT analysis, strategic analysis tools
- 🎓 **`career-education`** - Career guidance, educational resources, professional development
- 📄 **`document-processing`** - PDF analysis, file processing, document tools
- 💼 **`human-resources`** - Job postings, HR automation, talent management
- 📢 **`marketing`** - Social ads, branding, content marketing, advertising
- 💼 **`consulting`** - Business consultation, strategy services, expert advice
---
## Form Field Types (Webhook Agents)
- **`text`** - Single-line text input
- **`textarea`** - Multi-line text input
- **`select`** - Dropdown (requires options array)
- **`file`** - File upload with drag-and-drop
- **`url`** - URL input with validation
- **`checkbox`** - Boolean true/false
---
## Example Requests
### Example 1: Webhook Agent
```markdown
## New Agent Request
**Agent Name**: Email Campaign Optimizer
**Type**: Webhook
**Category**: marketing
**Price**: 4.0 AED
**Short Description**: AI-powered email campaign optimization and A/B testing
**Full Description**: Optimize your email campaigns with AI analysis of subject lines, content, and send times. Get recommendations for better open rates and conversions.
### Form Fields:
- Field 1: [name: email_subject, type: text, label: "Email Subject Line", required: true]
- Field 2: [name: email_content, type: textarea, label: "Email Content", required: true]
- Field 3: [name: target_audience, type: select, label: "Target Audience", required: true, options: [{"value": "b2b", "label": "Business"}, {"value": "b2c", "label": "Consumer"}]]
**N8N Webhook URL**: http://localhost:5678/webhook/email-optimizer
```
### Example 2: Direct Access Agent
```markdown
## New Agent Request
**Agent Name**: Financial Planning Consultant
**Type**: Direct Access
**Category**: consulting
**Price**: 0.0 AED
**Short Description**: Professional financial planning and investment consultation
**Full Description**: Get expert financial advice tailored to your goals. Our certified financial planners provide personalized investment strategies and retirement planning.
### For Direct Access Agents:
**External Form URL**: https://agent.jotform.com/financial-planning-form-id
**Custom Template Needed**: No
**Custom Views Needed**: No
```
---
## What Happens Next
After you provide the completed template:
1. ✅ **Claude creates JSON config** in `agents/configs/agents/`
2. ✅ **Runs populate_agents command** to add agent to database
3. ✅ **Agent appears in marketplace** automatically
4. ✅ **Creates any needed templates/views** (for Direct Access agents)
5. ✅ **Updates marketplace integration** if needed
6. ✅ **Commits changes** and makes them Railway-ready
**No additional work needed on your part!** 🚀
---
## Tips for Better Requests
- ✅ **Use existing categories** - Avoid creating new ones unless absolutely necessary
- ✅ **Be specific** - Clear descriptions help users understand the agent's value
- ✅ **Test external forms** - Ensure JotForm/external URLs are working before requesting
- ✅ **Consider pricing** - Free agents get more usage, paid agents need clear value proposition
- ✅ **Think about fields** - For webhook agents, plan your form fields carefully
---
*For comprehensive agent creation details, see `docs/AGENT_CREATION.md`*

View File

@ -1,10 +1,10 @@
=== Documentation Auto-Update Summary === === Documentation Auto-Update Summary ===
Update Date: 2025-08-01 01:37:22 Update Date: 2025-08-01 09:23:11
Recent Commits: Recent Commits:
- 11d28a1 📚 Update documentation after GitHub push
- f6970b6 🎨 Complete Phase 1 UI optimization with button hover fixes
- 277e7ec 📄 Auto-update documentation timestamp after security fixes - 277e7ec 📄 Auto-update documentation timestamp after security fixes
- c8ad34f 🔒 Implement critical security fixes for production readiness
- 657712f 🗑️ Remove workflows app completely and streamline to agents-only
Documentation Changes: Documentation Changes:
- CLAUDE.md - CLAUDE.md

8943
local_database_dump.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,10 @@ if config('RAILWAY_ENVIRONMENT', default=''):
else: else:
SITE_URL = config('SITE_URL', default='http://localhost:8000') SITE_URL = config('SITE_URL', default='http://localhost:8000')
# Email verification requirement
# Set to False for testing environments until final domain is ready
REQUIRE_EMAIL_VERIFICATION = config('REQUIRE_EMAIL_VERIFICATION', default=True, cast=bool)
# Application definition # Application definition

View File

@ -4,7 +4,7 @@
"builder": "NIXPACKS" "builder": "NIXPACKS"
}, },
"deploy": { "deploy": {
"startCommand": "python manage.py migrate --run-syncdb; python manage.py populate_agents; python manage.py reset_admin; python manage.py verify_email admin@quantumtaskai.com --force || true; python manage.py collectstatic --noinput && gunicorn netcop_hub.wsgi:application --bind 0.0.0.0:$PORT --workers 1 --timeout 60", "startCommand": "python manage.py migrate; python manage.py populate_agents; python manage.py reset_admin; python manage.py verify_email admin@quantumtaskai.com --force || true; python manage.py collectstatic --noinput && gunicorn netcop_hub.wsgi:application --bind 0.0.0.0:$PORT --workers 1 --timeout 60",
"restartPolicyType": "ON_FAILURE", "restartPolicyType": "ON_FAILURE",
"restartPolicyMaxRetries": 3 "restartPolicyMaxRetries": 3
}, },

View File

@ -8,6 +8,7 @@ gunicorn==21.2.0
psycopg2-binary==2.9.9 psycopg2-binary==2.9.9
dj-database-url==2.1.0 dj-database-url==2.1.0
whitenoise==6.8.2 whitenoise==6.8.2
reportlab==4.2.5
# Optional performance dependencies # Optional performance dependencies
redis==5.2.0 redis==5.2.0

View File

@ -89,7 +89,7 @@ html {
/* Layout - Data Analyzer Exact Copy */ /* Layout - Data Analyzer Exact Copy */
.agent-container { .agent-container {
margin: 0 auto; margin: 0 auto;
padding: var(--spacing-lg); padding: var(--spacing-sm);
max-width: 1600px; max-width: 1600px;
} }
@ -99,7 +99,7 @@ html {
border-radius: var(--radius); border-radius: var(--radius);
padding: var(--space-lg); padding: var(--space-lg);
border: var(--agent-card-border); border: var(--agent-card-border);
margin-bottom: var(--space-lg); margin-bottom: var(--space-md);
backdrop-filter: var(--agent-backdrop-filter); backdrop-filter: var(--agent-backdrop-filter);
box-shadow: var(--agent-card-shadow); box-shadow: var(--agent-card-shadow);
} }
@ -1207,7 +1207,7 @@ html {
/* Agent Grid and Layout System */ /* Agent Grid and Layout System */
.agent-grid { .agent-grid {
display: flex; display: flex;
gap: var(--spacing-lg); gap: var(--spacing-sm);
align-items: flex-start; align-items: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} }
@ -1216,7 +1216,7 @@ html {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
margin-bottom: var(--spacing-xl); margin-bottom: 20px;
} }
/* Typography - Data Analyzer Exact Copy */ /* Typography - Data Analyzer Exact Copy */

View File

@ -0,0 +1,652 @@
/* Digital Branding Services Page Styles */
/* Following homepage.css patterns and using unified color system from base.css */
/* Hero Section - matches homepage hero */
.digital-branding-hero {
position: relative;
background: var(--gradient-hero);
overflow: hidden;
min-height: 85vh;
display: flex;
align-items: center;
padding: clamp(40px, 10vw, 80px) clamp(16px, 4vw, 24px) clamp(60px, 15vw, 100px);
}
.hero-container {
max-width: 1280px;
margin: 0 auto;
text-align: center;
position: relative;
z-index: 10;
width: 100%;
}
.trust-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(59, 130, 246, 0.08);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 2.5rem;
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
border: 1px solid rgba(59, 130, 246, 0.15);
backdrop-filter: blur(10px);
}
.trust-badge-emoji {
font-size: 0.75rem;
}
.hero-title {
font-weight: 800;
margin-bottom: 2.5rem;
line-height: 1.1;
letter-spacing: -0.02em;
font-size: clamp(36px, 8vw, 110px);
margin-bottom: clamp(24px, 6vw, 40px);
}
.hero-title-gradient {
background: var(--gradient-primary);
background-size: 300% 300%;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-title-normal {
color: var(--text-primary);
}
.hero-description {
color: var(--text-secondary);
margin-bottom: 3.5rem;
max-width: 720px;
margin-left: auto;
margin-right: auto;
line-height: 1.7;
font-weight: 400;
font-size: clamp(1.1rem, 3vw, 1.4rem);
margin-bottom: clamp(32px, 8vw, 56px);
padding: 0 clamp(8px, 2vw, 16px);
}
.hero-buttons {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-bottom: 5rem;
gap: clamp(12px, 3vw, 20px);
margin-bottom: clamp(40px, 10vw, 80px);
padding: 0 clamp(8px, 2vw, 16px);
}
.btn-primary {
background: var(--gradient-primary);
color: white;
border-radius: 1rem;
font-weight: bold;
border: none;
cursor: pointer;
box-shadow: 0 8px 24px rgba(59, 130, 246, 0.25), 0 4px 12px rgba(0, 0, 0, 0.05);
letter-spacing: 0.01em;
text-align: center;
text-decoration: none;
display: inline-block;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.4);
filter: brightness(1.1);
}
.btn-primary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
.btn-secondary {
background: var(--background-card);
color: var(--primary-blue);
border-radius: 1rem;
font-weight: 600;
border: 2px solid var(--border-light);
text-decoration: none;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.04), 0 4px 12px rgba(59, 130, 246, 0.08);
letter-spacing: 0.01em;
display: inline-block;
text-align: center;
padding: clamp(14px, 4vw, 18px) clamp(24px, 6vw, 36px);
font-size: clamp(14px, 3.5vw, 18px);
min-height: 48px;
min-width: clamp(140px, 40vw, 180px);
transition: all 0.2s ease;
}
.btn-secondary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(59, 130, 246, 0.15);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
}
.btn-secondary:active {
transform: translateY(0);
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.12);
}
.trust-indicators {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
gap: clamp(16px, 4vw, 48px);
max-width: 600px;
margin: 0 auto;
padding: 0 clamp(8px, 2vw, 16px);
}
.trust-card {
text-align: center;
background: rgba(255, 255, 255, 0.5);
border: 1px solid rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.03);
border-radius: 1rem;
padding: clamp(16px, 4vw, 24px) clamp(12px, 3vw, 16px);
}
.trust-number {
background: var(--text-gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
font-weight: 800;
margin-bottom: 0.5rem;
font-size: clamp(1rem, 3vw, 1.2rem);
}
.trust-text {
color: var(--text-secondary);
font-weight: 500;
letter-spacing: 0.01em;
font-size: clamp(12px, 3vw, 15px);
}
/* Why Choose Us Section - matches company profile */
.why-choose-us {
position: relative;
background: var(--company-gradient);
overflow: hidden;
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.section-container {
max-width: 1200px;
margin: 0 auto;
position: relative;
z-index: 10;
}
.section-header {
text-align: center;
margin-bottom: clamp(40px, 10vw, 80px);
}
.section-badge {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: rgba(30, 64, 175, 0.1);
padding: 0.5rem 1.25rem;
border-radius: 50px;
margin-bottom: 1.5rem;
border: 1px solid rgba(30, 64, 175, 0.2);
}
.section-badge-icon {
font-size: 1rem;
}
.section-badge-text {
font-size: 0.875rem;
font-weight: 600;
color: var(--primary-blue);
}
.section-title {
font-weight: 800;
color: var(--primary-blue);
margin-bottom: 1rem;
text-align: center;
font-size: clamp(2rem, 5vw, 3.5rem);
}
.section-subtitle {
font-size: 1.25rem;
color: var(--text-light);
max-width: 600px;
margin: 0 auto;
line-height: 1.6;
}
.why-choose-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(24px, 6vw, 40px);
}
.choice-card {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 40px);
transition: all 0.2s ease;
}
.choice-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3.5rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.choice-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.choice-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 18px);
}
/* Our Process Section - matches services */
.our-process {
background: var(--services-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.process-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
margin-bottom: clamp(40px, 10vw, 60px);
}
.process-step-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 32px);
display: flex;
align-items: flex-start;
gap: clamp(16px, 4vw, 20px);
transition: all 0.2s ease;
}
.step-number {
background: var(--gradient-primary);
color: white;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: clamp(16px, 4vw, 20px);
flex-shrink: 0;
}
.step-content {
flex: 1;
}
.step-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 0.75rem;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.step-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* RACE Framework */
.race-framework {
background: white;
border-radius: clamp(16px, 4vw, 24px);
box-shadow: 0 12px 40px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.race-title {
text-align: center;
font-weight: bold;
color: var(--primary-blue);
margin-bottom: clamp(20px, 5vw, 32px);
font-size: clamp(1.3rem, 4vw, 1.8rem);
}
.race-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
gap: clamp(16px, 4vw, 24px);
}
.race-card {
text-align: center;
background: var(--background-light);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
transition: all 0.2s ease;
}
.race-phase {
margin-bottom: 0.75rem;
}
.race-icon {
font-size: clamp(1.5rem, 4vw, 2rem);
margin-bottom: 0.5rem;
display: block;
}
.race-phase h4 {
font-weight: bold;
color: var(--primary-blue);
margin: 0;
font-size: clamp(1.1rem, 3.5vw, 1.3rem);
}
.race-focus {
font-weight: 600;
color: var(--text-primary);
margin-bottom: 0.5rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.race-actions {
color: var(--text-light);
font-size: clamp(12px, 3vw, 14px);
line-height: 1.5;
}
/* Branding Services Section - matches services */
.branding-services {
background: var(--clients-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.services-title {
font-weight: bold;
text-align: center;
margin-bottom: 1rem;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
}
.services-subtitle {
text-align: center;
color: var(--text-light);
margin-bottom: 3rem;
font-size: clamp(16px, 4vw, 20px);
margin-bottom: clamp(24px, 6vw, 48px);
}
.branding-services-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
gap: clamp(20px, 5vw, 32px);
}
.service-card {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
text-align: center;
padding: clamp(24px, 6vw, 32px);
transition: all 0.2s ease;
}
.service-icon {
margin-bottom: 1.25rem;
font-size: clamp(2.5rem, 6vw, 3rem);
margin-bottom: clamp(16px, 4vw, 20px);
}
.service-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.2rem, 4vw, 1.4rem);
margin-bottom: clamp(12px, 3vw, 16px);
}
.service-description {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
/* CTA Section - matches contact */
.branding-cta {
background: var(--contact-gradient);
padding: clamp(60px, 15vw, 120px) clamp(16px, 4vw, 24px);
}
.cta-container {
max-width: 1200px;
margin: 0 auto;
}
.cta-title {
font-weight: bold;
text-align: center;
color: var(--primary-blue);
font-size: clamp(1.8rem, 5vw, 2.5rem);
margin-bottom: clamp(24px, 6vw, 48px);
}
.cta-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(350px, 100%), 1fr));
gap: clamp(30px, 8vw, 60px);
align-items: start;
}
.cta-content {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-content-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1rem;
font-size: clamp(1.3rem, 4vw, 1.6rem);
}
.cta-description {
color: var(--text-light);
line-height: 1.6;
margin-bottom: 1.5rem;
font-size: clamp(14px, 3.5vw, 18px);
}
.cta-features {
margin-bottom: 2rem;
}
.cta-feature {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 0.75rem;
font-size: clamp(14px, 3.5vw, 16px);
}
.feature-icon {
color: var(--success-green);
font-weight: bold;
}
.cta-buttons {
display: flex;
flex-direction: column;
gap: clamp(12px, 3vw, 16px);
}
.cta-btn {
padding: clamp(14px, 4vw, 16px) clamp(20px, 5vw, 24px);
border-radius: clamp(8px, 2vw, 12px);
font-weight: 600;
text-decoration: none;
text-align: center;
font-size: clamp(14px, 3.5vw, 16px);
transition: all 0.2s ease;
min-height: 48px;
display: flex;
align-items: center;
justify-content: center;
}
.cta-btn.primary {
background: var(--gradient-primary);
color: white;
box-shadow: 0 4px 16px rgba(59, 130, 246, 0.25);
}
.cta-btn.primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.35);
}
.cta-btn.secondary {
background: var(--background-card);
color: var(--primary-blue);
border: 2px solid var(--border-light);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
}
.cta-btn.secondary:hover {
transform: translateY(-2px);
border-color: var(--primary-blue);
background: rgba(59, 130, 246, 0.05);
box-shadow: 0 6px 20px rgba(59, 130, 246, 0.15);
}
.cta-info {
background: white;
border-radius: clamp(16px, 4vw, 20px);
box-shadow: 0 8px 32px rgba(30, 64, 175, 0.08);
padding: clamp(24px, 6vw, 40px);
}
.cta-info-title {
font-weight: bold;
color: var(--primary-blue);
margin-bottom: 1.5rem;
font-size: clamp(1.2rem, 4vw, 1.5rem);
margin-bottom: clamp(16px, 4vw, 24px);
}
.contact-item {
display: flex;
align-items: flex-start;
gap: clamp(12px, 3vw, 16px);
margin-bottom: clamp(20px, 5vw, 32px);
}
.contact-icon {
background: var(--primary-gradient);
border-radius: clamp(8px, 2vw, 12px);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: clamp(40px, 10vw, 50px);
height: clamp(40px, 10vw, 50px);
font-size: clamp(16px, 4vw, 20px);
}
.contact-details h4 {
font-weight: 600;
color: var(--primary-blue);
margin-bottom: 0.5rem;
font-size: clamp(16px, 4vw, 19px);
}
.contact-details p {
color: var(--text-light);
line-height: 1.6;
font-size: clamp(14px, 3.5vw, 16px);
}
.contact-email {
color: var(--primary-blue);
text-decoration: none;
}
.contact-email:hover {
text-decoration: underline;
}
.commitment-statement {
background: var(--services-gradient);
border-left: 4px solid var(--primary-blue);
border-radius: clamp(12px, 3vw, 16px);
padding: clamp(16px, 4vw, 24px);
margin-top: clamp(20px, 5vw, 32px);
}
.commitment-text {
color: var(--primary-blue);
font-weight: 600;
text-align: center;
font-size: clamp(14px, 3.5vw, 18px);
line-height: 1.6;
}
/* Loading state for buttons */
.cta-btn.loading {
opacity: 0.7;
pointer-events: none;
}
/* Mobile responsive adjustments */
@media (max-width: 767px) {
.cta-buttons {
flex-direction: column;
}
.process-step-card {
flex-direction: column;
text-align: center;
}
.step-number {
margin: 0 auto 1rem auto;
}
.race-grid {
grid-template-columns: 1fr;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
static/img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

BIN
static/img/og-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

View File

@ -478,6 +478,109 @@ class AgentsCore extends WorkflowsCore {
return isValid; return isValid;
} }
/**
* Handle JotForm agent execution (CyberSec Career Navigator)
*/
async handleJotFormAgent() {
// Check authentication and balance
if (!this.constructor.checkAuthentication()) return;
if (!this.constructor.checkBalance(this.price)) return;
const submitBtn = document.getElementById('generateBtn');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.textContent = '⏳ Processing Payment...';
}
try {
// Create execution record and charge wallet via form API
const response = await fetch('/agents/api/form/access/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
agent_slug: this.agentSlug
})
});
if (response.ok) {
const result = await response.json();
// Update wallet balance
this.constructor.updateWalletBalance(result.new_balance);
// Show white-label interface
this.showWhiteLabelInterface(result.interface_url);
this.constructor.showToast('✅ Payment processed! Access granted to Quantum AI Career Navigator', 'success');
} else {
const error = await response.json();
throw new Error(error.error || 'Failed to process payment');
}
} catch (error) {
console.error('Form agent error:', error);
this.constructor.showToast(`${error.message}`, 'error');
this.resetSubmitButton();
}
}
/**
* Show white-label interface in results container
*/
showWhiteLabelInterface(interfaceUrl) {
const resultsContainer = document.getElementById('resultsContainer');
const resultsContent = document.getElementById('resultsContent');
if (resultsContainer && resultsContent) {
// Update header
const widgetTitle = resultsContainer.querySelector('.widget-title');
if (widgetTitle) {
widgetTitle.innerHTML = '<span class="widget-icon">🎓</span>Quantum AI Career Navigator';
}
// Create white-label interface
resultsContent.innerHTML = `
<div class="career-nav-container" style="text-align: center; margin-bottom: 20px;">
<h3 style="color: #0369a1; margin-bottom: 10px;">🎓 Quantum AI Career Navigator</h3>
<p style="color: #6b7280; margin-bottom: 20px;">Meet Jessica, your personal AI cybersecurity career advisor. Share your goals and get expert guidance tailored to your journey.</p>
</div>
<div class="career-interface-container" style="width: 100%; min-height: 600px; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.1);">
<iframe
src="${interfaceUrl}"
style="width: 100%; min-height: 600px; border: none; background: white;"
frameborder="0"
scrolling="auto"
title="Quantum AI Career Navigator - Your Personal Career Advisor">
</iframe>
</div>
<div class="career-footer" style="margin-top: 20px; padding: 15px; background: #f8fafc; border-radius: 8px; text-align: center;">
<p style="color: #6b7280; font-size: 14px; margin: 0;">
💡 <strong>Pro Tip:</strong> Be specific about your experience level and career goals for the most personalized advice from your AI advisor!
</p>
</div>
`;
// Hide action buttons since this is an interactive interface
const actionButtons = resultsContainer.querySelector('.results-actions');
if (actionButtons) {
actionButtons.style.display = 'none';
}
// Show results container
resultsContainer.style.display = 'block';
// Scroll to results
resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
// Reset submit button
this.resetSubmitButton();
}
}
/** /**
* Reset submit button to original state * Reset submit button to original state
*/ */

View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}AI Brand Strategist - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="AI Brand Strategist">
</iframe>
</div>
{% endblock %}

View File

@ -104,6 +104,37 @@
text-decoration: underline; text-decoration: underline;
} }
.verification-actions {
text-align: center;
margin-bottom: var(--spacing-lg);
padding: var(--spacing-md);
background: var(--surface-variant);
border-radius: var(--radius-sm);
border: 1px solid var(--outline);
}
.verification-text {
margin: 0 0 var(--spacing-sm) 0;
color: var(--on-surface-variant);
font-size: 14px;
}
.btn-outline {
background: transparent;
border: 1px solid var(--primary);
color: var(--primary);
}
.btn-outline:hover {
background: var(--primary);
color: var(--on-primary);
}
.btn-sm {
padding: var(--spacing-xs) var(--spacing-md);
font-size: 14px;
}
/* Responsive */ /* Responsive */
@media (max-width: 480px) { @media (max-width: 480px) {
.login-page { .login-page {
@ -137,6 +168,13 @@
</div> </div>
{% endif %} {% endif %}
{% if show_resend_verification %}
<div class="verification-actions">
<p class="verification-text">Need to resend verification email?</p>
<a href="{% url 'authentication:resend_verification' %}" class="btn btn-outline btn-sm">Resend Verification</a>
</div>
{% endif %}
<form method="post" class="login-form"> <form method="post" class="login-form">
{% csrf_token %} {% csrf_token %}
{% if request.GET.next %} {% if request.GET.next %}
@ -176,7 +214,6 @@
<div class="login-auth-links"> <div class="login-auth-links">
<p><a href="{% url 'authentication:forgot_password' %}">Forgot your password?</a></p> <p><a href="{% url 'authentication:forgot_password' %}">Forgot your password?</a></p>
<p><a href="{% url 'authentication:resend_verification' %}">Resend email verification</a></p>
<p>Don't have an account? <a href="{% url 'authentication:register' %}">Create account</a></p> <p>Don't have an account? <a href="{% url 'authentication:register' %}">Create account</a></p>
</div> </div>
</div> </div>

View File

@ -6,6 +6,35 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Quantum Tasks AI - AI Platform{% endblock %}</title> <title>{% block title %}Quantum Tasks AI - AI Platform{% endblock %}</title>
<!-- SEO Meta Tags -->
<meta name="description" content="{% block description %}Quantum Tasks AI - Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta name="keywords" content="AI, artificial intelligence, automation, AI agents, machine learning, productivity, business tools">
<meta name="author" content="Quantum Tasks AI">
<!-- Open Graph Meta Tags for Rich Link Previews -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="Quantum Tasks AI">
<meta property="og:title" content="{% block og_title %}Quantum Tasks AI - AI Platform{% endblock %}">
<meta property="og:description" content="{% block og_description %}Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta property="og:url" content="{% block og_url %}https://quantumtaskai.com{{ request.get_full_path }}{% endblock %}">
<meta property="og:image" content="{% block og_image %}https://quantumtaskai.com{% static 'img/og-image.png' %}{% endblock %}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="Quantum Tasks AI - AI Agent Marketplace">
<!-- Twitter Card Meta Tags -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@quantumtaskai">
<meta name="twitter:title" content="{% block twitter_title %}Quantum Tasks AI - AI Platform{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}Advanced AI agent marketplace for automation, analysis, and productivity. Access powerful AI tools for business and personal use.{% endblock %}">
<meta name="twitter:image" content="{% block twitter_image %}https://quantumtaskai.com{% static 'img/og-image.png' %}{% endblock %}">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="{% static 'img/favicon.ico' %}">
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'img/apple-touch-icon.png' %}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'img/favicon-32x32.png' %}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'img/favicon-16x16.png' %}">
<!-- Unified Font Loading - Single Source of Truth --> <!-- Unified Font Loading - Single Source of Truth -->
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@ -30,8 +59,8 @@
</a> </a>
<nav class="header-nav" id="header-nav"> <nav class="header-nav" id="header-nav">
<a href="{% url 'core:homepage' %}" class="nav-link {% if request.resolver_match.url_name == 'homepage' %}active{% endif %}">Home</a> <a href="{% url 'core:homepage' %}" class="nav-link {% if request.resolver_match.url_name == 'homepage' %}active{% endif %}">Home</a>
<a href="{% url 'core:digital_branding' %}" class="nav-link {% if request.resolver_match.url_name == 'digital_branding' %}active{% endif %}">AI Digital Branding</a>
<a href="{% url 'agents:marketplace' %}" class="nav-link {% if request.resolver_match.url_name == 'marketplace' %}active{% endif %}">AI Marketplace</a> <a href="{% url 'agents:marketplace' %}" class="nav-link {% if request.resolver_match.url_name == 'marketplace' %}active{% endif %}">AI Marketplace</a>
<a href="{% url 'core:pricing' %}" class="nav-link {% if request.resolver_match.url_name == 'pricing' %}active{% endif %}">Pricing</a>
</nav> </nav>
<button class="mobile-nav-toggle" onclick="toggleMobileNav()" aria-label="Toggle navigation"> <button class="mobile-nav-toggle" onclick="toggleMobileNav()" aria-label="Toggle navigation">

View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Career Navigator - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Career Navigator">
</iframe>
</div>
{% endblock %}

View File

@ -0,0 +1,119 @@
{% if chat_session %}
<div class="agent-widget widget-small" style="min-width: min(280px, 100%); max-width: min(280px, 100%); margin-left: auto;">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">💬</span>
Current Session
</h3>
</div>
<div class="widget-content">
<div class="current-session-info">
<div class="session-status-row">
<span class="status-label">Status:</span>
<span class="session-status status-{{ chat_session.status }}">
{% if chat_session.status == 'active' %}
✅ {{ chat_session.get_status_display }}
{% elif chat_session.status == 'expired' %}
⏰ {{ chat_session.get_status_display }}
{% elif chat_session.status == 'completed' %}
🏁 {{ chat_session.get_status_display }}
{% else %}
{{ chat_session.get_status_display }}
{% endif %}
</span>
</div>
<div class="session-id-row">
<span class="id-label">Session ID:</span>
<span class="session-id">{{ chat_session.session_id }}</span>
</div>
<div class="session-time-row">
<span class="time-label">Started:</span>
<span class="session-time">{{ chat_session.created_at|date:"M d, H:i" }}</span>
</div>
</div>
</div>
</div>
<style>
.current-session-info {
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.session-status-row,
.session-id-row,
.session-time-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--spacing-xs) 0;
border-bottom: 1px solid var(--outline-variant);
}
.session-status-row:last-child,
.session-id-row:last-child,
.session-time-row:last-child {
border-bottom: none;
}
.status-label,
.id-label,
.time-label {
font-size: 13px;
font-weight: 500;
color: var(--on-surface-variant);
}
.session-status {
font-size: 13px;
font-weight: 600;
display: flex;
align-items: center;
gap: 4px;
}
.session-status.status-active {
color: #10b981;
}
.session-status.status-expired {
color: #f59e0b;
}
.session-status.status-completed {
color: #6366f1;
}
.session-id {
font-family: var(--font-mono);
font-size: 11px;
color: var(--on-surface-variant);
background: var(--surface-variant);
padding: 2px 6px;
border-radius: 3px;
word-break: break-all;
}
.session-time {
font-size: 12px;
color: var(--on-surface);
}
@media (max-width: 768px) {
.session-id-row {
flex-direction: column;
align-items: flex-start;
gap: 4px;
}
.session-id {
font-size: 10px;
align-self: stretch;
text-align: center;
}
}
</style>
{% endif %}

View File

@ -0,0 +1,206 @@
{% if previous_sessions %}
<div class="agent-widget widget-small" style="min-width: min(280px, 100%); max-width: min(280px, 100%); margin-left: auto;">
<div class="widget-header">
<h3 class="widget-title">
<span class="widget-icon">📋</span>
Previous Sessions
</h3>
</div>
<div class="widget-content">
{% for session in previous_sessions %}
<div class="session-item">
<div class="session-header">
<div class="session-info">
<span class="session-status status-{{ session.status }}">
{% if session.status == 'completed' %}✅{% elif session.status == 'expired' %}⏰{% elif session.status == 'abandoned' %}❌{% endif %}
{{ session.get_status_display }}
</span>
<span class="session-date">{{ session.created_at|date:"M d" }}</span>
</div>
<div class="session-stats">
<span class="message-count">{{ session.user_message_count }}/{{ session.agent.message_limit }} msgs</span>
</div>
</div>
{% if session.user_message_count > 0 and session.status != 'active' %}
<div class="session-actions">
<div class="download-actions">
<a href="{% url 'agents:export_chat' session.session_id %}?format=pdf"
class="download-link pdf-link"
title="Download PDF">
📄 PDF
</a>
<a href="{% url 'agents:export_chat' session.session_id %}?format=txt"
class="download-link txt-link"
title="Download TXT">
📝 TXT
</a>
</div>
</div>
{% endif %}
</div>
{% endfor %}
{% if previous_sessions|length >= 5 %}
<div class="view-all-sessions">
<a href="#" class="view-all-link" onclick="alert('Full session history coming soon!')">
View All Sessions →
</a>
</div>
{% endif %}
</div>
</div>
<style>
.session-item {
padding: var(--spacing-sm);
border: 1px solid var(--outline-variant);
border-radius: var(--radius-sm);
margin-bottom: var(--spacing-sm);
background: var(--surface);
transition: all 0.2s ease;
}
.session-item:hover {
background: var(--surface-variant);
border-color: var(--primary);
}
.session-item:last-child {
margin-bottom: 0;
}
.session-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: var(--spacing-xs);
}
.session-info {
display: flex;
flex-direction: column;
gap: 2px;
}
.session-status {
font-size: 12px;
font-weight: 600;
display: flex;
align-items: center;
gap: 4px;
}
.session-status.status-completed {
color: var(--success);
}
.session-status.status-expired {
color: var(--warning);
}
.session-status.status-abandoned {
color: var(--error);
}
.session-date {
font-size: 11px;
color: var(--on-surface-variant);
}
.session-stats {
text-align: right;
}
.message-count {
font-size: 11px;
color: var(--on-surface-variant);
background: var(--surface-variant);
padding: 2px 6px;
border-radius: 3px;
}
.session-actions {
border-top: 1px solid var(--outline-variant);
padding-top: var(--spacing-xs);
}
.download-actions {
display: flex;
gap: var(--spacing-sm);
justify-content: center;
}
.download-link {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: var(--primary);
color: white;
text-decoration: none;
border-radius: 4px;
font-size: 11px;
font-weight: 500;
transition: all 0.2s ease;
flex: 1;
justify-content: center;
}
.download-link:hover {
background: var(--primary-dark);
transform: translateY(-1px);
color: white;
text-decoration: none;
}
.download-link.pdf-link {
background: #dc2626;
}
.download-link.pdf-link:hover {
background: #b91c1c;
}
.download-link.txt-link {
background: var(--primary);
}
.download-link.txt-link:hover {
background: var(--primary-dark);
}
.view-all-sessions {
margin-top: var(--spacing-sm);
text-align: center;
border-top: 1px solid var(--outline-variant);
padding-top: var(--spacing-sm);
}
.view-all-link {
font-size: 12px;
color: var(--primary);
text-decoration: none;
font-weight: 500;
}
.view-all-link:hover {
text-decoration: underline;
}
@media (max-width: 768px) {
.session-header {
flex-direction: column;
gap: var(--spacing-xs);
}
.session-stats {
text-align: left;
}
.download-actions {
flex-direction: column;
}
}
</style>
{% endif %}

View File

@ -7,29 +7,23 @@
</div> </div>
<div class="quick-agents-grid"> <div class="quick-agents-grid">
<a href="/agents/social-ads-generator/" class="quick-agent-card"> {% for agent in all_agents %}
<div class="agent-icon">📢</div> {% if agent.slug == 'cybersec-career-navigator' %}
<div class="agent-info"> <a href="{% url 'agents:career_navigator_access' %}" class="quick-agent-card">
<h4>Social Ads Generator</h4> {% else %}
<p>Create social media ads</p> <a href="{% url 'agents:detail' agent.slug %}" class="quick-agent-card">
</div> {% endif %}
</a> <div class="agent-icon">{{ agent.category.icon }}</div>
<div class="agent-info">
<a href="/agents/job-posting-generator/" class="quick-agent-card"> <h4>{{ agent.name }}</h4>
<div class="agent-icon">💼</div> <div class="agent-price">{{ agent.price }} AED</div>
<div class="agent-info"> </div>
<h4>Job Posting Generator</h4> </a>
<p>Create professional job posts</p> {% empty %}
</div> <p style="text-align: center; color: var(--on-surface-variant); padding: 20px;">
</a> No other agents available
</p>
<a href="/agents/pdf-summarizer/" class="quick-agent-card"> {% endfor %}
<div class="agent-icon">📄</div>
<div class="agent-info">
<h4>PDF Summarizer</h4>
<p>Analyze and summarize PDFs</p>
</div>
</a>
</div> </div>
<div class="quick-agents-footer"> <div class="quick-agents-footer">

View File

@ -0,0 +1,200 @@
{% if chat_session and messages %}
<div class="session-indicators">
<h4 class="session-indicators-title">Session Status</h4>
<!-- Time Remaining Indicator -->
<div class="indicator-item">
<div class="indicator-header">
<span class="indicator-icon"></span>
<span class="indicator-label">Time Remaining</span>
<span class="indicator-value" id="timeRemaining">
{% if time_remaining %}
{{ time_remaining }}
{% else %}
Calculating...
{% endif %}
</span>
</div>
<div class="progress-bar">
<div class="progress-fill time-progress" id="timeProgress" style="width: {{ time_percentage|default:100 }}%"></div>
</div>
</div>
<!-- Messages Remaining Indicator -->
<div class="indicator-item">
<div class="indicator-header">
<span class="indicator-icon">💬</span>
<span class="indicator-label">Messages</span>
<span class="indicator-value" id="messageCount">
{{ message_count|default:0 }}/{{ message_limit }} used
</span>
</div>
<div class="progress-bar">
<div class="progress-fill message-progress" id="messageProgress" style="width: {{ message_percentage|default:0 }}%"></div>
</div>
</div>
<!-- Warning Messages -->
<div class="session-warnings" id="sessionWarnings">
{% if time_percentage <= 20 %}
<div class="warning-item time-warning">
⚠️ Session expires soon!
</div>
{% endif %}
{% if message_percentage >= 80 %}
<div class="warning-item message-warning">
⚠️ Approaching message limit!
</div>
{% endif %}
</div>
</div>
<style>
.session-indicators {
background: var(--surface);
border: 1px solid var(--outline-variant);
border-radius: var(--radius-lg);
padding: var(--spacing-lg);
margin-bottom: var(--spacing-md);
box-shadow: var(--shadow-sm);
min-width: min(280px, 100%);
max-width: min(280px, 100%);
margin-left: auto;
}
.session-indicators-title {
font-size: 16px;
font-weight: 600;
color: var(--on-surface);
margin: 0 0 var(--spacing-md) 0;
display: flex;
align-items: center;
gap: var(--spacing-sm);
}
.indicator-item {
margin-bottom: var(--spacing-md);
}
.indicator-item:last-of-type {
margin-bottom: 0;
}
.indicator-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: var(--spacing-xs);
}
.indicator-icon {
font-size: 16px;
}
.indicator-label {
font-size: 14px;
font-weight: 500;
color: var(--on-surface);
flex: 1;
margin-left: var(--spacing-sm);
}
.indicator-value {
font-size: 13px;
font-weight: 600;
color: var(--on-surface-variant);
}
.progress-bar {
width: 100%;
height: 6px;
background: var(--surface-variant);
border-radius: 3px;
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: 3px;
transition: width 0.3s ease, background-color 0.3s ease;
}
.time-progress {
background: linear-gradient(90deg, #10b981, #059669);
}
.time-progress[style*="width: 0"],
.time-progress[style*="width: 1"],
.time-progress[style*="width: 2"] {
background: linear-gradient(90deg, #ef4444, #dc2626);
}
.time-progress[style*="width: 3"],
.time-progress[style*="width: 4"],
.time-progress[style*="width: 5"],
.time-progress[style*="width: 10"],
.time-progress[style*="width: 15"],
.time-progress[style*="width: 20"] {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.message-progress {
background: linear-gradient(90deg, #3b82f6, #2563eb);
}
.message-progress[style*="width: 8"],
.message-progress[style*="width: 9"] {
background: linear-gradient(90deg, #f59e0b, #d97706);
}
.message-progress[style*="width: 95"],
.message-progress[style*="width: 96"],
.message-progress[style*="width: 97"],
.message-progress[style*="width: 98"],
.message-progress[style*="width: 99"],
.message-progress[style*="width: 100"] {
background: linear-gradient(90deg, #ef4444, #dc2626);
}
.session-warnings {
margin-top: var(--spacing-md);
}
.warning-item {
background: #fef3c7;
color: #92400e;
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--radius-sm);
font-size: 13px;
font-weight: 500;
margin-bottom: var(--spacing-xs);
border-left: 3px solid #f59e0b;
}
.warning-item:last-child {
margin-bottom: 0;
}
.time-warning {
background: #fee2e2;
color: #991b1b;
border-left-color: #ef4444;
}
@media (max-width: 768px) {
.session-indicators {
padding: var(--spacing-md);
}
.indicator-header {
flex-wrap: wrap;
gap: var(--spacing-xs);
}
.indicator-value {
flex-basis: 100%;
text-align: right;
}
}
</style>
{% endif %}

View File

@ -0,0 +1,523 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}AI Digital Branding Services - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{% static 'css/digital-branding.css' %}">
{% endblock %}
{% block content %}
<style>
/* Override main-container for full-width sections */
.main-container {
max-width: none;
padding: 0;
}
</style>
<!-- Hero Section -->
<section id="digital-branding-hero" class="digital-branding-hero">
<div class="hero-container">
<!-- Trust Badge -->
<div class="trust-badge">
<span class="trust-badge-emoji"></span>
<span>Trusted Digital Brand Partner</span>
</div>
<h1 class="hero-title">
<span class="hero-title-gradient">
AI-Powered Digital Branding
</span>
<br />
<span class="hero-title-normal">
Intelligence
</span>
</h1>
<p class="hero-description">
Elevate Your Brand with Intelligent Digital Strategies. Combine proven marketing expertise with AI automation to accelerate growth, optimize performance, and deliver measurable results that matter.
</p>
<!-- CTA Buttons -->
<div class="hero-buttons">
{% if user.is_authenticated %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Start Discovery
</a>
<a href="#our-process" class="btn-secondary">
View Process
</a>
{% else %}
<a href="https://form.jotform.com/252121444918050" target="_blank" class="btn-primary">
Get Started
</a>
<a href="#our-process" class="btn-secondary">
Learn More
</a>
{% endif %}
</div>
<!-- Trust Indicators -->
<div class="trust-indicators">
<div class="trust-card">
<div class="trust-number">
250%
</div>
<div class="trust-text">
Average ROI Increase
</div>
</div>
<div class="trust-card">
<div class="trust-number">
3x
</div>
<div class="trust-text">
Faster Content Creation
</div>
</div>
<div class="trust-card">
<div class="trust-number">
24/7
</div>
<div class="trust-text">
Performance Monitoring
</div>
</div>
</div>
</div>
</section>
<!-- Why Choose Us Section -->
<section id="why-choose-us" class="why-choose-us">
<div class="section-container">
<!-- Section Header -->
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">🎯</span>
<span class="section-badge-text">Why Choose Us</span>
</div>
<h2 class="section-title">
Intelligent Digital Excellence
</h2>
<p class="section-subtitle">
Combine proven digital strategies with smart automation and data insights to accelerate your brand's growth and market impact
</p>
</div>
<div class="why-choose-grid">
<div class="choice-card">
<div class="choice-icon">🤖</div>
<h3 class="choice-title">Data-Driven Brand Intelligence</h3>
<p class="choice-description">
Advanced analytics and automation for real-time audience insights, trend forecasting, and competitive intelligence. Our smart systems continuously optimize your strategy based on performance data.
</p>
</div>
<div class="choice-card">
<div class="choice-icon">🌐</div>
<h3 class="choice-title">Comprehensive Digital Automation</h3>
<p class="choice-description">
End-to-end digital presence management with smart automation, content optimization, intelligent scheduling, SEO enhancement, and reputation management for maximum efficiency and impact.
</p>
</div>
<div class="choice-card">
<div class="choice-icon"></div>
<h3 class="choice-title">Smart Personalization & Optimization</h3>
<p class="choice-description">
Intelligent systems that learn your brand identity, automatically adapt strategies for your market, and continuously optimize campaigns based on performance data and market insights.
</p>
</div>
</div>
</div>
</section>
<!-- Our Process Section -->
<section id="our-process" class="our-process">
<div class="section-container">
<div class="section-header">
<div class="section-badge">
<span class="section-badge-icon">📋</span>
<span class="section-badge-text">Our Process</span>
</div>
<h2 class="section-title">
AI-Enhanced SOSTAC+RACE Framework
</h2>
<p class="section-subtitle">
Our proven methodology supercharged with artificial intelligence, machine learning insights, and automated optimization at every stage
</p>
</div>
<div class="process-grid">
<div class="process-step-card">
<div class="step-number">1</div>
<div class="step-content">
<h3 class="step-title">AI-Powered Situation Analysis</h3>
<p class="step-description">
Deploy machine learning algorithms to analyze your brand's digital DNA, competitive intelligence automation, and predictive market positioning with real-time data insights.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">2</div>
<div class="step-content">
<h3 class="step-title">AI-Optimized Objectives</h3>
<p class="step-description">
Generate data-driven SMART goals using predictive analytics, automated KPI tracking, and AI-powered performance forecasting with continuous goal optimization.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">3</div>
<div class="step-content">
<h3 class="step-title">Intelligent Strategy Design</h3>
<p class="step-description">
AI-driven customer journey mapping, automated audience segmentation, dynamic value proposition testing, and intelligent channel selection with performance optimization.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">4</div>
<div class="step-content">
<h3 class="step-title">AI-Automated Tactics (RACE Framework)</h3>
<p class="step-description">
Deploy intelligent automation for Reach (AI-powered visibility), Act (automated engagement), Convert (smart sales funnels), and Engage (AI-driven loyalty programs).
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">5</div>
<div class="step-content">
<h3 class="step-title">Automated Action Execution</h3>
<p class="step-description">
AI-powered task automation, intelligent timeline management, and automated brand asset generation with smart content creation and deployment systems.
</p>
</div>
</div>
<div class="process-step-card">
<div class="step-number">6</div>
<div class="step-content">
<h3 class="step-title">Intelligent Control & Optimization</h3>
<p class="step-description">
Real-time AI monitoring, predictive KPI analysis, automated strategy refinement, and continuous machine learning optimization with performance forecasting.
</p>
</div>
</div>
</div>
<!-- RACE Framework Details -->
<div class="race-framework">
<h3 class="race-title">RACE Framework Breakdown</h3>
<div class="race-grid">
<div class="race-card">
<div class="race-phase">
<span class="race-icon">📢</span>
<h4>Reach</h4>
</div>
<div class="race-focus">AI-Powered Visibility</div>
<div class="race-actions">Automated LLM optimization, AI-driven SEO, smart ad targeting, AI influencer matching, automated PR distribution</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">💬</span>
<h4>Act</h4>
</div>
<div class="race-focus">Intelligent Engagement</div>
<div class="race-actions">AI content generation, dynamic landing pages, chatbot interactions, automated social responses</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">🎯</span>
<h4>Convert</h4>
</div>
<div class="race-focus">Smart Conversions</div>
<div class="race-actions">AI-optimized CTAs, predictive retargeting, automated lead scoring, intelligent funnel optimization</div>
</div>
<div class="race-card">
<div class="race-phase">
<span class="race-icon">❤️</span>
<h4>Engage</h4>
</div>
<div class="race-focus">AI-Driven Loyalty</div>
<div class="race-actions">Automated email personalization, AI community management, predictive advocacy, smart retention campaigns</div>
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section id="services" class="branding-services">
<div class="section-container">
<h2 class="services-title">
AI-Powered Service Portfolio
</h2>
<p class="services-subtitle">
Advanced artificial intelligence solutions that automate, optimize, and accelerate your digital brand transformation
</p>
<div class="branding-services-grid">
<div class="service-card">
<div class="service-icon">🎨</div>
<h3 class="service-title">Brand Discovery & Smart Identity Design</h3>
<p class="service-description">
Complete brand audit enhanced with AI insights, strategic identity creation, and adaptive design systems that evolve with market trends and audience data.
</p>
</div>
<div class="service-card">
<div class="service-icon">📱</div>
<h3 class="service-title">Strategic Platform Management & Automation</h3>
<p class="service-description">
Smart platform selection and optimization, automated content distribution, intelligent scheduling, and performance optimization across social media, websites, and digital touchpoints.
</p>
</div>
<div class="service-card">
<div class="service-icon">🔍</div>
<h3 class="service-title">Advanced Content & Marketing Automation</h3>
<p class="service-description">
AI-enhanced content creation, automated SEO optimization, intelligent ad targeting and social media management with real-time performance adjustments for maximum impact.
</p>
</div>
<div class="service-card">
<div class="service-icon">📢</div>
<h3 class="service-title">Influencer Partnerships & Digital PR</h3>
<p class="service-description">
Strategic influencer discovery and matching, automated PR campaign management, smart media outreach, and comprehensive relationship management for maximum brand amplification.
</p>
</div>
<div class="service-card">
<div class="service-icon">🎯</div>
<h3 class="service-title">Brand Consistency & Messaging Systems</h3>
<p class="service-description">
Unified brand guidelines with automated enforcement, intelligent messaging frameworks, smart visual asset management, and consistent brand voice across all platforms.
</p>
</div>
<div class="service-card">
<div class="service-icon">📊</div>
<h3 class="service-title">Predictive AI Analytics & Automated Insights</h3>
<p class="service-description">
Real-time predictive analytics, automated performance optimization, AI-generated insights and recommendations, with intelligent forecasting and proactive strategy adjustments.
</p>
</div>
</div>
</div>
</section>
<!-- CTA Section -->
<section id="discovery-form" class="branding-cta">
<div class="cta-container">
<h2 class="cta-title">
Accelerate Your Digital Brand Growth
</h2>
<div class="cta-grid">
<!-- CTA Content -->
<div class="cta-content">
<h3 class="cta-content-title">Ready to transform your digital brand presence?</h3>
<p class="cta-description">
Complete our Digital Brand Strategy Assessment and receive a customized growth roadmap with smart automation recommendations within 24 hours.
</p>
<!-- Features List -->
<div class="cta-features">
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Free comprehensive brand analysis</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Personalized growth automation roadmap</span>
</div>
<div class="cta-feature">
<span class="feature-icon"></span>
<span>Custom strategy proposal in 24 hours</span>
</div>
</div>
<!-- CTA Buttons -->
<div class="cta-buttons">
<!-- <a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn primary">
🚀 Get Discovery Questionnaire
</a> -->
<a href="https://form.jotform.com/252121444918050" target="_blank" class="cta-btn secondary">
💬 Contact Us Directly
</a>
</div>
</div>
<!-- Contact Information -->
<div class="cta-info">
<h3 class="cta-info-title">Get in Touch</h3>
<!-- Contact Item -->
<div class="contact-item">
<div class="contact-icon">
✉️
</div>
<div class="contact-details">
<h4>Email Address</h4>
<p>
<a href="mailto:abhay@quantumtaskai.com" class="contact-email">
abhay@quantumtaskai.com
</a>
</p>
</div>
</div>
<!-- Commitment Statement -->
<div class="commitment-statement">
<p class="commitment-text">
Leading the AI Revolution in Digital Branding - Where Artificial Intelligence Meets Brand Excellence for Unprecedented Growth and Automation.
</p>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
{% block extra_js %}
<script>
class DigitalBrandingManager {
constructor() {
this.processCards = document.querySelectorAll('.process-step-card');
this.raceCards = document.querySelectorAll('.race-card');
this.serviceCards = document.querySelectorAll('.service-card');
this.ctaButtons = document.querySelectorAll('.cta-btn');
this.init();
}
init() {
this.setupCardInteractions();
this.setupButtonHovers();
this.addScrollAnimations();
this.setupSmoothScrolling();
}
setupCardInteractions() {
// Process step cards
this.processCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// RACE framework cards
this.raceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
// Service cards
this.serviceCards.forEach(card => {
card.addEventListener('mouseenter', () => {
this.highlightCard(card);
});
card.addEventListener('mouseleave', () => {
this.removeHighlight(card);
});
});
}
highlightCard(card) {
card.style.transform = 'translateY(-4px)';
card.style.boxShadow = '0 20px 40px rgba(30, 64, 175, 0.15)';
}
removeHighlight(card) {
card.style.transform = 'translateY(0)';
card.style.boxShadow = '';
}
setupButtonHovers() {
this.ctaButtons.forEach(button => {
button.addEventListener('mouseenter', () => {
button.style.transform = 'translateY(-2px)';
});
button.addEventListener('mouseleave', () => {
button.style.transform = '';
});
button.addEventListener('click', () => {
if (!button.classList.contains('loading')) {
button.classList.add('loading');
const originalText = button.textContent;
button.textContent = '⏳ Loading...';
setTimeout(() => {
if (button.classList.contains('loading')) {
button.classList.remove('loading');
button.textContent = originalText;
}
}, 2000);
}
});
});
}
addScrollAnimations() {
if ('IntersectionObserver' in window) {
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe cards for scroll animations
[...this.processCards, ...this.raceCards, ...this.serviceCards].forEach((card, index) => {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = `opacity 0.6s ease ${index * 0.1}s, transform 0.6s ease ${index * 0.1}s`;
observer.observe(card);
});
// Observe sections
document.querySelectorAll('.section-header, .cta-content').forEach(section => {
section.style.opacity = '0';
section.style.transform = 'translateY(20px)';
section.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(section);
});
}
}
setupSmoothScrolling() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
new DigitalBrandingManager();
});
</script>
{% endblock %}

43
templates/core/event.html Normal file
View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Event - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Event">
</iframe>
</div>
{% endblock %}

View File

@ -3,6 +3,11 @@
{% block title %}Quantum Tasks AI - AI & Task Automation Solutions{% endblock %} {% block title %}Quantum Tasks AI - AI & Task Automation Solutions{% endblock %}
{% block description %}Discover powerful AI agents for automation, analysis, and productivity. Access premium AI tools for social media, business analysis, document processing, and more.{% endblock %}
{% block og_title %}Quantum Tasks AI - AI & Task Automation Solutions{% endblock %}
{% block og_description %}Discover powerful AI agents for automation, analysis, and productivity. Access premium AI tools for social media, business analysis, document processing, and more.{% endblock %}
{% block extra_css %} {% block extra_css %}
<link rel="stylesheet" href="{% static 'css/homepage.css' %}"> <link rel="stylesheet" href="{% static 'css/homepage.css' %}">
{% endblock %} {% endblock %}

View File

@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Lean Six Sigma Expert - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
/* Override main-container for full-width iframe */
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px); /* Account for header height */
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
/* Hide footer for this page */
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="Lean Six Sigma Expert">
</iframe>
</div>
{% endblock %}

View File

@ -0,0 +1,38 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}SWOT Analysis Expert - Quantum Tasks AI{% endblock %}
{% block extra_css %}
<style>
.main-container {
max-width: none;
padding: 0;
height: calc(100vh - 80px);
}
.iframe-container {
width: 100%;
height: 100%;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
display: block;
}
.footer {
display: none !important;
}
</style>
{% endblock %}
{% block content %}
<div class="iframe-container">
<iframe
src="{{ form_url }}"
frameborder="0"
scrolling="auto"
title="SWOT Analysis Expert">
</iframe>
</div>
{% endblock %}

View File

@ -79,16 +79,22 @@ def wallet_topup_view(request):
return redirect('wallet:wallet_topup') return redirect('wallet:wallet_topup')
except Exception as e: except Exception as e:
logger.error(f"Checkout session creation failed for user {request.user.id}: {e}") logger.error(f"Checkout session creation failed for user {request.user.id}: {e}")
messages.error(request, 'Unable to process payment at this time. Please try again.') messages.error(request, 'Payment failed. Try again.')
return redirect('wallet:wallet_topup') return redirect('wallet:wallet_topup')
return render(request, 'wallet/wallet_topup.html') return render(request, 'wallet/wallet_topup.html')
@login_required
@ratelimit(key='user', rate='10/m', method='GET', block=False) @ratelimit(key='user', rate='10/m', method='GET', block=False)
def wallet_topup_success_view(request): def wallet_topup_success_view(request):
"""Payment success page with automatic payment verification""" """Payment success page with automatic payment verification"""
# Check authentication first and clear any messages if redirecting to login
if not request.user.is_authenticated:
# Clear any existing messages to prevent them from showing on login page
storage = messages.get_messages(request)
storage.used = True
return redirect('authentication:login')
# Check if rate limited # Check if rate limited
if getattr(request, 'limited', False): if getattr(request, 'limited', False):
logger.warning(f"Payment success page rate limit exceeded for user {request.user.id}") logger.warning(f"Payment success page rate limit exceeded for user {request.user.id}")
@ -99,7 +105,7 @@ def wallet_topup_success_view(request):
if not session_id: if not session_id:
logger.warning(f"No session ID provided for user {request.user.id}") logger.warning(f"No session ID provided for user {request.user.id}")
messages.error(request, 'No payment session found. Please contact support if you completed a payment.') messages.error(request, 'Payment session not found.')
return redirect('wallet:wallet') return redirect('wallet:wallet')
# Verify payment directly with Stripe API # Verify payment directly with Stripe API
@ -111,10 +117,10 @@ def wallet_topup_success_view(request):
if result['success']: if result['success']:
if result['processed']: if result['processed']:
messages.success(request, f'Payment successful! {result["amount"]} AED has been added to your wallet.') messages.success(request, f'{result["amount"]} AED added to wallet.')
logger.info(f"Payment verified and wallet updated for user {request.user.id}") logger.info(f"Payment verified and wallet updated for user {request.user.id}")
else: else:
messages.info(request, 'Payment already processed. Your wallet balance is up to date.') messages.info(request, 'Payment already processed.')
logger.info(f"Payment already processed for session {session_id}") logger.info(f"Payment already processed for session {session_id}")
else: else:
messages.warning(request, 'Payment verification failed. Please contact support.') messages.warning(request, 'Payment verification failed. Please contact support.')
@ -122,15 +128,21 @@ def wallet_topup_success_view(request):
except Exception as e: except Exception as e:
logger.error(f"Error verifying payment for user {request.user.id}: {e}") logger.error(f"Error verifying payment for user {request.user.id}: {e}")
messages.error(request, 'Unable to verify payment. Please contact support if you completed a payment.') messages.error(request, 'Payment verification failed.')
return redirect('wallet:wallet') return redirect('wallet:wallet')
@login_required
def wallet_topup_cancel_view(request): def wallet_topup_cancel_view(request):
"""Payment cancel page""" """Payment cancel page"""
messages.info(request, 'Payment was cancelled. No charges were made.') # Check authentication first and clear any messages if redirecting to login
if not request.user.is_authenticated:
# Clear any existing messages to prevent them from showing on login page
storage = messages.get_messages(request)
storage.used = True
return redirect('authentication:login')
messages.info(request, 'Payment cancelled.')
return redirect('wallet:wallet_topup') return redirect('wallet:wallet_topup')