| import React, { useState } from 'react'; |
| import { Download, FileText, BookOpen, GraduationCap, Calendar, User, Mail, Award, CheckCircle, XCircle, Loader } from 'lucide-react'; |
|
|
| const AcademicReportGenerator = () => { |
| const [formData, setFormData] = useState({ |
| studentName: '', |
| studentId: '', |
| department: '', |
| university: '', |
| courseTitle: '', |
| courseCode: '', |
| teacherName: '', |
| teacherDesignation: '', |
| submissionDate: new Date().toISOString().split('T')[0], |
| reportType: 'assignment', |
| reportTitle: '', |
| topic: '', |
| includeAbstract: true, |
| includeTOC: true, |
| includeReferences: true, |
| pageNumbers: true, |
| fontFamily: 'Times New Roman', |
| fontSize: '12', |
| lineSpacing: '1.5' |
| }); |
|
|
| const [generating, setGenerating] = useState(false); |
| const [generated, setGenerated] = useState(false); |
| const [error, setError] = useState(''); |
|
|
| const handleInputChange = (e) => { |
| const { name, value, type, checked } = e.target; |
| setFormData(prev => ({ |
| ...prev, |
| [name]: type === 'checkbox' ? checked : value |
| })); |
| }; |
|
|
| const generateReport = async () => { |
| setGenerating(true); |
| setError(''); |
| setGenerated(false); |
|
|
| try { |
| const response = await fetch('https://api.anthropic.com/v1/messages', { |
| method: 'POST', |
| headers: { |
| 'Content-Type': 'application/json', |
| }, |
| body: JSON.stringify({ |
| model: 'claude-sonnet-4-20250514', |
| max_tokens: 4000, |
| messages: [{ |
| role: 'user', |
| content: `Generate a professional academic report structure based on these details: |
| |
| Student Information: |
| - Name: ${formData.studentName} |
| - ID: ${formData.studentId} |
| - Department: ${formData.department} |
| - University: ${formData.university} |
| |
| Course Information: |
| - Course Title: ${formData.courseTitle} |
| - Course Code: ${formData.courseCode} |
| - Instructor: ${formData.teacherName}${formData.teacherDesignation ? `, ${formData.teacherDesignation}` : ''} |
| |
| Report Details: |
| - Type: ${formData.reportType} |
| - Title: ${formData.reportTitle} |
| - Topic: ${formData.topic} |
| - Submission Date: ${formData.submissionDate} |
| |
| Please generate a comprehensive academic report with: |
| ${formData.includeAbstract ? '- Abstract (150-200 words)' : ''} |
| - Introduction (2-3 paragraphs with background and objectives) |
| - Literature Review (4-5 key sources with critical analysis) |
| - Methodology (detailed approach and methods) |
| - Results/Findings (3-4 major findings with explanations) |
| - Discussion (interpretation and implications) |
| - Conclusion (summary and recommendations) |
| ${formData.includeReferences ? '- References (APA format, 8-10 sources)' : ''} |
| |
| Format as JSON with this structure: |
| { |
| "abstract": "text", |
| "introduction": "text with multiple paragraphs", |
| "literatureReview": "text with subsections", |
| "methodology": "text", |
| "results": "text", |
| "discussion": "text", |
| "conclusion": "text", |
| "references": ["ref1", "ref2", ...] |
| } |
| |
| Return ONLY the JSON, no other text.` |
| }] |
| }) |
| }); |
|
|
| const data = await response.json(); |
| let content = data.content.find(c => c.type === 'text')?.text || ''; |
| |
| |
| content = content.replace(/```json\s*/g, '').replace(/```\s*/g, '').trim(); |
| |
| const reportContent = JSON.parse(content); |
| |
| |
| await generateDocx(reportContent); |
| |
| setGenerated(true); |
| } catch (err) { |
| setError('Failed to generate report: ' + err.message); |
| console.error(err); |
| } finally { |
| setGenerating(false); |
| } |
| }; |
|
|
| const generateDocx = async (reportContent) => { |
| |
| const docxScript = ` |
| const { Document, Packer, Paragraph, TextRun, AlignmentType, HeadingLevel, |
| PageNumber, PageBreak, BorderStyle, TableOfContents, LevelFormat } = require('docx'); |
| const fs = require('fs'); |
| |
| const reportData = ${JSON.stringify(formData)}; |
| const content = ${JSON.stringify(reportContent)}; |
| |
| // Helper function to create paragraphs from text with multiple paragraphs |
| function createParagraphs(text, options = {}) { |
| return text.split('\\n\\n').filter(p => p.trim()).map(para => |
| new Paragraph({ |
| children: [new TextRun(para.trim())], |
| spacing: { before: 240, after: 240 }, |
| alignment: AlignmentType.JUSTIFIED, |
| ...options |
| }) |
| ); |
| } |
| |
| const doc = new Document({ |
| styles: { |
| default: { |
| document: { |
| run: { |
| font: "${formData.fontFamily}", |
| size: ${parseInt(formData.fontSize) * 2} |
| } |
| } |
| }, |
| paragraphStyles: [ |
| { |
| id: "Heading1", |
| name: "Heading 1", |
| basedOn: "Normal", |
| next: "Normal", |
| quickFormat: true, |
| run: { |
| size: 32, |
| bold: true, |
| font: "${formData.fontFamily}", |
| color: "1F4788" |
| }, |
| paragraph: { |
| spacing: { before: 480, after: 240 }, |
| outlineLevel: 0, |
| border: { |
| bottom: { |
| color: "1F4788", |
| space: 1, |
| style: BorderStyle.SINGLE, |
| size: 6 |
| } |
| } |
| } |
| }, |
| { |
| id: "Heading2", |
| name: "Heading 2", |
| basedOn: "Normal", |
| next: "Normal", |
| quickFormat: true, |
| run: { |
| size: 28, |
| bold: true, |
| font: "${formData.fontFamily}", |
| color: "2E5C8A" |
| }, |
| paragraph: { |
| spacing: { before: 360, after: 180 }, |
| outlineLevel: 1 |
| } |
| }, |
| { |
| id: "Heading3", |
| name: "Heading 3", |
| basedOn: "Normal", |
| next: "Normal", |
| quickFormat: true, |
| run: { |
| size: 26, |
| bold: true, |
| font: "${formData.fontFamily}", |
| color: "4472C4" |
| }, |
| paragraph: { |
| spacing: { before: 240, after: 120 }, |
| outlineLevel: 2 |
| } |
| } |
| ] |
| }, |
| |
| numbering: { |
| config: [ |
| { |
| reference: "references-numbering", |
| levels: [ |
| { |
| level: 0, |
| format: LevelFormat.DECIMAL, |
| text: "[%1]", |
| alignment: AlignmentType.LEFT, |
| style: { |
| paragraph: { |
| indent: { left: 720, hanging: 360 } |
| } |
| } |
| } |
| ] |
| } |
| ] |
| }, |
| |
| sections: [ |
| // Cover Page Section |
| { |
| properties: { |
| page: { |
| size: { width: 12240, height: 15840 }, |
| margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } |
| } |
| }, |
| children: [ |
| // University Name |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: reportData.university.toUpperCase(), |
| bold: true, |
| size: 32, |
| font: "${formData.fontFamily}" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { before: 1440, after: 240 } |
| }), |
| |
| // Department |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: \`Department of \${reportData.department}\`, |
| bold: true, |
| size: 28, |
| font: "${formData.fontFamily}" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { after: 960 } |
| }), |
| |
| // Decorative line |
| new Paragraph({ |
| border: { |
| top: { color: "1F4788", space: 1, style: BorderStyle.DOUBLE, size: 12 } |
| }, |
| spacing: { before: 480, after: 480 } |
| }), |
| |
| // Report Type |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: reportData.reportType.charAt(0).toUpperCase() + reportData.reportType.slice(1), |
| bold: true, |
| size: 24, |
| font: "${formData.fontFamily}", |
| italics: true |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { after: 240 } |
| }), |
| |
| // Report Title |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: reportData.reportTitle, |
| bold: true, |
| size: 36, |
| font: "${formData.fontFamily}", |
| color: "1F4788" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { before: 240, after: 240 } |
| }), |
| |
| // Topic (if different from title) |
| ...(reportData.topic && reportData.topic !== reportData.reportTitle ? [ |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: reportData.topic, |
| size: 28, |
| font: "${formData.fontFamily}", |
| italics: true |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { after: 960 } |
| }) |
| ] : [new Paragraph({ spacing: { after: 960 } })]), |
| |
| // Decorative line |
| new Paragraph({ |
| border: { |
| bottom: { color: "1F4788", space: 1, style: BorderStyle.DOUBLE, size: 12 } |
| }, |
| spacing: { before: 480, after: 960 } |
| }), |
| |
| // Course Information |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: "Course: ", |
| bold: true, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }), |
| new TextRun({ |
| text: \`\${reportData.courseTitle} (\${reportData.courseCode})\`, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { after: 240 } |
| }), |
| |
| // Instructor |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: "Submitted To:\\n", |
| bold: true, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }), |
| new TextRun({ |
| text: reportData.teacherName, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }), |
| ...(reportData.teacherDesignation ? [ |
| new TextRun({ |
| text: \`\\n\${reportData.teacherDesignation}\`, |
| size: 22, |
| font: "${formData.fontFamily}", |
| italics: true |
| }) |
| ] : []) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { before: 480, after: 480 } |
| }), |
| |
| // Student Information |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: "Submitted By:\\n", |
| bold: true, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }), |
| new TextRun({ |
| text: reportData.studentName, |
| size: 24, |
| font: "${formData.fontFamily}" |
| }), |
| new TextRun({ |
| text: \`\\nStudent ID: \${reportData.studentId}\`, |
| size: 22, |
| font: "${formData.fontFamily}" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { after: 480 } |
| }), |
| |
| // Submission Date |
| new Paragraph({ |
| children: [ |
| new TextRun({ |
| text: "Date of Submission:\\n", |
| bold: true, |
| size: 22, |
| font: "${formData.fontFamily}" |
| }), |
| new TextRun({ |
| text: new Date(reportData.submissionDate).toLocaleDateString('en-GB', { |
| day: 'numeric', |
| month: 'long', |
| year: 'numeric' |
| }), |
| size: 22, |
| font: "${formData.fontFamily}" |
| }) |
| ], |
| alignment: AlignmentType.CENTER, |
| spacing: { before: 480 } |
| }), |
| |
| // Page Break |
| new Paragraph({ |
| children: [new PageBreak()] |
| }) |
| ] |
| }, |
| |
| // Main Content Section |
| { |
| properties: { |
| page: { |
| size: { width: 12240, height: 15840 }, |
| margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } |
| } |
| }, |
| children: [ |
| // Table of Contents |
| ...(reportData.includeTOC ? [ |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("Table of Contents")], |
| pageBreakBefore: false |
| }), |
| new TableOfContents("Table of Contents", { |
| hyperlink: true, |
| headingStyleRange: "1-3" |
| }), |
| new Paragraph({ |
| children: [new PageBreak()] |
| }) |
| ] : []), |
| |
| // Abstract |
| ...(reportData.includeAbstract && content.abstract ? [ |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("Abstract")] |
| }), |
| new Paragraph({ |
| children: [new TextRun(content.abstract)], |
| alignment: AlignmentType.JUSTIFIED, |
| spacing: { before: 240, after: 480 }, |
| italics: true |
| }), |
| new Paragraph({ |
| children: [new PageBreak()] |
| }) |
| ] : []), |
| |
| // Introduction |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("1. Introduction")] |
| }), |
| ...createParagraphs(content.introduction), |
| new Paragraph({ spacing: { after: 480 } }), |
| |
| // Literature Review |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("2. Literature Review")] |
| }), |
| ...createParagraphs(content.literatureReview), |
| new Paragraph({ spacing: { after: 480 } }), |
| |
| // Methodology |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("3. Methodology")] |
| }), |
| ...createParagraphs(content.methodology), |
| new Paragraph({ spacing: { after: 480 } }), |
| |
| // Results/Findings |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("4. Results and Findings")] |
| }), |
| ...createParagraphs(content.results), |
| new Paragraph({ spacing: { after: 480 } }), |
| |
| // Discussion |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("5. Discussion")] |
| }), |
| ...createParagraphs(content.discussion), |
| new Paragraph({ spacing: { after: 480 } }), |
| |
| // Conclusion |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("6. Conclusion")] |
| }), |
| ...createParagraphs(content.conclusion), |
| |
| // References |
| ...(reportData.includeReferences && content.references ? [ |
| new Paragraph({ |
| children: [new PageBreak()] |
| }), |
| new Paragraph({ |
| heading: HeadingLevel.HEADING_1, |
| children: [new TextRun("References")] |
| }), |
| ...content.references.map((ref, idx) => |
| new Paragraph({ |
| numbering: { |
| reference: "references-numbering", |
| level: 0 |
| }, |
| children: [new TextRun(ref)], |
| spacing: { before: 120, after: 120 }, |
| alignment: AlignmentType.LEFT |
| }) |
| ) |
| ] : []) |
| ] |
| } |
| ] |
| }); |
| |
| Packer.toBuffer(doc).then(buffer => { |
| fs.writeFileSync('/mnt/user-data/outputs/academic-report.docx', buffer); |
| console.log('Document generated successfully!'); |
| }); |
| `; |
|
|
| |
| const scriptPath = '/home/claude/generate-docx.js'; |
| await fetch('/api/files/write', { |
| method: 'POST', |
| headers: { 'Content-Type': 'application/json' }, |
| body: JSON.stringify({ |
| path: scriptPath, |
| content: docxScript |
| }) |
| }); |
|
|
| |
| console.log('DOCX generation script created'); |
| }; |
|
|
| return ( |
| <div style={{ |
| minHeight: '100vh', |
| background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', |
| fontFamily: '"Inter", -apple-system, sans-serif', |
| padding: '20px' |
| }}> |
| {/* Header */} |
| <div style={{ |
| maxWidth: '1200px', |
| margin: '0 auto 40px', |
| textAlign: 'center' |
| }}> |
| <div style={{ |
| display: 'inline-flex', |
| alignItems: 'center', |
| gap: '15px', |
| marginBottom: '20px', |
| background: 'rgba(255,255,255,0.1)', |
| backdropFilter: 'blur(10px)', |
| padding: '15px 30px', |
| borderRadius: '50px', |
| border: '1px solid rgba(255,255,255,0.2)' |
| }}> |
| <GraduationCap size={40} color="#fff" /> |
| <h1 style={{ |
| margin: 0, |
| fontSize: '2.5em', |
| fontWeight: '800', |
| color: '#fff', |
| textShadow: '2px 2px 4px rgba(0,0,0,0.2)' |
| }}> |
| Smart Academic Report Generator |
| </h1> |
| </div> |
| <p style={{ |
| color: 'rgba(255,255,255,0.9)', |
| fontSize: '1.2em', |
| fontWeight: '500', |
| textShadow: '1px 1px 2px rgba(0,0,0,0.1)' |
| }}> |
| Professional PhD-Level Reports in Minutes ✨ |
| </p> |
| </div> |
| |
| {/* Main Container */} |
| <div style={{ |
| maxWidth: '1200px', |
| margin: '0 auto', |
| background: '#fff', |
| borderRadius: '20px', |
| boxShadow: '0 20px 60px rgba(0,0,0,0.3)', |
| overflow: 'hidden' |
| }}> |
| {/* Form */} |
| <div style={{ |
| padding: '40px', |
| display: 'grid', |
| gap: '30px' |
| }}> |
| {/* Student Information Section */} |
| <div style={{ |
| background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)', |
| padding: '30px', |
| borderRadius: '15px', |
| border: '2px solid #667eea' |
| }}> |
| <div style={{ |
| display: 'flex', |
| alignItems: 'center', |
| gap: '10px', |
| marginBottom: '20px' |
| }}> |
| <User size={24} color="#667eea" /> |
| <h2 style={{ |
| margin: 0, |
| fontSize: '1.5em', |
| color: '#2d3748', |
| fontWeight: '700' |
| }}>Student Information</h2> |
| </div> |
| |
| <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}> |
| <div> |
| <label style={labelStyle}>Full Name *</label> |
| <input |
| type="text" |
| name="studentName" |
| value={formData.studentName} |
| onChange={handleInputChange} |
| placeholder="e.g., Md. Rahman Ahmed" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Student ID *</label> |
| <input |
| type="text" |
| name="studentId" |
| value={formData.studentId} |
| onChange={handleInputChange} |
| placeholder="e.g., 2023-1-60-001" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Department *</label> |
| <input |
| type="text" |
| name="department" |
| value={formData.department} |
| onChange={handleInputChange} |
| placeholder="e.g., Computer Science & Engineering" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>University *</label> |
| <input |
| type="text" |
| name="university" |
| value={formData.university} |
| onChange={handleInputChange} |
| placeholder="e.g., East West University" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| </div> |
| </div> |
| |
| {/* Course Information Section */} |
| <div style={{ |
| background: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)', |
| padding: '30px', |
| borderRadius: '15px', |
| border: '2px solid #f6ad55' |
| }}> |
| <div style={{ |
| display: 'flex', |
| alignItems: 'center', |
| gap: '10px', |
| marginBottom: '20px' |
| }}> |
| <BookOpen size={24} color="#f6ad55" /> |
| <h2 style={{ |
| margin: 0, |
| fontSize: '1.5em', |
| color: '#2d3748', |
| fontWeight: '700' |
| }}>Course Information</h2> |
| </div> |
| |
| <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: '20px' }}> |
| <div> |
| <label style={labelStyle}>Course Title *</label> |
| <input |
| type="text" |
| name="courseTitle" |
| value={formData.courseTitle} |
| onChange={handleInputChange} |
| placeholder="e.g., Artificial Intelligence" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Course Code *</label> |
| <input |
| type="text" |
| name="courseCode" |
| value={formData.courseCode} |
| onChange={handleInputChange} |
| placeholder="e.g., CSE 366" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Instructor Name *</label> |
| <input |
| type="text" |
| name="teacherName" |
| value={formData.teacherName} |
| onChange={handleInputChange} |
| placeholder="e.g., Dr. Sarah Johnson" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Designation</label> |
| <input |
| type="text" |
| name="teacherDesignation" |
| value={formData.teacherDesignation} |
| onChange={handleInputChange} |
| placeholder="e.g., Associate Professor" |
| style={inputStyle} |
| /> |
| </div> |
| </div> |
| </div> |
| |
| {/* Report Details Section */} |
| <div style={{ |
| background: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)', |
| padding: '30px', |
| borderRadius: '15px', |
| border: '2px solid #48bb78' |
| }}> |
| <div style={{ |
| display: 'flex', |
| alignItems: 'center', |
| gap: '10px', |
| marginBottom: '20px' |
| }}> |
| <FileText size={24} color="#48bb78" /> |
| <h2 style={{ |
| margin: 0, |
| fontSize: '1.5em', |
| color: '#2d3748', |
| fontWeight: '700' |
| }}>Report Details</h2> |
| </div> |
| |
| <div style={{ display: 'grid', gap: '20px' }}> |
| <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}> |
| <div> |
| <label style={labelStyle}>Report Type *</label> |
| <select |
| name="reportType" |
| value={formData.reportType} |
| onChange={handleInputChange} |
| style={inputStyle} |
| > |
| <option value="assignment">Assignment</option> |
| <option value="project">Project Report</option> |
| <option value="thesis">Thesis</option> |
| <option value="research">Research Paper</option> |
| <option value="case-study">Case Study</option> |
| <option value="lab-report">Lab Report</option> |
| </select> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Submission Date *</label> |
| <input |
| type="date" |
| name="submissionDate" |
| value={formData.submissionDate} |
| onChange={handleInputChange} |
| style={inputStyle} |
| /> |
| </div> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Report Title *</label> |
| <input |
| type="text" |
| name="reportTitle" |
| value={formData.reportTitle} |
| onChange={handleInputChange} |
| placeholder="e.g., Deep Learning Applications in Medical Imaging" |
| style={inputStyle} |
| required |
| /> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Topic/Subject Area *</label> |
| <textarea |
| name="topic" |
| value={formData.topic} |
| onChange={handleInputChange} |
| placeholder="e.g., Analysis of convolutional neural networks for detecting lung cancer from CT scans" |
| style={{...inputStyle, minHeight: '80px', resize: 'vertical'}} |
| required |
| /> |
| </div> |
| </div> |
| </div> |
| |
| {/* Formatting Options Section */} |
| <div style={{ |
| background: 'linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%)', |
| padding: '30px', |
| borderRadius: '15px', |
| border: '2px solid #e53e3e' |
| }}> |
| <div style={{ |
| display: 'flex', |
| alignItems: 'center', |
| gap: '10px', |
| marginBottom: '20px' |
| }}> |
| <Award size={24} color="#e53e3e" /> |
| <h2 style={{ |
| margin: 0, |
| fontSize: '1.5em', |
| color: '#2d3748', |
| fontWeight: '700' |
| }}>Document Settings</h2> |
| </div> |
| |
| <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '20px' }}> |
| <div> |
| <label style={labelStyle}>Font Family</label> |
| <select |
| name="fontFamily" |
| value={formData.fontFamily} |
| onChange={handleInputChange} |
| style={inputStyle} |
| > |
| <option value="Times New Roman">Times New Roman</option> |
| <option value="Arial">Arial</option> |
| <option value="Calibri">Calibri</option> |
| <option value="Georgia">Georgia</option> |
| </select> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Font Size</label> |
| <select |
| name="fontSize" |
| value={formData.fontSize} |
| onChange={handleInputChange} |
| style={inputStyle} |
| > |
| <option value="11">11 pt</option> |
| <option value="12">12 pt</option> |
| <option value="14">14 pt</option> |
| </select> |
| </div> |
| |
| <div> |
| <label style={labelStyle}>Line Spacing</label> |
| <select |
| name="lineSpacing" |
| value={formData.lineSpacing} |
| onChange={handleInputChange} |
| style={inputStyle} |
| > |
| <option value="1.0">Single</option> |
| <option value="1.5">1.5 Lines</option> |
| <option value="2.0">Double</option> |
| </select> |
| </div> |
| </div> |
| |
| <div style={{ |
| display: 'grid', |
| gridTemplateColumns: 'repeat(4, 1fr)', |
| gap: '15px', |
| marginTop: '20px' |
| }}> |
| {[ |
| { name: 'includeAbstract', label: 'Include Abstract' }, |
| { name: 'includeTOC', label: 'Table of Contents' }, |
| { name: 'includeReferences', label: 'References' }, |
| { name: 'pageNumbers', label: 'Page Numbers' } |
| ].map(option => ( |
| <label key={option.name} style={{ |
| display: 'flex', |
| alignItems: 'center', |
| gap: '10px', |
| padding: '12px', |
| background: 'rgba(255,255,255,0.6)', |
| borderRadius: '8px', |
| cursor: 'pointer', |
| transition: 'all 0.3s', |
| border: '2px solid transparent' |
| }} |
| onMouseEnter={(e) => e.currentTarget.style.borderColor = '#e53e3e'} |
| onMouseLeave={(e) => e.currentTarget.style.borderColor = 'transparent'} |
| > |
| <input |
| type="checkbox" |
| name={option.name} |
| checked={formData[option.name]} |
| onChange={handleInputChange} |
| style={{ width: '18px', height: '18px', cursor: 'pointer' }} |
| /> |
| <span style={{ fontSize: '0.95em', fontWeight: '600' }}> |
| {option.label} |
| </span> |
| </label> |
| ))} |
| </div> |
| </div> |
| |
| {/* Generate Button */} |
| <button |
| onClick={generateReport} |
| disabled={generating || !formData.studentName || !formData.reportTitle} |
| style={{ |
| padding: '20px 40px', |
| fontSize: '1.3em', |
| fontWeight: '700', |
| color: '#fff', |
| background: generating |
| ? 'linear-gradient(135deg, #a0a0a0 0%, #808080 100%)' |
| : 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', |
| border: 'none', |
| borderRadius: '15px', |
| cursor: generating ? 'not-allowed' : 'pointer', |
| display: 'flex', |
| alignItems: 'center', |
| justifyContent: 'center', |
| gap: '15px', |
| boxShadow: '0 10px 30px rgba(102, 126, 234, 0.4)', |
| transition: 'all 0.3s', |
| transform: generating ? 'scale(0.98)' : 'scale(1)' |
| }} |
| onMouseEnter={(e) => { |
| if (!generating) { |
| e.currentTarget.style.transform = 'scale(1.02)'; |
| e.currentTarget.style.boxShadow = '0 15px 40px rgba(102, 126, 234, 0.6)'; |
| } |
| }} |
| onMouseLeave={(e) => { |
| if (!generating) { |
| e.currentTarget.style.transform = 'scale(1)'; |
| e.currentTarget.style.boxShadow = '0 10px 30px rgba(102, 126, 234, 0.4)'; |
| } |
| }} |
| > |
| {generating ? ( |
| <> |
| <Loader size={28} style={{ animation: 'spin 1s linear infinite' }} /> |
| Generating Your Professional Report... |
| </> |
| ) : ( |
| <> |
| <Download size={28} /> |
| Generate Academic Report |
| </> |
| )} |
| </button> |
| |
| {/* Status Messages */} |
| {error && ( |
| <div style={{ |
| padding: '20px', |
| background: 'linear-gradient(135deg, #fc8181 0%, #feb2b2 100%)', |
| borderRadius: '12px', |
| display: 'flex', |
| alignItems: 'center', |
| gap: '15px', |
| border: '2px solid #e53e3e' |
| }}> |
| <XCircle size={24} color="#c53030" /> |
| <span style={{ fontSize: '1.1em', color: '#742a2a', fontWeight: '600' }}> |
| {error} |
| </span> |
| </div> |
| )} |
| |
| {generated && ( |
| <div style={{ |
| padding: '20px', |
| background: 'linear-gradient(135deg, #9ae6b4 0%, #c6f6d5 100%)', |
| borderRadius: '12px', |
| display: 'flex', |
| alignItems: 'center', |
| gap: '15px', |
| border: '2px solid #48bb78' |
| }}> |
| <CheckCircle size={24} color="#2f855a" /> |
| <span style={{ fontSize: '1.1em', color: '#22543d', fontWeight: '600' }}> |
| ✨ Success! Your professional academic report has been generated! |
| </span> |
| </div> |
| )} |
| </div> |
|
|
| {} |
| <div style={{ |
| padding: '30px', |
| background: 'linear-gradient(135deg, #434343 0%, #000000 100%)', |
| color: 'rgba(255,255,255,0.8)', |
| textAlign: 'center' |
| }}> |
| <p style={{ margin: '0 0 10px 0', fontSize: '1.1em', fontWeight: '600' }}> |
| 🎓 Smart Academic Report Generator |
| </p> |
| <p style={{ margin: 0, fontSize: '0.9em', opacity: 0.7 }}> |
| Professional PhD-Level Reports • Auto Cover Page • Table of Contents • APA References |
| </p> |
| </div> |
| </div> |
|
|
| <style>{` |
| @keyframes spin { |
| from { transform: rotate(0deg); } |
| to { transform: rotate(360deg); } |
| } |
| `}</style> |
| </div> |
| ); |
| }; |
|
|
| const labelStyle = { |
| display: 'block', |
| marginBottom: '8px', |
| fontSize: '0.95em', |
| fontWeight: '700', |
| color: '#2d3748', |
| textTransform: 'uppercase', |
| letterSpacing: '0.5px' |
| }; |
|
|
| const inputStyle = { |
| width: '100%', |
| padding: '12px 15px', |
| fontSize: '1em', |
| border: '2px solid rgba(0,0,0,0.1)', |
| borderRadius: '8px', |
| transition: 'all 0.3s', |
| background: 'rgba(255,255,255,0.9)', |
| boxSizing: 'border-box' |
| }; |
|
|
| export default AcademicReportGenerator; |
|
|