| const API_URL = window.location.origin;
|
|
|
| const questions = [
|
| {
|
| id: 'startup_name',
|
| section: 'A. BASIC STARTUP INFORMATION',
|
| text: "What is your startup's name?",
|
| type: 'text',
|
| required: true
|
| },
|
| {
|
| id: 'industry',
|
| section: 'A. BASIC STARTUP INFORMATION',
|
| text: 'Which industry/domain does your startup operate in?',
|
| subtitle: 'e.g., fintech, AI/ML, SaaS, edtech, e-commerce, healthtech, manufacturing, HR-tech, gaming, etc.',
|
| type: 'text',
|
| required: true
|
| },
|
| {
|
| id: 'description',
|
| section: 'A. BASIC STARTUP INFORMATION',
|
| text: 'Describe your startup in one or two sentences',
|
| subtitle: 'This helps the model understand your exact business model',
|
| type: 'textarea',
|
| required: true
|
| },
|
| {
|
| id: 'company_structure',
|
| section: 'A. BASIC STARTUP INFORMATION',
|
| text: 'What is your current company structure?',
|
| type: 'buttons',
|
| options: [
|
| 'Not registered yet',
|
| 'Sole proprietorship',
|
| 'Partnership',
|
| 'LLP',
|
| 'Private Limited Company',
|
| 'Public Limited',
|
| 'One Person Company'
|
| ],
|
| required: true
|
| },
|
| {
|
| id: 'num_founders',
|
| section: 'B. FOUNDERS & OWNERSHIP',
|
| text: 'How many founders does your startup have?',
|
| type: 'number',
|
| required: true
|
| },
|
| {
|
| id: 'founder_agreement',
|
| section: 'B. FOUNDERS & OWNERSHIP',
|
| text: 'Do you have a founder agreement in place?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'ownership_splits',
|
| section: 'B. FOUNDERS & OWNERSHIP',
|
| text: 'Should the documents consider ownership splits or equity distribution?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'has_employees',
|
| section: 'C. EMPLOYEES & TEAM STRUCTURE',
|
| text: 'Do you currently have employees?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'num_employees',
|
| section: 'C. EMPLOYEES & TEAM STRUCTURE',
|
| text: 'How many employees or interns?',
|
| type: 'number',
|
| subtitle: 'Skip if you answered No to previous question',
|
| required: false,
|
| conditionalOn: { field: 'has_employees', value: 'Yes' }
|
| },
|
| {
|
| id: 'plan_to_hire',
|
| section: 'C. EMPLOYEES & TEAM STRUCTURE',
|
| text: 'Do you plan to hire soon?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'product_type',
|
| section: 'D. PRODUCT / TECH / OPERATIONS',
|
| text: 'What type of product/service do you offer?',
|
| type: 'buttons',
|
| options: [
|
| 'Software app / SaaS',
|
| 'AI model/service',
|
| 'Physical product / hardware',
|
| 'Advisory/consulting',
|
| 'Marketplace',
|
| 'Platform (B2B/B2C)'
|
| ],
|
| required: true
|
| },
|
| {
|
| id: 'collects_user_data',
|
| section: 'D. PRODUCT / TECH / OPERATIONS',
|
| text: 'Do you collect or process user data?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'data_type',
|
| section: 'D. PRODUCT / TECH / OPERATIONS',
|
| text: 'What kind of data?',
|
| subtitle: 'Select all that apply',
|
| type: 'checkboxes',
|
| options: ['Personal', 'Financial', 'Medical', 'Behavioural', 'Other'],
|
| required: false,
|
| conditionalOn: { field: 'collects_user_data', value: 'Yes' }
|
| },
|
| {
|
| id: 'primary_customers',
|
| section: 'E. CUSTOMERS & MARKET',
|
| text: 'Who are your primary customers?',
|
| type: 'buttons',
|
| options: ['Individuals (B2C)', 'Businesses (B2B)', 'Government', 'Mixed'],
|
| required: true
|
| },
|
| {
|
| id: 'has_vendors',
|
| section: 'E. CUSTOMERS & MARKET',
|
| text: 'Do you work with vendors/partners?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'client_contracts',
|
| section: 'E. CUSTOMERS & MARKET',
|
| text: 'Do you plan to onboard clients under contracts?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'has_ip',
|
| section: 'F. INTELLECTUAL PROPERTY (IP)',
|
| text: 'Do you have any proprietary technology, designs, or brand assets?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'ip_types',
|
| section: 'F. INTELLECTUAL PROPERTY (IP)',
|
| text: 'What type of IP protection do you need?',
|
| subtitle: 'Select all that apply',
|
| type: 'checkboxes',
|
| options: ['Patents', 'Copyrights', 'Trademarks', 'Licensing agreements'],
|
| required: false,
|
| conditionalOn: { field: 'has_ip', value: 'Yes' }
|
| },
|
| {
|
| id: 'startup_stage',
|
| section: 'G. FINANCIALS & FUNDRAISING',
|
| text: 'What stage is your startup currently in?',
|
| type: 'buttons',
|
| options: ['Idea', 'Validation / MVP', 'Early revenue', 'Scaling'],
|
| required: true
|
| },
|
| {
|
| id: 'raising_funds',
|
| section: 'G. FINANCIALS & FUNDRAISING',
|
| text: 'Have you raised or are you planning to raise funds?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'funding_type',
|
| section: 'G. FINANCIALS & FUNDRAISING',
|
| text: 'What type of funding?',
|
| type: 'buttons',
|
| options: ['Angel', 'Seed', 'VC', 'Grant', 'Crowdfunding', 'Multiple'],
|
| required: false,
|
| conditionalOn: { field: 'raising_funds', value: 'Yes' }
|
| },
|
| {
|
| id: 'considering_esops',
|
| section: 'G. FINANCIALS & FUNDRAISING',
|
| text: 'Are you considering ESOPs?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'regulated_industry',
|
| section: 'H. RISK / COMPLIANCE NEEDS',
|
| text: 'Do you operate in a regulated industry?',
|
| subtitle: 'Select all that apply',
|
| type: 'checkboxes',
|
| options: ['Fintech', 'Health', 'Logistics', 'Finance/Banking', 'Food', 'Education', 'None'],
|
| required: true
|
| },
|
| {
|
| id: 'operates_internationally',
|
| section: 'H. RISK / COMPLIANCE NEEDS',
|
| text: 'Does your startup operate internationally?',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'countries',
|
| section: 'H. RISK / COMPLIANCE NEEDS',
|
| text: 'List the countries',
|
| subtitle: 'Separate countries with commas',
|
| type: 'text',
|
| required: false,
|
| conditionalOn: { field: 'operates_internationally', value: 'Yes' }
|
| },
|
| {
|
| id: 'turnover_exceeds_20l',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you expect your annual turnover to exceed INR 20 lakh?',
|
| subtitle: 'GST registration becomes mandatory above this threshold',
|
| type: 'buttons',
|
| options: ['Yes', 'No', 'Unsure'],
|
| required: true
|
| },
|
| {
|
| id: 'sells_products_services',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you sell physical products, digital services, or both?',
|
| subtitle: 'GST rates vary; product sellers must generate GST-compliant invoices',
|
| type: 'buttons',
|
| options: ['Physical products', 'Digital services', 'Both'],
|
| required: true
|
| },
|
| {
|
| id: 'sells_outside_india',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you sell your product/services outside India?',
|
| subtitle: 'If yes → GST LUT, export documentation, zero-rated supply requirements',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'sells_through_platforms',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you sell through online platforms/marketplaces?',
|
| subtitle: 'E-commerce operators have special GST compliance and TCS rules',
|
| type: 'buttons',
|
| options: ['Yes', 'No'],
|
| required: true
|
| },
|
| {
|
| id: 'buys_for_business',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you buy goods/services for business (ITC eligibility)?',
|
| subtitle: 'To generate ITC-related compliance recommendations',
|
| type: 'buttons',
|
| options: ['Yes', 'No', 'Unsure'],
|
| required: true
|
| },
|
| {
|
| id: 'gst_registration_timing',
|
| section: 'I. GST QUESTIONS',
|
| text: 'Do you want GST registration done immediately?',
|
| subtitle: 'Helps include GSTIN and registration documents in the list',
|
| type: 'buttons',
|
| options: ['Yes', 'No', 'Later'],
|
| required: true
|
| }
|
| ];
|
|
|
|
|
|
|
|
|
| let currentQuestionIndex = 0;
|
| let answers = {};
|
| let generatedDocuments = null;
|
|
|
|
|
|
|
|
|
| function showSection(sectionId) {
|
| document.querySelectorAll('.section').forEach(section => {
|
| section.classList.remove('active');
|
| });
|
| document.getElementById(sectionId).classList.add('active');
|
| }
|
|
|
| function startQuestionnaire() {
|
| showSection('questionPage');
|
| currentQuestionIndex = 0;
|
| answers = {};
|
| displayQuestion();
|
| }
|
|
|
| function startOver() {
|
| if (confirm('Are you sure you want to start over? This will clear all your answers.')) {
|
| currentQuestionIndex = 0;
|
| answers = {};
|
| generatedDocuments = null;
|
| showSection('landingPage');
|
| }
|
| }
|
|
|
|
|
|
|
|
|
| function displayQuestion() {
|
| const question = questions[currentQuestionIndex];
|
|
|
|
|
| if (question.conditionalOn) {
|
| const { field, value } = question.conditionalOn;
|
| if (answers[field] !== value) {
|
|
|
| if (currentQuestionIndex < questions.length - 1) {
|
| currentQuestionIndex++;
|
| displayQuestion();
|
| } else {
|
| submitAnswers();
|
| }
|
| return;
|
| }
|
| }
|
|
|
|
|
| updateProgress();
|
|
|
|
|
| document.getElementById('questionText').textContent = question.text;
|
| document.getElementById('questionSubtitle').textContent = question.subtitle || '';
|
|
|
|
|
| document.getElementById('textInput').style.display = 'none';
|
| document.getElementById('textareaInput').style.display = 'none';
|
| document.getElementById('numberInput').style.display = 'none';
|
| document.getElementById('buttonOptions').style.display = 'none';
|
| document.getElementById('checkboxOptions').style.display = 'none';
|
|
|
|
|
| switch (question.type) {
|
| case 'text':
|
| document.getElementById('textInput').style.display = 'block';
|
| document.getElementById('textAnswer').value = answers[question.id] || '';
|
| document.getElementById('textAnswer').focus();
|
| break;
|
|
|
| case 'textarea':
|
| document.getElementById('textareaInput').style.display = 'block';
|
| document.getElementById('textareaAnswer').value = answers[question.id] || '';
|
| document.getElementById('textareaAnswer').focus();
|
| break;
|
|
|
| case 'number':
|
| document.getElementById('numberInput').style.display = 'block';
|
| document.getElementById('numberAnswer').value = answers[question.id] || '';
|
| document.getElementById('numberAnswer').focus();
|
| break;
|
|
|
| case 'buttons':
|
| displayButtonOptions(question);
|
| break;
|
|
|
| case 'checkboxes':
|
| displayCheckboxOptions(question);
|
| break;
|
| }
|
|
|
|
|
| document.getElementById('backBtn').style.display = currentQuestionIndex > 0 ? 'flex' : 'none';
|
|
|
|
|
| const card = document.getElementById('questionCard');
|
| card.style.animation = 'none';
|
| setTimeout(() => {
|
| card.style.animation = 'slideUp 0.4s ease-out';
|
| }, 10);
|
| }
|
|
|
| function displayButtonOptions(question) {
|
| const container = document.getElementById('buttonOptions');
|
| container.style.display = 'grid';
|
| container.innerHTML = '';
|
|
|
| question.options.forEach(option => {
|
| const button = document.createElement('button');
|
| button.className = 'option-btn';
|
| button.textContent = option;
|
| button.onclick = () => selectOption(question.id, option, button);
|
|
|
| if (answers[question.id] === option) {
|
| button.classList.add('selected');
|
| }
|
|
|
| container.appendChild(button);
|
| });
|
| }
|
|
|
| function displayCheckboxOptions(question) {
|
| const container = document.getElementById('checkboxOptions');
|
| container.style.display = 'flex';
|
| container.innerHTML = '';
|
|
|
| const existingAnswers = answers[question.id] || [];
|
|
|
| question.options.forEach((option, index) => {
|
| const wrapper = document.createElement('div');
|
| wrapper.className = 'checkbox-option';
|
|
|
| const checkbox = document.createElement('input');
|
| checkbox.type = 'checkbox';
|
| checkbox.id = `checkbox_${index}`;
|
| checkbox.value = option;
|
| checkbox.checked = existingAnswers.includes(option);
|
|
|
| const label = document.createElement('label');
|
| label.htmlFor = `checkbox_${index}`;
|
| label.textContent = option;
|
|
|
| wrapper.appendChild(checkbox);
|
| wrapper.appendChild(label);
|
|
|
| if (checkbox.checked) {
|
| wrapper.classList.add('selected');
|
| }
|
|
|
| wrapper.onclick = () => {
|
| checkbox.checked = !checkbox.checked;
|
| wrapper.classList.toggle('selected', checkbox.checked);
|
| };
|
|
|
| container.appendChild(wrapper);
|
| });
|
| }
|
|
|
| function selectOption(questionId, value, button) {
|
| answers[questionId] = value;
|
|
|
|
|
| document.querySelectorAll('.option-btn').forEach(btn => {
|
| btn.classList.remove('selected');
|
| });
|
| button.classList.add('selected');
|
| }
|
|
|
| function updateProgress() {
|
| const progress = ((currentQuestionIndex + 1) / questions.length) * 100;
|
| document.getElementById('progressFill').style.width = `${progress}%`;
|
| document.getElementById('questionCounter').textContent = `Question ${currentQuestionIndex + 1} of ${questions.length}`;
|
| }
|
|
|
|
|
|
|
|
|
| function getCurrentAnswer() {
|
| const question = questions[currentQuestionIndex];
|
|
|
| switch (question.type) {
|
| case 'text':
|
| return document.getElementById('textAnswer').value.trim();
|
|
|
| case 'textarea':
|
| return document.getElementById('textareaAnswer').value.trim();
|
|
|
| case 'number':
|
| return document.getElementById('numberAnswer').value;
|
|
|
| case 'buttons':
|
| return answers[question.id] || null;
|
|
|
| case 'checkboxes':
|
| const checkboxes = document.querySelectorAll('#checkboxOptions input[type="checkbox"]:checked');
|
| return Array.from(checkboxes).map(cb => cb.value);
|
| }
|
| }
|
|
|
| function validateAnswer(answer) {
|
| const question = questions[currentQuestionIndex];
|
|
|
| if (!question.required) {
|
| return true;
|
| }
|
|
|
| if (question.type === 'checkboxes') {
|
| return answer && answer.length > 0;
|
| }
|
|
|
| return answer !== null && answer !== '' && answer !== undefined;
|
| }
|
|
|
|
|
|
|
|
|
| function nextQuestion() {
|
| const answer = getCurrentAnswer();
|
|
|
| if (!validateAnswer(answer)) {
|
| alert('Please provide an answer before continuing.');
|
| return;
|
| }
|
|
|
|
|
| const question = questions[currentQuestionIndex];
|
| answers[question.id] = answer;
|
|
|
|
|
| if (currentQuestionIndex < questions.length - 1) {
|
| currentQuestionIndex++;
|
| displayQuestion();
|
| } else {
|
| submitAnswers();
|
| }
|
| }
|
|
|
| function goBack() {
|
| if (currentQuestionIndex > 0) {
|
| currentQuestionIndex--;
|
|
|
|
|
| const question = questions[currentQuestionIndex];
|
| if (question.conditionalOn) {
|
| const { field, value } = question.conditionalOn;
|
| if (answers[field] !== value) {
|
| goBack();
|
| return;
|
| }
|
| }
|
|
|
| displayQuestion();
|
| }
|
| }
|
|
|
|
|
|
|
|
|
| async function submitAnswers() {
|
| console.log('\n' + '='.repeat(80));
|
| console.log('🚀 STARTING DOCUMENT GENERATION PROCESS');
|
| console.log('='.repeat(80));
|
| console.log('📝 Timestamp:', new Date().toLocaleTimeString());
|
|
|
| showSection('loadingPage');
|
| animateLoadingSteps();
|
|
|
| try {
|
|
|
| console.log('\n📋 Step 1: Building prompt from user answers...');
|
| const prompt = buildPrompt(answers);
|
| console.log(' ✅ Prompt built successfully');
|
| console.log(' - Prompt length:', prompt.length, 'characters');
|
| console.log(' - Prompt preview:', prompt.substring(0, 200) + '...');
|
|
|
| const requestParams = {
|
| prompt: prompt,
|
| max_new_tokens: 100,
|
| temperature: 0.3,
|
| top_p: 0.85
|
| };
|
|
|
| console.log('\n📋 Step 2: Preparing API request...');
|
| console.log(' - API URL:', `${API_URL}/api/generate`);
|
| console.log(' - Max tokens:', requestParams.max_new_tokens);
|
| console.log(' - Temperature:', requestParams.temperature);
|
| console.log(' - Top P:', requestParams.top_p);
|
|
|
| console.log('\n🌐 Step 3: Sending POST request to backend...');
|
| const requestStartTime = Date.now();
|
|
|
| const response = await fetch(`${API_URL}/api/generate`, {
|
| method: 'POST',
|
| headers: {
|
| 'Content-Type': 'application/json',
|
| },
|
| body: JSON.stringify(requestParams)
|
| });
|
|
|
| const requestEndTime = Date.now();
|
| const requestDuration = ((requestEndTime - requestStartTime) / 1000).toFixed(2);
|
|
|
| console.log('\n📥 Step 4: Response received from backend');
|
| console.log(' - Response status:', response.status, response.statusText);
|
| console.log(' - Response time:', requestDuration, 'seconds');
|
| console.log(' - Response OK:', response.ok);
|
|
|
| if (!response.ok) {
|
| console.error(' ❌ Backend returned error status');
|
| throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
| }
|
|
|
| console.log('\n🔄 Step 5: Parsing JSON response...');
|
| const data = await response.json();
|
| console.log(' ✅ JSON parsed successfully');
|
|
|
|
|
| const generatedText = data.generated_text;
|
| console.log('\n📄 Step 6: Processing generated text...');
|
| console.log(' - Generated text length:', generatedText.length, 'characters');
|
| console.log(' - Generated text preview:', generatedText.substring(0, 200) + '...');
|
|
|
| console.log('\n🔍 Step 7: Parsing generated documents from text...');
|
| generatedDocuments = parseGeneratedDocuments(generatedText);
|
| console.log(' ✅ Documents parsed successfully');
|
| console.log(' - Number of documents:', generatedDocuments.length);
|
|
|
|
|
| console.log('\n🎨 Step 8: Displaying results to user...');
|
| displayResults();
|
| console.log(' ✅ Results displayed successfully');
|
|
|
| console.log('\n✅ DOCUMENT GENERATION COMPLETED SUCCESSFULLY');
|
| console.log('⏱️ Total time:', requestDuration, 'seconds');
|
| console.log('='.repeat(80) + '\n');
|
|
|
| } catch (error) {
|
| console.error('\n❌ ERROR OCCURRED DURING GENERATION:');
|
| console.error(' - Error type:', error.name);
|
| console.error(' - Error message:', error.message);
|
| console.error(' - Stack trace:', error.stack);
|
| console.log('='.repeat(80) + '\n');
|
|
|
| alert(`Error generating documents: ${error.message}\n\nPlease try again.`);
|
| showSection('questionPage');
|
| }
|
| }
|
|
|
| function buildPrompt(answers) {
|
|
|
| let prompt = `You are a legal document advisor for startups. Based on the following information about a startup, generate a comprehensive JSON list of required legal documents.\n\n`;
|
|
|
| prompt += `STARTUP INFORMATION:\n`;
|
| prompt += `- Name: ${answers.startup_name}\n`;
|
| prompt += `- Industry: ${answers.industry}\n`;
|
| prompt += `- Description: ${answers.description}\n`;
|
| prompt += `- Company Structure: ${answers.company_structure}\n`;
|
| prompt += `- Number of Founders: ${answers.num_founders}\n`;
|
| prompt += `- Has Founder Agreement: ${answers.founder_agreement}\n`;
|
| prompt += `- Consider Ownership Splits: ${answers.ownership_splits}\n`;
|
| prompt += `- Has Employees: ${answers.has_employees}\n`;
|
|
|
| if (answers.num_employees) {
|
| prompt += `- Number of Employees: ${answers.num_employees}\n`;
|
| }
|
|
|
| prompt += `- Plans to Hire: ${answers.plan_to_hire}\n`;
|
| prompt += `- Product Type: ${answers.product_type}\n`;
|
| prompt += `- Collects User Data: ${answers.collects_user_data}\n`;
|
|
|
| if (answers.data_type) {
|
| prompt += `- Data Types: ${Array.isArray(answers.data_type) ? answers.data_type.join(', ') : answers.data_type}\n`;
|
| }
|
|
|
| prompt += `- Primary Customers: ${answers.primary_customers}\n`;
|
| prompt += `- Works with Vendors: ${answers.has_vendors}\n`;
|
| prompt += `- Client Contracts: ${answers.client_contracts}\n`;
|
| prompt += `- Has Intellectual Property: ${answers.has_ip}\n`;
|
|
|
| if (answers.ip_types) {
|
| prompt += `- IP Types: ${Array.isArray(answers.ip_types) ? answers.ip_types.join(', ') : answers.ip_types}\n`;
|
| }
|
|
|
| prompt += `- Startup Stage: ${answers.startup_stage}\n`;
|
| prompt += `- Raising Funds: ${answers.raising_funds}\n`;
|
|
|
| if (answers.funding_type) {
|
| prompt += `- Funding Type: ${answers.funding_type}\n`;
|
| }
|
|
|
| prompt += `- Considering ESOPs: ${answers.considering_esops}\n`;
|
| prompt += `- Regulated Industries: ${Array.isArray(answers.regulated_industry) ? answers.regulated_industry.join(', ') : answers.regulated_industry}\n`;
|
| prompt += `- Operates Internationally: ${answers.operates_internationally}\n`;
|
|
|
| if (answers.countries) {
|
| prompt += `- Countries: ${answers.countries}\n`;
|
| }
|
|
|
| prompt += `- Turnover Exceeds 20L: ${answers.turnover_exceeds_20l}\n`;
|
| prompt += `- Sells: ${answers.sells_products_services}\n`;
|
| prompt += `- Sells Outside India: ${answers.sells_outside_india}\n`;
|
| prompt += `- Sells Through Platforms: ${answers.sells_through_platforms}\n`;
|
| prompt += `- Buys for Business: ${answers.buys_for_business}\n`;
|
| prompt += `- GST Registration Timing: ${answers.gst_registration_timing}\n\n`;
|
|
|
| prompt += `Generate a JSON array of document objects with the following structure:\n`;
|
| prompt += `[\n`;
|
| prompt += ` {\n`;
|
| prompt += ` "name": "Document Name",\n`;
|
| prompt += ` "description": "Brief description of what this document does",\n`;
|
| prompt += ` "why_needed": "Why this startup specifically needs this document",\n`;
|
| prompt += ` "risk_if_missing": "What risks the startup faces without this document",\n`;
|
| prompt += ` "priority": "critical|high|medium|low",\n`;
|
| prompt += ` "category": "legal|compliance|financial|operational|ip",\n`;
|
| prompt += ` "stakeholders": ["stakeholder1", "stakeholder2"],\n`;
|
| prompt += ` "is_optional": false\n`;
|
| prompt += ` }\n`;
|
| prompt += `]\n\n`;
|
| prompt += `Return ONLY the JSON array, no additional text.`;
|
|
|
| return prompt;
|
| }
|
|
|
| function parseGeneratedDocuments(text) {
|
| try {
|
|
|
| const jsonMatch = text.match(/\[[\s\S]*\]/);
|
| if (jsonMatch) {
|
| return JSON.parse(jsonMatch[0]);
|
| }
|
|
|
|
|
| return JSON.parse(text);
|
| } catch (error) {
|
| console.error('Error parsing JSON:', error);
|
| console.log('Generated text:', text);
|
|
|
|
|
| return [
|
| {
|
| name: "Error Parsing Response",
|
| description: "The AI generated a response but it couldn't be parsed. Please try again.",
|
| why_needed: "N/A",
|
| risk_if_missing: "N/A",
|
| priority: "high",
|
| category: "legal",
|
| stakeholders: [],
|
| is_optional: false
|
| }
|
| ];
|
| }
|
| }
|
|
|
| function animateLoadingSteps() {
|
| const steps = document.querySelectorAll('.loading-step');
|
|
|
| setTimeout(() => {
|
| steps[0].classList.remove('active');
|
| steps[1].classList.add('active');
|
| }, 2000);
|
|
|
| setTimeout(() => {
|
| steps[1].classList.remove('active');
|
| steps[2].classList.add('active');
|
| }, 4000);
|
| }
|
|
|
|
|
|
|
|
|
| function displayResults() {
|
| showSection('resultsPage');
|
|
|
| const requiredDocs = generatedDocuments.filter(doc => !doc.is_optional);
|
| const optionalDocs = generatedDocuments.filter(doc => doc.is_optional);
|
|
|
|
|
| const grid = document.getElementById('documentsGrid');
|
| grid.innerHTML = '';
|
|
|
| requiredDocs.forEach((doc, index) => {
|
| const card = createDocumentCard(doc, index);
|
| grid.appendChild(card);
|
| });
|
|
|
|
|
| if (optionalDocs.length > 0) {
|
| document.getElementById('optionalSection').style.display = 'block';
|
| const optionalGrid = document.getElementById('optionalDocumentsGrid');
|
| optionalGrid.innerHTML = '';
|
|
|
| optionalDocs.forEach((doc, index) => {
|
| const card = createDocumentCard(doc, index + requiredDocs.length);
|
| optionalGrid.appendChild(card);
|
| });
|
| } else {
|
| document.getElementById('optionalSection').style.display = 'none';
|
| }
|
| }
|
|
|
| function createDocumentCard(doc, index) {
|
| const card = document.createElement('div');
|
| card.className = 'document-card';
|
| card.style.animationDelay = `${index * 0.1}s`;
|
|
|
| const priorityClass = doc.priority.toLowerCase();
|
|
|
| card.innerHTML = `
|
| <div class="card-header">
|
| <h3 class="card-title">${doc.name}</h3>
|
| <span class="priority-badge ${priorityClass}">${doc.priority}</span>
|
| </div>
|
| <span class="category-badge">${doc.category}</span>
|
| <p class="card-description">${doc.description}</p>
|
|
|
| <div class="card-section">
|
| <div class="card-section-title">Why You Need This</div>
|
| <div class="card-section-content">${doc.why_needed}</div>
|
| </div>
|
|
|
| <div class="card-section">
|
| <div class="card-section-title">Risk If Missing</div>
|
| <div class="card-section-content risk">${doc.risk_if_missing}</div>
|
| </div>
|
|
|
| ${doc.stakeholders && doc.stakeholders.length > 0 ? `
|
| <div class="card-section">
|
| <div class="card-section-title">Stakeholders</div>
|
| <div class="stakeholders-list">
|
| ${doc.stakeholders.map(s => `<span class="stakeholder-tag">${s}</span>`).join('')}
|
| </div>
|
| </div>
|
| ` : ''}
|
| `;
|
|
|
| return card;
|
| }
|
|
|
|
|
|
|
|
|
| function downloadPDF() {
|
| const { jsPDF } = window.jspdf;
|
| const doc = new jsPDF();
|
|
|
| let yPos = 20;
|
| const pageHeight = doc.internal.pageSize.height;
|
| const margin = 20;
|
| const lineHeight = 7;
|
|
|
|
|
| doc.setFontSize(20);
|
| doc.setTextColor(26, 35, 126);
|
| doc.text('Legal Document Requirements', margin, yPos);
|
| yPos += 15;
|
|
|
|
|
| doc.setFontSize(12);
|
| doc.setTextColor(100, 100, 100);
|
| doc.text(`${answers.startup_name} - ${answers.industry}`, margin, yPos);
|
| yPos += 10;
|
|
|
| doc.setFontSize(10);
|
| doc.text(`Generated on ${new Date().toLocaleDateString()}`, margin, yPos);
|
| yPos += 15;
|
|
|
|
|
| const requiredDocs = generatedDocuments.filter(doc => !doc.is_optional);
|
| const optionalDocs = generatedDocuments.filter(doc => doc.is_optional);
|
|
|
|
|
| doc.setFontSize(14);
|
| doc.setTextColor(26, 35, 126);
|
| doc.text('Required Documents', margin, yPos);
|
| yPos += 10;
|
|
|
| requiredDocs.forEach((document, index) => {
|
|
|
| if (yPos > pageHeight - 40) {
|
| doc.addPage();
|
| yPos = 20;
|
| }
|
|
|
|
|
| doc.setFontSize(12);
|
| doc.setTextColor(0, 0, 0);
|
| doc.text(`${index + 1}. ${document.name}`, margin, yPos);
|
| yPos += lineHeight;
|
|
|
|
|
| doc.setFontSize(9);
|
| const priorityColors = {
|
| critical: [239, 68, 68],
|
| high: [245, 158, 11],
|
| medium: [59, 130, 246],
|
| low: [16, 185, 129]
|
| };
|
| const color = priorityColors[document.priority.toLowerCase()] || [100, 100, 100];
|
| doc.setTextColor(...color);
|
| doc.text(`Priority: ${document.priority.toUpperCase()}`, margin + 5, yPos);
|
| yPos += lineHeight;
|
|
|
|
|
| doc.setFontSize(10);
|
| doc.setTextColor(80, 80, 80);
|
| const descLines = doc.splitTextToSize(document.description, 170);
|
| doc.text(descLines, margin + 5, yPos);
|
| yPos += descLines.length * lineHeight;
|
|
|
| yPos += 5;
|
| });
|
|
|
|
|
| if (optionalDocs.length > 0) {
|
| if (yPos > pageHeight - 60) {
|
| doc.addPage();
|
| yPos = 20;
|
| }
|
|
|
| yPos += 10;
|
| doc.setFontSize(14);
|
| doc.setTextColor(26, 35, 126);
|
| doc.text('Optional Documents', margin, yPos);
|
| yPos += 10;
|
|
|
| optionalDocs.forEach((document, index) => {
|
| if (yPos > pageHeight - 40) {
|
| doc.addPage();
|
| yPos = 20;
|
| }
|
|
|
| doc.setFontSize(12);
|
| doc.setTextColor(0, 0, 0);
|
| doc.text(`${index + 1}. ${document.name}`, margin, yPos);
|
| yPos += lineHeight;
|
|
|
| doc.setFontSize(10);
|
| doc.setTextColor(80, 80, 80);
|
| const descLines = doc.splitTextToSize(document.description, 170);
|
| doc.text(descLines, margin + 5, yPos);
|
| yPos += descLines.length * lineHeight + 5;
|
| });
|
| }
|
|
|
|
|
| const totalPages = doc.internal.getNumberOfPages();
|
| for (let i = 1; i <= totalPages; i++) {
|
| doc.setPage(i);
|
| doc.setFontSize(8);
|
| doc.setTextColor(150, 150, 150);
|
| doc.text(
|
| 'Generated by LegalDocs AI - This is informational guidance only, not legal advice',
|
| margin,
|
| pageHeight - 10
|
| );
|
| doc.text(`Page ${i} of ${totalPages}`, pageHeight - margin, pageHeight - 10);
|
| }
|
|
|
| doc.save(`${answers.startup_name}_legal_documents.pdf`);
|
| }
|
|
|
|
|
|
|
|
|
| async function regenerate() {
|
| if (confirm('This will generate a new document list with the same answers. Continue?')) {
|
| await submitAnswers();
|
| }
|
| }
|
|
|
|
|
|
|
|
|
| document.addEventListener('keydown', (e) => {
|
| if (e.key === 'Enter' && !e.shiftKey) {
|
| const activeSection = document.querySelector('.section.active');
|
| if (activeSection && activeSection.id === 'questionPage') {
|
| const question = questions[currentQuestionIndex];
|
| if (question.type === 'text' || question.type === 'number') {
|
| e.preventDefault();
|
| nextQuestion();
|
| }
|
| }
|
| }
|
| });
|
|
|
|
|
|
|
|
|
| console.log('LegalDocs AI initialized');
|
| console.log(`Total questions: ${questions.length}`);
|
|
|