mirror of
https://github.com/thecyberlearn/quantum-ai-v2.git
synced 2026-08-18 13:52:59 +00:00
🧠 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>
This commit is contained in:
parent
6fae2686c5
commit
d8b8420319
@ -95,6 +95,10 @@
|
|||||||
<a href="{% url 'agents:career_navigator_access' %}" class="try-btn career-nav-btn">
|
<a href="{% url 'agents:career_navigator_access' %}" class="try-btn career-nav-btn">
|
||||||
🎓 Try Now →
|
🎓 Try Now →
|
||||||
</a>
|
</a>
|
||||||
|
{% elif agent.slug == 'ai-brand-strategist' %}
|
||||||
|
<a href="{% url 'agents:ai_brand_strategist_access' %}" class="try-btn">
|
||||||
|
🧠 Try Now →
|
||||||
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
|
<a href="{% url 'agents:detail' agent.slug %}" class="try-btn">Try Now →</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -103,6 +107,10 @@
|
|||||||
<a href="{% url 'authentication:login' %}?next={% url 'agents:career_navigator_access' %}" class="try-btn login-required" style="width: 100%;">
|
<a href="{% url 'authentication:login' %}?next={% url 'agents:career_navigator_access' %}" class="try-btn login-required" style="width: 100%;">
|
||||||
🔐 Login to Try
|
🔐 Login to Try
|
||||||
</a>
|
</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>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
|
<a href="{% url 'authentication:login' %}?next={% url 'agents:detail' agent.slug %}" class="try-btn login-required" style="width: 100%;">
|
||||||
🔐 Login to Try
|
🔐 Login to Try
|
||||||
|
|||||||
@ -10,6 +10,8 @@ urlpatterns = [
|
|||||||
# Direct access routes
|
# Direct access routes
|
||||||
path('career-navigator/', views.career_navigator_view, name='career_navigator'),
|
path('career-navigator/', views.career_navigator_view, name='career_navigator'),
|
||||||
path('career-navigator/access/', views.career_navigator_access, name='career_navigator_access'),
|
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'),
|
||||||
|
|
||||||
# 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'),
|
||||||
|
|||||||
@ -289,6 +289,102 @@ def career_navigator_view(request):
|
|||||||
return render(request, 'career_navigator.html', context)
|
return render(request, 'career_navigator.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def ai_brand_strategist_view(request):
|
||||||
|
"""Display the AI Brand Strategist 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 AI Brand Strategist.')
|
||||||
|
return redirect('authentication:login')
|
||||||
|
|
||||||
|
# Get the AI Brand Strategist agent
|
||||||
|
try:
|
||||||
|
agent = Agent.objects.get(slug='ai-brand-strategist', is_active=True)
|
||||||
|
except Agent.DoesNotExist:
|
||||||
|
messages.error(request, 'AI Brand Strategist 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 AI Brand Strategist 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, 'ai_brand_strategist.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def ai_brand_strategist_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 AI Brand Strategist.')
|
||||||
|
return redirect('authentication:login')
|
||||||
|
|
||||||
|
# Get the AI Brand Strategist agent
|
||||||
|
try:
|
||||||
|
agent = Agent.objects.get(slug='ai-brand-strategist', is_active=True)
|
||||||
|
except Agent.DoesNotExist:
|
||||||
|
messages.error(request, 'AI Brand Strategist 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 AI Brand Strategist.')
|
||||||
|
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
|
||||||
|
if agent.price > 0:
|
||||||
|
messages.success(request, f'Welcome to your {agent.name} consultation.')
|
||||||
|
else:
|
||||||
|
messages.success(request, f'Welcome to your {agent.name} consultation.')
|
||||||
|
return redirect('agents:ai_brand_strategist')
|
||||||
|
|
||||||
|
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
def execution_list(request):
|
def execution_list(request):
|
||||||
|
|||||||
43
templates/ai_brand_strategist.html
Normal file
43
templates/ai_brand_strategist.html
Normal 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 %}
|
||||||
Loading…
Reference in New Issue
Block a user