diff --git a/CLAUDE.md b/CLAUDE.md index c13a10b..1c50cfb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,13 +4,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## 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:** - **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 -- **Payments**: Stripe integration with wallet system +- **Payments**: Stripe integration with wallet system (supports free agents) - **Database**: SQLite for development, PostgreSQL for production (Railway) - **Static Files**: WhiteNoise for production static file serving @@ -101,17 +103,27 @@ gunicorn netcop_hub.wsgi:application ### Agent System (agents app) **Key Files:** -- `agents/models.py`: Agent, AgentCategory, AgentExecution models -- `agents/views.py`: REST API and web interface views -- `agents/templates/agents/`: Dynamic agent templates with form generation +- `agents/models.py`: Agent, AgentCategory, AgentExecution, ChatSession models +- `agents/views.py`: Dual integration systems and web interface views +- `agents/templates/agents/`: Dynamic agent templates and marketplace - `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/`) -2. Selects agent and fills dynamic form (`/agents/{slug}/`) -3. Form submission creates AgentExecution and calls N8N webhook -4. N8N processes request and returns response via webhook -5. Results displayed with file upload support and real-time wallet updates +2. Clicks "Try Now" → Agent detail page (`/agents/{slug}/`) +3. Fills dynamic form → Form submission calls `/agents/api/execute/` +4. N8N webhook processes request and returns response +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 **User Management:** @@ -136,9 +148,10 @@ gunicorn netcop_hub.wsgi:application - `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`: Stripe API keys - `DATABASE_URL`: PostgreSQL connection string (Railway) -**N8N Webhook URLs:** -Agent-specific webhook URLs are stored in the database with each agent. Current working agents (all tested and confirmed working): +**Current Agents:** +The platform supports both webhook-based agents (N8N integration) and direct access agents (embedded forms): +**Webhook Agents (N8N Integration):** 1. **Social Ads Generator** (social-ads-generator) - 6.00 AED - Creates compelling social media advertisements - Form fields: description, social_platform, include_emoji, language @@ -154,12 +167,27 @@ Agent-specific webhook URLs are stored in the database with each agent. Current - Form fields: pdf_file (file upload with drag-and-drop), summary_type - Webhook: N8N endpoint for PDF processing with multipart file support +4. **5 Whys Analyzer** (5-whys-analyzer) - 15.00 AED + - Interactive chat-based root cause analysis using 5 Whys methodology + - Chat interface with real-time N8N webhook integration + - Session timeout: 2 hours + +**Direct Access Agents (Embedded Forms):** +5. **CyberSec Career Navigator** (cybersec-career-navigator) - 0.00 AED + - JotForm-based career guidance consultation + - Embedded white-label interface + - Session duration: 2 hours + - Direct access URL: `/agents/career-navigator/` + ### URL Structure ``` / # Homepage (core app) +/digital-branding/ # Digital branding services page /auth/ # Authentication (login, register, etc.) /agents/ # Agent marketplace (agents app) -/agents/{slug}/ # Individual agent pages +/agents/{slug}/ # Individual agent pages (webhook agents) +/agents/career-navigator/ # Career navigator form page +/agents/career-navigator/access/ # Career navigator payment processing /wallet/ # Wallet management /admin/ # Django admin ``` @@ -271,17 +299,20 @@ class Command(BaseCommand): ## System Status **Current Status: ✅ STABLE WORKING SYSTEM** -- All 3 agents confirmed working and tested -- Clean agents-only architecture (workflows app completely removed) -- Emergency recovery completed from optimization failures -- System restored to stable commit 657712f +- All 5 agents confirmed working and tested (4 webhook + 1 direct access) +- Dual integration architecture with clean separation +- Digital branding services integration complete +- Chat-based and form-based agent systems operational +- White-label integration patterns established **Latest Changes:** -- Removed workflows app completely for simplified architecture -- Enhanced agent marketplace with modern responsive design -- Fixed all authentication-aware UI components -- Implemented file upload support for PDF Summarizer -- Real-time wallet balance updates after agent execution +- Implemented dual integration architecture (webhook + direct access) +- Added CyberSec Career Navigator with JotForm integration +- Enhanced agent marketplace with conditional button logic +- Added digital branding services page +- Cleaned up unused form API endpoints +- Implemented 2-hour session timeout system +- Fixed persistent success messages and UI consistency **Future Development:** - Optimization work available in feature/optimization-backup branch @@ -289,4 +320,4 @@ class Command(BaseCommand): - Performance optimizations should be applied incrementally with testing --- -Last updated: Last updated: Last updated: Last updated: Last updated: 2025-08-01 09:22:55 +Last updated: 2025-08-02 12:30:00 diff --git a/agents/management/commands/create_cybersec_career_agent.py b/agents/management/commands/create_cybersec_career_agent.py new file mode 100644 index 0000000..4b11e11 --- /dev/null +++ b/agents/management/commands/create_cybersec_career_agent.py @@ -0,0 +1,58 @@ +from django.core.management.base import BaseCommand +from agents.models import AgentCategory, Agent + +class Command(BaseCommand): + help = 'Create CyberSec Career Navigator agent with JotForm integration' + + def handle(self, *args, **options): + # Create Career & Education category + career_category, created = AgentCategory.objects.get_or_create( + slug='career-education', + defaults={ + 'name': 'Career & Education', + 'description': 'Professional career guidance and educational resources', + 'icon': '🎓' + } + ) + + if created: + self.stdout.write(self.style.SUCCESS(f'Created category: {career_category.name}')) + else: + self.stdout.write(f'Category already exists: {career_category.name}') + + # Create CyberSec Career Navigator agent + cybersec_agent, created = Agent.objects.get_or_create( + slug='cybersec-career-navigator', + defaults={ + '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. Whether you\'re starting out, changing careers, or advancing in cybersecurity, get personalized advice on certifications, job roles, skills development, and career progression. Jessica, your AI career consultant, provides tailored recommendations based on your experience level and goals.', + 'category': career_category, + 'price': 12.0, + 'agent_type': 'form', + 'form_schema': { + 'fields': [] # Empty since we're using JotForm directly + }, + 'webhook_url': 'https://agent.jotform.com/019865a942ab7fa5b5b743a5fd2abe09e345' + } + ) + + if created: + self.stdout.write(self.style.SUCCESS(f'Created agent: {cybersec_agent.name}')) + self.stdout.write(f' 📝 Description: {cybersec_agent.short_description}') + self.stdout.write(f' 💰 Price: {cybersec_agent.price} AED') + self.stdout.write(f' 🔗 JotForm URL: {cybersec_agent.webhook_url}') + self.stdout.write(f' 📂 Category: {cybersec_agent.category.name}') + else: + self.stdout.write(f'Agent already exists: {cybersec_agent.name}') + + self.stdout.write('') + self.stdout.write(self.style.SUCCESS('✅ CyberSec Career Navigator setup completed successfully')) + self.stdout.write('') + self.stdout.write('🚀 Next steps:') + self.stdout.write(' 1. Agent will appear in the Career & Education category') + self.stdout.write(' 2. Users will pay 12 AED and get direct access to JotForm interface') + self.stdout.write(' 3. Visit /agents/cybersec-career-navigator/ to test the interface') + self.stdout.write('') + self.stdout.write(f'Agent ID: {cybersec_agent.id}') + self.stdout.write(f'Agent Slug: {cybersec_agent.slug}') \ No newline at end of file diff --git a/agents/templates/agents/marketplace.html b/agents/templates/agents/marketplace.html index a1303fd..a2a42e5 100644 --- a/agents/templates/agents/marketplace.html +++ b/agents/templates/agents/marketplace.html @@ -6,6 +6,25 @@ {% block extra_css %} + {% endblock %} {% block content %} @@ -72,12 +91,23 @@
{{ agent.short_description }}
diff --git a/agents/urls.py b/agents/urls.py index 3a46bf5..d1e055b 100644 --- a/agents/urls.py +++ b/agents/urls.py @@ -7,6 +7,10 @@ urlpatterns = [ # Web interface 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'), + # API endpoints - specific URLs first to avoid slug conflicts path('api/execute/', views.execute_agent, name='execute_agent'), path('api/executions/', views.execution_list, name='execution_list'), diff --git a/agents/views.py b/agents/views.py index 0335091..9800eda 100644 --- a/agents/views.py +++ b/agents/views.py @@ -3,9 +3,10 @@ from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.pagination import PageNumberPagination -from django.shortcuts import get_object_or_404, render +from django.shortcuts import get_object_or_404, render, redirect from django.utils import timezone from django.contrib.auth.decorators import login_required +from django.contrib import messages from django.db import models from .models import Agent, AgentExecution, AgentCategory, ChatSession, ChatMessage from .serializers import AgentSerializer, AgentExecutionSerializer @@ -184,6 +185,100 @@ def execute_agent(request): 'execution_id': str(execution.id) }, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + +def career_navigator_access(request): + """Handle Try Now button click - charge wallet and redirect to form""" + if not request.user.is_authenticated: + # Clear any existing messages to prevent confusion + storage = messages.get_messages(request) + storage.used = True + messages.error(request, 'Please login to access the Career Navigator.') + return redirect('authentication:login') + + # Get the career navigator agent + try: + agent = Agent.objects.get(slug='cybersec-career-navigator', is_active=True) + except Agent.DoesNotExist: + messages.error(request, 'Career Navigator is currently unavailable.') + return redirect('agents:marketplace') + + # Check if user has sufficient balance + if not request.user.has_sufficient_balance(agent.price): + messages.error(request, f'Insufficient balance! You need {agent.price} AED to access the Career Navigator.') + return redirect('wallet:wallet') + + # Deduct fee from user wallet + success = request.user.deduct_balance( + agent.price, + f'{agent.name} - Direct Access', + agent.slug + ) + + if not success: + messages.error(request, 'Failed to process payment. Please try again.') + return redirect('agents:marketplace') + + # Create execution record for tracking + execution = AgentExecution.objects.create( + agent=agent, + user=request.user, + input_data={'action': 'direct_access', 'source': 'try_now_button'}, + fee_charged=agent.price, + status='completed', + output_data={ + 'type': 'direct_access', + 'message': f'Direct access granted to {agent.name}', + 'access_method': 'try_now_button' + }, + completed_at=timezone.now() + ) + + # Success message and redirect to form + messages.success(request, f'✅ Payment processed! Welcome to your {agent.name} consultation.') + return redirect('agents:career_navigator') + + +def career_navigator_view(request): + """Display the career navigator form page""" + if not request.user.is_authenticated: + # Clear any existing messages to prevent confusion + storage = messages.get_messages(request) + storage.used = True + messages.error(request, 'Please login to access the Career Navigator.') + return redirect('authentication:login') + + # Get the career navigator agent + try: + agent = Agent.objects.get(slug='cybersec-career-navigator', is_active=True) + except Agent.DoesNotExist: + messages.error(request, 'Career Navigator is currently unavailable.') + return redirect('agents:marketplace') + + # Check if user has a recent execution (within last 2 hours) or just redirect to payment + from django.utils import timezone + from datetime import timedelta + + recent_execution = AgentExecution.objects.filter( + agent=agent, + user=request.user, + status='completed', + created_at__gte=timezone.now() - timedelta(hours=2) + ).first() + + if not recent_execution: + messages.info(request, 'Please click "Try Now" to access your Career Navigator consultation.') + return redirect('agents:marketplace') + + context = { + 'agent': agent, + 'form_url': agent.webhook_url, + 'user_balance': request.user.wallet_balance, + 'execution': recent_execution + } + + return render(request, 'career_navigator.html', context) + + @api_view(['GET']) @permission_classes([IsAuthenticated]) def execution_list(request): diff --git a/core/urls.py b/core/urls.py index e4eb6ee..dce4432 100644 --- a/core/urls.py +++ b/core/urls.py @@ -5,6 +5,7 @@ app_name = 'core' urlpatterns = [ path('', views.homepage_view, name='homepage'), + path('digital-branding/', views.digital_branding_view, name='digital_branding'), path('pricing/', views.pricing_view, name='pricing'), path('contact/', views.contact_form_view, name='contact_form'), path('health/', views.health_check_view, name='health_check'), diff --git a/core/views.py b/core/views.py index 040ef91..7be5a9f 100644 --- a/core/views.py +++ b/core/views.py @@ -65,6 +65,27 @@ def pricing_view(request): return render(request, 'core/pricing.html', {'sample_agents': []}) +@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 + if getattr(request, 'limited', False): + 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.') + + try: + context = { + 'user_balance': request.user.wallet_balance if request.user.is_authenticated else 0, + } + + return render(request, 'core/digital_branding.html', context) + + except Exception as e: + logger.error(f"Digital branding view error: {e}") + messages.error(request, 'Unable to load digital branding page. Please try again.') + return render(request, 'core/digital_branding.html', {}) + + def validate_contact_input(name, email, message, company=""): """Validate and sanitize contact form input""" errors = [] diff --git a/static/css/digital-branding.css b/static/css/digital-branding.css new file mode 100644 index 0000000..5ff6f2a --- /dev/null +++ b/static/css/digital-branding.css @@ -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; + } +} \ No newline at end of file diff --git a/static/js/agents-core.js b/static/js/agents-core.js index 6ba993d..225a10f 100644 --- a/static/js/agents-core.js +++ b/static/js/agents-core.js @@ -478,6 +478,109 @@ class AgentsCore extends WorkflowsCore { 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 = 'Quantum AI Career Navigator'; + } + + // Create white-label interface + resultsContent.innerHTML = ` +Meet Jessica, your personal AI cybersecurity career advisor. Share your goals and get expert guidance tailored to your journey.
++ Elevate Your Brand in the AI-Driven Era. Unlock unparalleled digital visibility, recognition, and growth with Quantum Task AI's expert digital branding solutions. +
+ + + + + ++ Transform your brand with cutting-edge AI strategies and comprehensive digital solutions +
++ Harness cutting-edge AI to analyze your digital landscape, audience trends, and competitor benchmarks, ensuring your brand stands out in the AI-driven era. +
++ From LLM, SEO and social activation to influencer partnerships and review management - we handle every aspect of your digital brand presence. +
++ Our process adapts to your unique vision, market challenges, and growth ambitions, delivering personalized strategies that drive real results. +
++ A unified, data-driven planning system that combines proven strategy with powerful digital execution +
++ Understand your brand's current status, digital footprint, and competitor landscape to establish a baseline for growth. +
++ Set SMART goals to grow brand awareness, engagement, leads, and loyalty with measurable targets and timelines. +
++ Map your customer journey, segment audiences, define your value proposition, and select optimal channels for maximum impact. +
++ Execute with Reach (visibility), Act (engagement), Convert (sales), and Engage (loyalty) strategies across all channels. +
++ Assign tasks, manage timelines, and ensure streamlined brand asset creation across all digital channels and platforms. +
++ Monitor analytics, measure KPIs, and refine strategy through continuous feedback loops for ongoing optimization. +
++ Comprehensive digital branding solutions tailored to your business needs +
++ Complete brand audit, identity creation, and visual design systems that reflect your unique value proposition and market position. +
++ Strategic platform selection and optimization across social media, websites, and digital touchpoints for maximum brand impact. +
++ Advanced Large Language Model Optimization, search engine optimization, targeted advertising, and social media strategy execution. +
++ Strategic influencer partnerships, public relations campaigns, and media outreach to amplify your brand's reach and credibility. +
++ Unified brand guidelines, messaging frameworks, and visual standards that ensure consistency across all digital touchpoints. +
++ Advanced analytics setup, performance monitoring, and data-driven insights to measure and optimize your brand's digital performance. +
++ Fill out our Digital Branding Discovery Questionnaire and we'll review your goals and craft a personalized proposal within 24 hours. +
+ + ++ Transforming Brands for the Digital Future with AI-powered solutions and expert cybersecurity strategies. +
+