Spaces:
Sleeping
Sleeping
| import re | |
| import gradio as gr | |
| CUSTOM_CSS = """ | |
| body { | |
| background: linear-gradient(180deg, #f4f6f8 0%, #edf1f5 100%); | |
| } | |
| .gradio-container { | |
| max-width: 1280px !important; | |
| padding-top: 20px !important; | |
| padding-bottom: 36px !important; | |
| font-family: "Aptos", "Segoe UI", "Helvetica Neue", sans-serif !important; | |
| color: #1c2733; | |
| } | |
| .hero-shell { | |
| background: linear-gradient(135deg, #11283f 0%, #1a3d5f 100%); | |
| border-radius: 10px; | |
| overflow: hidden; | |
| box-shadow: 0 18px 40px rgba(18, 36, 53, 0.16); | |
| margin-bottom: 18px; | |
| border: 1px solid rgba(255, 255, 255, 0.08); | |
| } | |
| .hero-inner { | |
| padding: 30px 34px; | |
| color: #ffffff; | |
| } | |
| .eyebrow { | |
| display: inline-block; | |
| font-size: 0.78rem; | |
| font-weight: 700; | |
| text-transform: uppercase; | |
| letter-spacing: 0.08em; | |
| color: #ffffff !important; | |
| margin-bottom: 12px; | |
| } | |
| .hero-title { | |
| margin: 0 0 12px 0; | |
| font-size: 2.5rem; | |
| line-height: 1.08; | |
| font-weight: 800; | |
| letter-spacing: -0.02em; | |
| color: #ffffff !important; | |
| opacity: 1 !important; | |
| text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18); | |
| } | |
| .hero-subtitle { | |
| max-width: 860px; | |
| margin: 0; | |
| font-size: 1.02rem; | |
| line-height: 1.75; | |
| color: #ffffff !important; | |
| } | |
| .hero-bar { | |
| display: grid; | |
| grid-template-columns: repeat(4, minmax(0, 1fr)); | |
| gap: 1px; | |
| margin-top: 22px; | |
| background: rgba(255, 255, 255, 0.12); | |
| border-radius: 8px; | |
| overflow: hidden; | |
| } | |
| .hero-stat { | |
| background: rgba(255, 255, 255, 0.08); | |
| padding: 14px 16px; | |
| } | |
| .hero-stat strong { | |
| display: block; | |
| font-size: 0.92rem; | |
| margin-bottom: 4px; | |
| color: #ffffff !important; | |
| } | |
| .hero-stat span { | |
| font-size: 0.84rem; | |
| color: #ffffff !important; | |
| line-height: 1.45; | |
| } | |
| .panel { | |
| background: #ffffff; | |
| border: 1px solid #d7dde5; | |
| border-radius: 10px; | |
| box-shadow: 0 8px 20px rgba(31, 47, 61, 0.06); | |
| overflow: hidden; | |
| } | |
| .panel-head { | |
| padding: 20px 22px 14px 22px; | |
| border-bottom: 1px solid #e3e8ee; | |
| background: linear-gradient(180deg, #fbfcfd 0%, #f5f8fb 100%); | |
| } | |
| .panel-title { | |
| margin: 0 0 6px 0; | |
| font-size: 1.2rem; | |
| font-weight: 800; | |
| color: #17324a; | |
| } | |
| .panel-copy { | |
| margin: 0; | |
| color: #56697a; | |
| font-size: 0.95rem; | |
| line-height: 1.6; | |
| } | |
| .panel-body { | |
| padding: 20px 22px 22px 22px; | |
| } | |
| .metric-strip { | |
| display: grid; | |
| grid-template-columns: repeat(3, minmax(0, 1fr)); | |
| gap: 12px; | |
| margin-bottom: 16px; | |
| } | |
| .metric-card { | |
| background: #f8fafc; | |
| border: 1px solid #dfe5eb; | |
| border-left: 4px solid #244e73; | |
| border-radius: 8px; | |
| padding: 14px 14px 12px 14px; | |
| } | |
| .metric-card strong { | |
| display: block; | |
| color: #173954; | |
| font-size: 1rem; | |
| margin-bottom: 4px; | |
| } | |
| .metric-card span { | |
| color: #607180; | |
| font-size: 0.88rem; | |
| line-height: 1.45; | |
| } | |
| /* Base Textbox & Textarea styling */ | |
| textarea, [data-testid="textbox"] textarea { | |
| background: #ffffff !important; | |
| border: 1px solid #ccd5de !important; | |
| border-radius: 8px !important; | |
| font-size: 0.98rem !important; | |
| color: #27272A !important; | |
| box-shadow: none !important; | |
| } | |
| textarea::placeholder, [data-testid="textbox"] textarea::placeholder { | |
| color: #7a8896 !important; | |
| } | |
| textarea:focus, [data-testid="textbox"] textarea:focus { | |
| border: 1px solid #244e73 !important; | |
| box-shadow: 0 0 0 3px rgba(36, 78, 115, 0.12) !important; | |
| } | |
| /* Button styling */ | |
| button.primary { | |
| background: #173a59 !important; | |
| color: #ffffff !important; | |
| border: 1px solid #173a59 !important; | |
| border-radius: 8px !important; | |
| min-height: 46px !important; | |
| font-weight: 700 !important; | |
| transition: all 0.2s ease !important; | |
| } | |
| button.primary:hover { | |
| background: #214d75 !important; | |
| border-color: #214d75 !important; | |
| color: #ffffff !important; | |
| } | |
| button.secondary { | |
| background: #ffffff !important; | |
| color: #173954 !important; | |
| border: 1px solid #ccd5de !important; | |
| border-radius: 8px !important; | |
| min-height: 46px !important; | |
| font-weight: 700 !important; | |
| transition: all 0.2s ease !important; | |
| } | |
| button.secondary:hover { | |
| background: #eef4f8 !important; | |
| color: #16324a !important; | |
| border-color: #b8c7d4 !important; | |
| } | |
| /* Output Prose styling */ | |
| .prose, .prose * { | |
| color: #1e2f3d !important; | |
| line-height: 1.72 !important; | |
| } | |
| .prose h1, .prose h2, .prose h3 { | |
| color: #16324a !important; | |
| font-weight: 800 !important; | |
| } | |
| /* Footer Banner */ | |
| .footer-banner { | |
| margin-top: 16px; | |
| background: #ffffff; | |
| border: 1px solid #d8dfe6; | |
| border-radius: 10px; | |
| padding: 16px 20px; | |
| color: #4d6272; | |
| font-size: 0.94rem; | |
| line-height: 1.65; | |
| box-shadow: 0 8px 18px rgba(31, 47, 61, 0.05); | |
| } | |
| .footer-banner strong { | |
| color: #16324a; | |
| } | |
| /* Keep hero stats white no matter what */ | |
| .hero-shell *, | |
| .hero-inner *, | |
| .hero-subtitle, | |
| .eyebrow, | |
| .hero-stat strong, | |
| .hero-stat span { | |
| color: #ffffff !important; | |
| } | |
| @media (max-width: 900px) { | |
| .hero-title { | |
| font-size: 2rem; | |
| } | |
| .hero-bar, | |
| .metric-strip { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| /* ========================================= | |
| SLEDGEHAMMER OVERRIDES FOR GRADIO BUGS | |
| ========================================= */ | |
| /* 1. HERO TITLE FIX (Bypasses Gradio's internal h1 color reset) */ | |
| .gradio-container .hero-shell h1.hero-title, | |
| .gradio-container .hero-shell h1, | |
| .hero-shell .hero-title { | |
| color: #ffffff !important; | |
| -webkit-text-fill-color: #ffffff !important; /* Forces white even if webkit overrides it */ | |
| opacity: 1 !important; | |
| text-shadow: 0 1px 2px rgba(0, 0, 0, 0.18) !important; | |
| margin: 0 0 12px 0 !important; | |
| font-size: 2.5rem !important; | |
| font-weight: 800 !important; | |
| } | |
| /* 2. TABS VISIBILITY FIX */ | |
| div.tab-nav { | |
| gap: 8px !important; | |
| padding: 14px 22px 0 22px !important; | |
| background: #ffffff !important; | |
| } | |
| button[role="tab"] { | |
| color: #41586b !important; /* Forces unselected text to be dark grey */ | |
| border-radius: 999px !important; | |
| border: 1px solid #d5dce4 !important; | |
| background: #f7f9fb !important; | |
| font-weight: 700 !important; | |
| transition: all 0.2s ease !important; | |
| } | |
| button[role="tab"]:hover { | |
| background: #edf3f8 !important; | |
| color: #173954 !important; | |
| border-color: #bfd0dd !important; | |
| } | |
| button[role="tab"].selected { | |
| background: #173a59 !important; /* Force background on active */ | |
| color: #ffffff !important; /* Force white text on active */ | |
| border-color: #173a59 !important; | |
| } | |
| /* 3. EXAMPLES LABEL ("Sample Business Scenarios") FIX */ | |
| .examples > div:first-child, | |
| .examples > div:first-child *, | |
| .examples .label-wrap, | |
| .examples .label-wrap *, | |
| div.examples label, | |
| div.examples p, | |
| div.examples span { | |
| color: #000000 !important; | |
| font-weight: 700 !important; | |
| opacity: 1 !important; | |
| } | |
| /* 4. EXAMPLES BUTTONS & HOVER STATE FIX */ | |
| .examples button, | |
| .examples [role="button"], | |
| .examples .gallery-item { | |
| background-color: #ffffff !important; | |
| color: #000000 !important; | |
| border: 1px solid #ccd5de !important; | |
| } | |
| /* Force text inside the un-hovered buttons to stay black */ | |
| .examples button *, | |
| .examples [role="button"] *, | |
| .examples .gallery-item * { | |
| color: #000000 !important; | |
| } | |
| /* Hover and Selected states for Examples */ | |
| .examples button:hover, | |
| .examples [role="button"]:hover, | |
| .examples .gallery-item:hover, | |
| .examples button.selected, | |
| .examples [aria-selected="true"] { | |
| background-color: #173a59 !important; /* Dark blue background so white text pops */ | |
| color: #ffffff !important; /* White text */ | |
| border-color: #173a59 !important; | |
| } | |
| /* Force text inside the hovered/selected buttons to turn white */ | |
| .examples button:hover *, | |
| .examples [role="button"]:hover *, | |
| .examples .gallery-item:hover *, | |
| .examples button.selected *, | |
| .examples [aria-selected="true"] * { | |
| color: #ffffff !important; | |
| } | |
| """ | |
| def guess_title(notes): | |
| text = notes.lower() | |
| if "checkout" in text or "cart" in text or "payment" in text: | |
| return "Checkout Experience Improvement" | |
| if "hospital" in text or "patient" in text or "reception" in text: | |
| return "Patient Registration Process Improvement" | |
| if "login" in text or "signup" in text or "authentication" in text: | |
| return "Login and Access Experience Improvement" | |
| if "dashboard" in text: | |
| return "Operational Dashboard Enhancement" | |
| return "Business Process Improvement Initiative" | |
| def extract_payment_methods(text): | |
| methods = [] | |
| options = ["upi", "cards", "wallets", "net banking", "cod", "cash on delivery"] | |
| lowered = text.lower() | |
| for item in options: | |
| if item in lowered: | |
| methods.append(item.upper() if item == "upi" else item.title()) | |
| return methods | |
| def build_objectives(text): | |
| objectives = [] | |
| lowered = text.lower() | |
| if "cart" in lowered or "checkout" in lowered: | |
| objectives.append("Reduce checkout drop-off and improve completion rate") | |
| if "mobile" in lowered: | |
| objectives.append("Improve the experience for mobile users") | |
| if "support" in lowered: | |
| objectives.append("Reduce support tickets related to the process") | |
| if "faster" in lowered or "slow" in lowered: | |
| objectives.append("Reduce time required to complete the process") | |
| if "payment" in lowered: | |
| objectives.append("Make payment completion simpler and more flexible") | |
| if "dashboard" in lowered: | |
| objectives.append("Provide clearer visibility for business users") | |
| if not objectives: | |
| objectives = [ | |
| "Improve process efficiency", | |
| "Increase consistency in user experience", | |
| "Reduce manual effort" | |
| ] | |
| return objectives[:4] | |
| def build_scope(text): | |
| scope = [] | |
| lowered = text.lower() | |
| if "checkout" in lowered or "cart" in lowered: | |
| scope.append("Covers the end-to-end checkout journey") | |
| if "payment" in lowered: | |
| scope.append("Includes payment option selection and payment completion flow") | |
| if "guest checkout" in lowered or "guest" in lowered: | |
| scope.append("Includes guest user purchase flow") | |
| if "mobile" in lowered or "tablet" in lowered: | |
| scope.append("Includes responsive experience on mobile and tablet devices") | |
| if "dashboard" in lowered: | |
| scope.append("Includes dashboard access for internal users") | |
| if not scope: | |
| scope = [ | |
| "Covers the target business process described in the stakeholder notes", | |
| "Includes the main user interactions and supporting business workflow" | |
| ] | |
| return scope | |
| def build_functional_requirements(text): | |
| reqs = [] | |
| lowered = text.lower() | |
| payments = extract_payment_methods(text) | |
| if "guest checkout" in lowered or "guest" in lowered: | |
| reqs.append("The system should allow users to continue without mandatory account login") | |
| if payments: | |
| reqs.append(f"The system should support the following payment methods: {', '.join(payments)}") | |
| if "mobile" in lowered: | |
| reqs.append("The system should provide a mobile-friendly experience") | |
| if "tablet" in lowered: | |
| reqs.append("The system should work effectively on tablet devices") | |
| if "otp" in lowered: | |
| reqs.append("The system should support OTP-based verification") | |
| if "dashboard" in lowered: | |
| reqs.append("The system should provide a dashboard for business users") | |
| if "login" in lowered and "optional" in lowered: | |
| reqs.append("The system should make login optional where appropriate") | |
| if "faster" in lowered or "slow" in lowered: | |
| reqs.append("The system should reduce unnecessary user steps in the process") | |
| if not reqs: | |
| reqs = [ | |
| "The system should support the core business process described by stakeholders", | |
| "The system should simplify the current user journey", | |
| "The system should improve consistency across the workflow" | |
| ] | |
| return reqs[:6] | |
| def build_non_functional_requirements(text): | |
| reqs = [ | |
| "The solution should be easy to use for target users", | |
| "The solution should be reliable during normal business usage" | |
| ] | |
| lowered = text.lower() | |
| if "mobile" in lowered or "tablet" in lowered: | |
| reqs.append("The interface should be responsive across supported screen sizes") | |
| if "payment" in lowered or "otp" in lowered or "login" in lowered: | |
| reqs.append("The solution should protect user and transaction data") | |
| if "faster" in lowered or "slow" in lowered: | |
| reqs.append("The process should complete within an acceptable response time") | |
| return reqs[:4] | |
| def build_assumptions(text): | |
| assumptions = [ | |
| "Stakeholder notes represent the primary business need for the first version", | |
| "Existing systems can be updated without a full platform replacement" | |
| ] | |
| lowered = text.lower() | |
| if "launch" in lowered or "month" in lowered: | |
| assumptions.append("Delivery timeline expectations are realistic and approved by stakeholders") | |
| if "payment" in lowered: | |
| assumptions.append("Payment integrations can be configured within the current technical landscape") | |
| return assumptions[:4] | |
| def build_risks(text): | |
| risks = [ | |
| "Incomplete stakeholder input may lead to missing requirements", | |
| "Tight delivery timelines may reduce testing time" | |
| ] | |
| lowered = text.lower() | |
| if "payment" in lowered: | |
| risks.append("Payment integration complexity may delay release") | |
| if "guest" in lowered: | |
| risks.append("Guest user journeys may create reporting or tracking challenges") | |
| if "mobile" in lowered or "tablet" in lowered: | |
| risks.append("Cross-device usability issues may affect adoption") | |
| return risks[:4] | |
| def build_success_metrics(text): | |
| metrics = [ | |
| "Reduced time spent preparing business documentation", | |
| "Improved consistency of requirement outputs" | |
| ] | |
| lowered = text.lower() | |
| if "cart" in lowered or "checkout" in lowered: | |
| metrics.append("Higher checkout completion rate") | |
| if "support" in lowered: | |
| metrics.append("Lower support ticket volume") | |
| if "mobile" in lowered: | |
| metrics.append("Improved mobile task completion rate") | |
| return metrics[:4] | |
| def build_user_stories(text): | |
| lowered = text.lower() | |
| stories = [] | |
| if "guest checkout" in lowered or "guest" in lowered: | |
| stories.append({ | |
| "role": "customer", | |
| "goal": "complete checkout without creating an account", | |
| "benefit": "I can purchase faster", | |
| "given": "I have items in my cart", | |
| "when": "I proceed to checkout", | |
| "then": "I should be able to continue as a guest" | |
| }) | |
| if "payment" in lowered or extract_payment_methods(text): | |
| methods = extract_payment_methods(text) | |
| method_text = ", ".join(methods) if methods else "multiple payment options" | |
| stories.append({ | |
| "role": "customer", | |
| "goal": f"choose from {method_text}", | |
| "benefit": "I can use my preferred payment method", | |
| "given": "I am on the payment step", | |
| "when": "I review the payment options", | |
| "then": f"I should see {method_text}" | |
| }) | |
| if "mobile" in lowered or "tablet" in lowered: | |
| device = "mobile device" if "mobile" in lowered else "tablet" | |
| stories.append({ | |
| "role": "user", | |
| "goal": f"complete the journey smoothly on my {device}", | |
| "benefit": "I can finish the task without frustration", | |
| "given": f"I am using a {device}", | |
| "when": "I open the process flow", | |
| "then": "the experience should be clear and easy to use" | |
| }) | |
| if "dashboard" in lowered: | |
| stories.append({ | |
| "role": "business user", | |
| "goal": "view information in a dashboard", | |
| "benefit": "I can manage work more efficiently", | |
| "given": "I log into the dashboard", | |
| "when": "I review current records or updates", | |
| "then": "I should be able to access the information I need clearly" | |
| }) | |
| if not stories: | |
| stories.append({ | |
| "role": "end user", | |
| "goal": "complete the main process with fewer steps", | |
| "benefit": "I can save time and effort", | |
| "given": "I start the process", | |
| "when": "I move through the required steps", | |
| "then": "the journey should feel simple and efficient" | |
| }) | |
| stories.append({ | |
| "role": "business stakeholder", | |
| "goal": "receive clearer requirement documentation", | |
| "benefit": "delivery can be more consistent", | |
| "given": "stakeholder notes are captured", | |
| "when": "documentation is generated", | |
| "then": "the output should be structured and easy to review" | |
| }) | |
| return stories[:5] | |
| def format_brd(notes): | |
| title = guess_title(notes) | |
| objectives = build_objectives(notes) | |
| scope = build_scope(notes) | |
| functional = build_functional_requirements(notes) | |
| non_functional = build_non_functional_requirements(notes) | |
| assumptions = build_assumptions(notes) | |
| risks = build_risks(notes) | |
| metrics = build_success_metrics(notes) | |
| brd = f"""# Business Requirements Document | |
| ## Project Title | |
| {title} | |
| ## Executive Summary | |
| This document translates unstructured stakeholder notes into a cleaner, review-ready business requirements format. It is designed to help Business Analysts move faster from conversation capture to formal documentation. | |
| ## Business Problem | |
| Stakeholder feedback suggests that the current process contains friction, inconsistency, or avoidable manual effort. A more structured solution is needed to improve user outcomes and business performance. | |
| ## Objectives | |
| """ + "\n".join([f"- {item}" for item in objectives]) + """ | |
| ## Scope | |
| """ + "\n".join([f"- {item}" for item in scope]) + """ | |
| ## Functional Requirements | |
| """ + "\n".join([f"- {item}" for item in functional]) + """ | |
| ## Non-Functional Requirements | |
| """ + "\n".join([f"- {item}" for item in non_functional]) + """ | |
| ## Assumptions | |
| """ + "\n".join([f"- {item}" for item in assumptions]) + """ | |
| ## Risks | |
| """ + "\n".join([f"- {item}" for item in risks]) + """ | |
| ## Success Metrics | |
| """ + "\n".join([f"- {item}" for item in metrics]) | |
| return brd | |
| def format_stories(notes): | |
| stories = build_user_stories(notes) | |
| sections = ["# BDD-Style User Stories"] | |
| for index, story in enumerate(stories, start=1): | |
| sections.append( | |
| f""" | |
| ## User Story {index} | |
| As a {story['role']}, | |
| I want to {story['goal']}, | |
| So that {story['benefit']}. | |
| ### Acceptance Criteria | |
| - Given {story['given']} | |
| - When {story['when']} | |
| - Then {story['then']} | |
| """.strip() | |
| ) | |
| return "\n\n".join(sections) | |
| def format_before_after(notes): | |
| cleaned = notes.strip() | |
| bullet_lines = [line.strip(" -•\t") for line in cleaned.splitlines() if line.strip()] | |
| if not bullet_lines: | |
| bullet_lines = [part.strip() for part in re.split(r"[.;]\s*", cleaned) if part.strip()] | |
| before = "\n".join([f"- {line}" for line in bullet_lines[:8]]) | |
| return f"""# Before vs After | |
| ## Before: Raw Stakeholder Notes | |
| {before} | |
| ## After: Business-Ready Output | |
| - Raw notes were grouped into a formal BRD structure | |
| - Requirements were separated into functional and non-functional areas | |
| - User needs were rewritten as BDD-style stories | |
| - The output is now easier to review, share, and present | |
| ## Portfolio Value | |
| This demonstrates BA lifecycle thinking, requirement structuring, and workflow automation in a recruiter-friendly format. | |
| """ | |
| def generate_documents(notes): | |
| notes = notes.strip() | |
| if not notes: | |
| msg = "Please paste stakeholder notes first." | |
| return msg, msg, msg | |
| brd = format_brd(notes) | |
| stories = format_stories(notes) | |
| before_after = format_before_after(notes) | |
| return brd, stories, before_after | |
| with gr.Blocks(css=CUSTOM_CSS, theme=gr.themes.Base()) as demo: | |
| gr.HTML(""" | |
| <div class="hero-shell"> | |
| <div class="hero-inner"> | |
| <div class="eyebrow">Strategy • Requirements • Workflow Automation</div> | |
| <h1 class="hero-title">Agentic BA</h1> | |
| <p class="hero-subtitle"> | |
| A Business Analyst portfolio solution that converts unstructured stakeholder notes into | |
| structured BRDs, BDD-style user stories, and a clear before-versus-after documentation view. | |
| </p> | |
| <div class="hero-bar"> | |
| <div class="hero-stat"> | |
| <strong>Structured Documentation</strong> | |
| <span>Converts rough notes into formal requirement outputs.</span> | |
| </div> | |
| <div class="hero-stat"> | |
| <strong>Public Portfolio Demo</strong> | |
| <span>Built to share with recruiters and hiring teams.</span> | |
| </div> | |
| <div class="hero-stat"> | |
| <strong>100% Free Stack</strong> | |
| <span>No paid APIs, subscriptions, or hidden usage costs.</span> | |
| </div> | |
| <div class="hero-stat"> | |
| <strong>BA Lifecycle Focus</strong> | |
| <span>Highlights analysis, structuring, and requirement thinking.</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| """) | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=5): | |
| gr.HTML(""" | |
| <div class="panel"> | |
| <div class="panel-head"> | |
| <h2 class="panel-title">Input Workspace</h2> | |
| <p class="panel-copy"> | |
| Provide stakeholder notes, workshop summaries, or interview observations. | |
| The application reorganizes them into clearer business deliverables. | |
| </p> | |
| </div> | |
| <div class="panel-body"> | |
| <div class="metric-strip"> | |
| <div class="metric-card"> | |
| <strong>BRD Output</strong> | |
| <span>Formal business requirement structure</span> | |
| </div> | |
| <div class="metric-card"> | |
| <strong>BDD Stories</strong> | |
| <span>User-centered requirement framing</span> | |
| </div> | |
| <div class="metric-card"> | |
| <strong>Showcase View</strong> | |
| <span>Before-and-after transformation for interviews</span> | |
| </div> | |
| </div> | |
| """) | |
| notes_input = gr.Textbox( | |
| lines=16, | |
| label="Raw Stakeholder Notes", | |
| placeholder="Example: Customers are abandoning carts before payment. Stakeholders want easier checkout, UPI, cards, wallets, guest checkout, mobile-friendly flow, and fewer support issues." | |
| ) | |
| with gr.Row(): | |
| generate_btn = gr.Button("Generate Deliverables", variant="primary") | |
| clear_btn = gr.Button("Clear Input", variant="secondary") | |
| gr.Examples( | |
| examples=[ | |
| ["Customers are abandoning carts before payment. They want easier checkout, UPI, cards, wallets, mobile-friendly pages, guest checkout, and fewer support issues."], | |
| ["Hospital reception staff say patient registration is slow. They want OTP verification, fewer manual steps, tablet support, and a simple dashboard for receptionists."], | |
| ["Users find login confusing. Stakeholders want optional sign-in where possible, a simpler user flow, faster completion, and fewer helpdesk calls."] | |
| ], | |
| inputs=notes_input, | |
| label="Sample Business Scenarios" | |
| ) | |
| gr.HTML("</div></div>") | |
| with gr.Column(scale=7): | |
| gr.HTML(""" | |
| <div class="panel"> | |
| <div class="panel-head"> | |
| <h2 class="panel-title">Output Review</h2> | |
| <p class="panel-copy"> | |
| Review the generated documentation in a format designed for portfolio presentation | |
| and rapid recruiter understanding. | |
| </p> | |
| </div> | |
| """) | |
| with gr.Tabs(): | |
| with gr.Tab("BRD"): | |
| brd_output = gr.Markdown() | |
| with gr.Tab("BDD User Stories"): | |
| stories_output = gr.Markdown() | |
| with gr.Tab("Before vs After"): | |
| before_after_output = gr.Markdown() | |
| gr.HTML("</div>") | |
| gr.HTML(""" | |
| <div class="footer-banner"> | |
| <strong>Recruiter takeaway:</strong> This project demonstrates how a Business Analyst can apply | |
| structured automation thinking to convert unclear stakeholder input into clearer, more consistent, | |
| and more presentation-ready requirement documentation. | |
| </div> | |
| """) | |
| generate_btn.click( | |
| fn=generate_documents, | |
| inputs=notes_input, | |
| outputs=[brd_output, stories_output, before_after_output] | |
| ) | |
| clear_btn.click( | |
| fn=lambda: ("", "", "", ""), | |
| inputs=[], | |
| outputs=[notes_input, brd_output, stories_output, before_after_output] | |
| ) | |
| demo.launch() | |