Flowchart Updated

This commit is contained in:
mukesh13
2025-08-11 16:08:29 +05:30
parent 2ced46ab8f
commit d2b2bc52d8
40 changed files with 1130 additions and 1357 deletions

View File

@ -30,21 +30,14 @@ const configs = {
sample: { sample: {
subject: 'SIF Form received for Project', subject: 'SIF Form received for Project',
fields: [ fields: [
// Customer Information
'Principal_Investigator', 'Email', 'Company_Institution', 'Contact_Number', 'Address', 'City', 'State', 'Pin', 'Principal_Investigator', 'Email', 'Company_Institution', 'Contact_Number', 'Address', 'City', 'State', 'Pin',
'Secondary_Contact', 'Secondary_Email', 'Secondary_Company_Institution', 'Secondary_Contact_Number', 'Secondary_Contact', 'Secondary_Email', 'Secondary_Company_Institution', 'Secondary_Contact_Number',
// Sample Information
'Project_Title', 'Number_of_Samples', 'Sample_Type', 'Sample_Type_Other', 'Sample_Source', 'Sample_Source_Other', 'Project_Title', 'Number_of_Samples', 'Sample_Type', 'Sample_Type_Other', 'Sample_Source', 'Sample_Source_Other',
'Pathogenicity', 'Sample_Remarks', 'Pathogenicity', 'Sample_Remarks',
// Service Information
'Service_Requested', 'Service_Requested_Other', 'Type_of_Library', 'Type_of_Library_Other', 'Service_Requested', 'Service_Requested_Other', 'Type_of_Library', 'Type_of_Library_Other',
'Required_Library_Size', 'Required_Library_Size_Other', 'Index_Information', 'Kit_Information', 'Required_Library_Size', 'Required_Library_Size_Other', 'Index_Information', 'Kit_Information',
'Sequencing_Platform', 'Sequencing_Platform_Other', 'Sequencing_Read_Length', 'Sequencing_Read_Length_Other', 'Sequencing_Platform', 'Sequencing_Platform_Other', 'Sequencing_Read_Length', 'Sequencing_Read_Length_Other',
'Total_Data_Requirement', 'Service_Remarks', 'Total_Data_Requirement', 'Service_Remarks',
// Bioinformatics Information
'Analysis_Requested', 'Analysis_Details', 'Reference_Genome_Available', 'Genome_Size', 'Special_Consideration' 'Analysis_Requested', 'Analysis_Details', 'Reference_Genome_Available', 'Genome_Size', 'Special_Consideration'
], ],
required: [ required: [
@ -58,6 +51,24 @@ const configs = {
} }
}; };
// Serial number tracker
let serialTracker = {};
function generateSerialNumber() {
const today = new Date();
const dateKey = today.toISOString().slice(0, 10); // "YYYY-MM-DD"
if (!serialTracker[dateKey]) {
serialTracker[dateKey] = 1;
} else {
serialTracker[dateKey] += 1;
}
const serialNum = String(serialTracker[dateKey]).padStart(2, '0');
return {
serialNum,
formatted: `Operify Tech. ${today.getFullYear()}.${String(today.getMonth() + 1).padStart(2, '0')}.${String(today.getDate()).padStart(2, '0')}.${serialNum}`,
dateString: dateKey
};
}
// Utility functions // Utility functions
function isValidEmail(email) { function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
@ -77,7 +88,6 @@ export async function GET() {
export async function POST(request) { export async function POST(request) {
try { try {
// Parse form data
const formData = await request.formData(); const formData = await request.formData();
const data = {}; const data = {};
const files = {}; const files = {};
@ -92,7 +102,6 @@ export async function POST(request) {
const form_type = data.form_type; const form_type = data.form_type;
// Validate form type
if (!form_type || !configs[form_type]) { if (!form_type || !configs[form_type]) {
return NextResponse.json({ return NextResponse.json({
error: 'Invalid form type: ' + (form_type || 'missing') error: 'Invalid form type: ' + (form_type || 'missing')
@ -102,7 +111,6 @@ export async function POST(request) {
const config = configs[form_type]; const config = configs[form_type];
const errors = []; const errors = [];
// Validate required fields
for (const required_field of config.required) { for (const required_field of config.required) {
if (!data[required_field] || String(data[required_field]).trim() === '') { if (!data[required_field] || String(data[required_field]).trim() === '') {
errors.push(`The "${fieldName(required_field)}" field is required.`); errors.push(`The "${fieldName(required_field)}" field is required.`);
@ -111,37 +119,28 @@ export async function POST(request) {
} }
} }
// Validate file upload for career form
if (form_type === 'career') { if (form_type === 'career') {
const fileField = config.file_field; const fileField = config.file_field;
const uploadedFile = files[fileField]; const uploadedFile = files[fileField];
if (!uploadedFile || uploadedFile.size === 0) { if (!uploadedFile || uploadedFile.size === 0) {
errors.push('Please upload your resume.'); errors.push('Please upload your resume.');
} else { } else {
const allowedExtensions = ['pdf', 'doc', 'docx']; const allowedExtensions = ['pdf', 'doc', 'docx'];
const fileName = uploadedFile.name.toLowerCase(); const fileExtension = uploadedFile.name.toLowerCase().split('.').pop();
const fileExtension = fileName.split('.').pop();
if (!allowedExtensions.includes(fileExtension)) { if (!allowedExtensions.includes(fileExtension)) {
errors.push('Invalid file type. Please upload a PDF, DOC, or DOCX file.'); errors.push('Invalid file type. Please upload a PDF, DOC, or DOCX file.');
} }
if (uploadedFile.size > 10 * 1024 * 1024) {
if (uploadedFile.size > 10 * 1024 * 1024) { // 10MB limit
errors.push('File is too large. Maximum size is 10MB.'); errors.push('File is too large. Maximum size is 10MB.');
} }
} }
} }
if (errors.length > 0) { if (errors.length > 0) {
return NextResponse.json({ return NextResponse.json({ error: errors.join(' ') }, { status: 400 });
error: errors.join(' ')
}, { status: 400 });
} }
// Construct email body
let emailBody = `<h2>${config.subject}</h2><table style="border: 1px solid #b5b5b5; padding: 5px;">`; let emailBody = `<h2>${config.subject}</h2><table style="border: 1px solid #b5b5b5; padding: 5px;">`;
for (const [key, value] of Object.entries(data)) { for (const [key, value] of Object.entries(data)) {
if (config.fields.includes(key) && key !== 'form_type' && key !== 'sample_details') { if (config.fields.includes(key) && key !== 'form_type' && key !== 'sample_details') {
emailBody += `<tr> emailBody += `<tr>
@ -151,7 +150,6 @@ export async function POST(request) {
} }
} }
// Add file info if uploaded
if (form_type === 'career' && files.resume) { if (form_type === 'career' && files.resume) {
emailBody += `<tr> emailBody += `<tr>
<td style="border: 1px solid #b5b5b5; padding: 5px;"><strong>Resume</strong></td> <td style="border: 1px solid #b5b5b5; padding: 5px;"><strong>Resume</strong></td>
@ -159,20 +157,17 @@ export async function POST(request) {
</tr>`; </tr>`;
} }
// Add sample details for sample form
if (form_type === 'sample' && data.sample_details) { if (form_type === 'sample' && data.sample_details) {
try { try {
const sampleDetails = JSON.parse(data.sample_details); const sampleDetails = JSON.parse(data.sample_details);
if (sampleDetails && sampleDetails.length > 0) { if (sampleDetails.length > 0) {
emailBody += `<tr> emailBody += `<tr>
<td colspan="2" style="border: 1px solid #b5b5b5; padding: 10px; background-color: #e8f5f3; text-align: center;"><strong>SAMPLE DETAILS</strong></td> <td colspan="2" style="border: 1px solid #b5b5b5; padding: 10px; background-color: #e8f5f3; text-align: center;"><strong>SAMPLE DETAILS</strong></td>
</tr>`; </tr>`;
sampleDetails.forEach((sample, index) => { sampleDetails.forEach((sample, index) => {
emailBody += `<tr> emailBody += `<tr>
<td colspan="2" style="border: 1px solid #b5b5b5; padding: 8px; background-color: #f0f8f5; font-weight: bold;">Sample ${index + 1}</td> <td colspan="2" style="border: 1px solid #b5b5b5; padding: 8px; background-color: #f0f8f5; font-weight: bold;">Sample ${index + 1}</td>
</tr>`; </tr>`;
Object.entries(sample).forEach(([key, value]) => { Object.entries(sample).forEach(([key, value]) => {
if (value && String(value).trim() !== '') { if (value && String(value).trim() !== '') {
emailBody += `<tr> emailBody += `<tr>
@ -183,25 +178,16 @@ export async function POST(request) {
}); });
}); });
} }
} catch (error) { } catch {
console.error('Error parsing sample details:', error);
emailBody += `<tr> emailBody += `<tr>
<td colspan="2" style="border: 1px solid #b5b5b5; padding: 5px; color: red;">Error: Could not parse sample details</td> <td colspan="2" style="border: 1px solid #b5b5b5; padding: 5px; color: red;">Error: Could not parse sample details</td>
</tr>`; </tr>`;
} }
} }
emailBody += '</table>'; emailBody += '</table>';
// Determine reply-to email based on form type let replyToEmail = form_type === 'sample' ? data.Email : data.email;
let replyToEmail;
if (form_type === 'sample') {
replyToEmail = data.Email;
} else {
replyToEmail = data.email;
}
// Create transporter
const transporter = nodemailer.createTransport({ const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com', host: 'smtp.gmail.com',
port: 587, port: 587,
@ -212,17 +198,24 @@ export async function POST(request) {
}, },
}); });
// Prepare email options // SERIAL NUMBER LOGIC
let serialInfo;
if (form_type === 'sample') {
serialInfo = generateSerialNumber();
}
// Internal mail
const mailOptions = { const mailOptions = {
from: `${emailConfig.from_email_name} <${emailConfig.from_email}>`, from: `${emailConfig.from_email_name} <${emailConfig.from_email}>`,
to: `${emailConfig.to_email_name} <${emailConfig.to_email}>`, to: `${emailConfig.to_email_name} <${emailConfig.to_email}>`,
replyTo: replyToEmail || emailConfig.from_email, replyTo: replyToEmail || emailConfig.from_email,
subject: config.subject, subject: form_type === 'sample'
? `${data.Company_Institution} | ${data.Principal_Investigator} | ${serialInfo.dateString} | ${serialInfo.formatted}`
: config.subject,
html: emailBody, html: emailBody,
text: emailBody.replace(/<[^>]*>/g, ''), // Strip HTML for text version text: emailBody.replace(/<[^>]*>/g, '')
}; };
// Add attachment for career form
if (form_type === 'career' && files.resume) { if (form_type === 'career' && files.resume) {
const fileBuffer = await files.resume.arrayBuffer(); const fileBuffer = await files.resume.arrayBuffer();
mailOptions.attachments = [{ mailOptions.attachments = [{
@ -231,18 +224,24 @@ export async function POST(request) {
}]; }];
} }
// Send email
await transporter.sendMail(mailOptions); await transporter.sendMail(mailOptions);
return NextResponse.json({ // PI email for sample form
success: true, if (form_type === 'sample') {
message: config.successMessage const piMailOptions = {
}); from: `${emailConfig.from_email_name} <${emailConfig.from_email}>`,
to: `${data.Principal_Investigator} <${data.Email}>`,
subject: `SIF Form received for Project with - ${serialInfo.formatted}`,
html: emailBody,
text: emailBody.replace(/<[^>]*>/g, '')
};
await transporter.sendMail(piMailOptions);
}
return NextResponse.json({ success: true, message: config.successMessage });
} catch (error) { } catch (error) {
console.error('Email sending error:', error); console.error('Email sending error:', error);
return NextResponse.json({ return NextResponse.json({ error: 'Error sending email. Please try again later.' }, { status: 500 });
error: 'Error sending email. Please try again later.'
}, { status: 500 });
} }
} }

View File

@ -45,7 +45,7 @@ const NGSSection = () => {
description: "Rapid sequencing of large genetic material be completed within a comparatively short duration, thereby yielding quick results." description: "Rapid sequencing of large genetic material be completed within a comparatively short duration, thereby yielding quick results."
}, },
{ {
icon: "/images/homepage-1/service/Advantages-NGS-Icons-24.svg", icon: "/images/homepage-1/service/BioinformaticsAnalysis.svg",
title: "Bioinformatics Analysis", title: "Bioinformatics Analysis",
description: "NGS produces vast amounts of data, supporting complex research through advanced bioinformatic analysis." description: "NGS produces vast amounts of data, supporting complex research through advanced bioinformatic analysis."
} }

View File

@ -6,7 +6,7 @@ const CareerPage = () => {
return ( return (
<div className="page-content contact-us"> <div className="page-content contact-us">
<CareerHero /> <CareerHero />
<div className="h-6"></div> {/* <div className="h-2"></div> */}
<CareerSection /> <CareerSection />
</div> </div>
); );

View File

@ -4,7 +4,7 @@ import CareerInfo from './CareerInfo';
const CareerSection = () => { const CareerSection = () => {
return ( return (
<section className="py-10 md:py-16 lg:py-6"> <section className="py-10 md:py-16 lg:py-2">
<div className="container mx-auto max-w-none px-4"> <div className="container mx-auto max-w-none px-4">
<div className="flex flex-col lg:flex-row gap-6"> <div className="flex flex-col lg:flex-row gap-6">
<CareerInfo /> <CareerInfo />

View File

@ -7,7 +7,7 @@ const ContactPage = () => {
return ( return (
<div className="page-content contact-us"> <div className="page-content contact-us">
<PageTitle /> <PageTitle />
<div className="h-6"></div> {/* <div className="h-6"></div> */}
<ContactSection /> <ContactSection />
<ContactMap /> <ContactMap />
</div> </div>

View File

@ -39,7 +39,7 @@ const Footer = () => {
</address> </address>
{/* Social Links */} {/* Social Links */}
<div className="flex space-x-4 mt-8"> <div className="flex mt-8">
<a <a
href="#" href="#"
target="_blank" target="_blank"
@ -136,7 +136,7 @@ const Footer = () => {
<div className="container mx-auto px-4 py-4"> <div className="container mx-auto px-4 py-4">
<div className="flex flex-col md:flex-row justify-between items-center text-sm"> <div className="flex flex-col md:flex-row justify-between items-center text-sm">
<p> <p>
Copyright © 2024 <span className="text-gray-800 font-medium">Operify</span> All Rights Reserved. Copyright © 2025 <span className="text-gray-800 font-medium">Operify</span> All Rights Reserved.
</p> </p>
<ul className="flex space-x-6 mt-3 md:mt-0"> <ul className="flex space-x-6 mt-3 md:mt-0">
<li><Link href="#" className="hover:text-gray-800 transition-colors">Privacy Policy</Link></li> <li><Link href="#" className="hover:text-gray-800 transition-colors">Privacy Policy</Link></li>

View File

@ -142,8 +142,8 @@ const ShippingTemperatureTable = () => {
<table className="w-full border-collapse border border-gray-300 text-sm"> <table className="w-full border-collapse border border-gray-300 text-sm">
<colgroup> <colgroup>
<col style={{width: '25%'}} /> <col style={{width: '25%'}} />
<col style={{width: '25%'}} /> <col style={{width: '40%'}} />
<col style={{width: '50%'}} /> <col style={{width: '35%'}} />
</colgroup> </colgroup>
<thead> <thead>
<tr className="bg-teal-50"> <tr className="bg-teal-50">

View File

@ -8,70 +8,29 @@ import SampleDetailsSection from './SampleDetailsSection';
const SampleFormContainer = () => { const SampleFormContainer = () => {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
// Customer Information Principal_Investigator: '', Email: '', Company_Institution: '', Contact_Number: '',
Principal_Investigator: '', Address: '', City: '', State: '', Pin: '', Secondary_Contact: '', Secondary_Email: '',
Email: '', Secondary_Company_Institution: '', Secondary_Contact_Number: '', Project_Title: '',
Company_Institution: '', Number_of_Samples: '', Sample_Type: '', Sample_Type_Other: '', Sample_Source: '',
Contact_Number: '', Sample_Source_Other: '', Pathogenicity: '', Sample_Remarks: '', Service_Requested: '',
Address: '', Service_Requested_Other: '', Type_of_Library: '', Type_of_Library_Other: '',
City: '', Required_Library_Size: '', Required_Library_Size_Other: '', Index_Information: '',
State: '', Kit_Information: '', Sequencing_Platform: '', Sequencing_Platform_Other: '',
Pin: '', Sequencing_Read_Length: '', Sequencing_Read_Length_Other: '', Total_Data_Requirement: '',
Secondary_Contact: '', Service_Remarks: '', Analysis_Requested: '', Analysis_Details: '',
Secondary_Email: '', Reference_Genome_Available: '', Genome_Size: '', Special_Consideration: ''
Secondary_Company_Institution: '',
Secondary_Contact_Number: '',
// Sample Information
Project_Title: '',
Number_of_Samples: '',
Sample_Type: '',
Sample_Type_Other: '',
Sample_Source: '',
Sample_Source_Other: '',
Pathogenicity: '',
Sample_Remarks: '',
// Service Information
Service_Requested: '',
Service_Requested_Other: '',
Type_of_Library: '',
Type_of_Library_Other: '',
Required_Library_Size: '',
Required_Library_Size_Other: '',
Index_Information: '',
Kit_Information: '',
Sequencing_Platform: '',
Sequencing_Platform_Other: '',
Sequencing_Read_Length: '',
Sequencing_Read_Length_Other: '',
Total_Data_Requirement: '',
Service_Remarks: '',
// Bioinformatics Information
Analysis_Requested: '',
Analysis_Details: '',
Reference_Genome_Available: '',
Genome_Size: '',
Special_Consideration: '',
}); });
const [sampleDetails, setSampleDetails] = useState([ const [sampleDetails, setSampleDetails] = useState([{
{ Serial_Number: '', Sample_Name: '', Storage_Temp: '',
Serial_Number: '', Preservative_Reagent: '', Temp_Information: '', Comments: ''
Sample_Name: '', }]);
Storage_Temp: '',
Preservative_Reagent: '',
Temp_Information: '',
Comments: ''
}
]);
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const [showSuccessModal, setShowSuccessModal] = useState(false);
useEffect(() => { useEffect(() => {
// Check for Excel data in sessionStorage
const excelData = sessionStorage.getItem('excelData'); const excelData = sessionStorage.getItem('excelData');
const uploadedFileName = sessionStorage.getItem('uploadedFileName'); const uploadedFileName = sessionStorage.getItem('uploadedFileName');
@ -79,11 +38,8 @@ const SampleFormContainer = () => {
try { try {
const jsonData = JSON.parse(excelData); const jsonData = JSON.parse(excelData);
autoFillForm(jsonData); autoFillForm(jsonData);
// Clear stored data
sessionStorage.removeItem('excelData'); sessionStorage.removeItem('excelData');
sessionStorage.removeItem('uploadedFileName'); sessionStorage.removeItem('uploadedFileName');
setMessage(`Form auto-filled from uploaded file: ${uploadedFileName}`); setMessage(`Form auto-filled from uploaded file: ${uploadedFileName}`);
} catch (error) { } catch (error) {
console.error('Error parsing Excel data:', error); console.error('Error parsing Excel data:', error);
@ -93,14 +49,10 @@ const SampleFormContainer = () => {
const autoFillForm = (jsonData) => { const autoFillForm = (jsonData) => {
if (jsonData.length === 0) return; if (jsonData.length === 0) return;
const data = jsonData[0]; const data = jsonData[0];
const newFormData = { ...formData }; const newFormData = { ...formData };
// Helper function to safely get value
const getValue = (key) => data[key] ? data[key].toString().trim() : ''; const getValue = (key) => data[key] ? data[key].toString().trim() : '';
// Customer Information
newFormData.Principal_Investigator = getValue('Principal Investigator'); newFormData.Principal_Investigator = getValue('Principal Investigator');
newFormData.Email = getValue('Email'); newFormData.Email = getValue('Email');
newFormData.Company_Institution = getValue('Company/Institution'); newFormData.Company_Institution = getValue('Company/Institution');
@ -114,7 +66,6 @@ const SampleFormContainer = () => {
newFormData.Secondary_Company_Institution = getValue('Secondary Company/Institution'); newFormData.Secondary_Company_Institution = getValue('Secondary Company/Institution');
newFormData.Secondary_Contact_Number = getValue('Secondary Contact Number'); newFormData.Secondary_Contact_Number = getValue('Secondary Contact Number');
// Sample Information
newFormData.Project_Title = getValue('Project Title'); newFormData.Project_Title = getValue('Project Title');
newFormData.Number_of_Samples = getValue('Number of Samples'); newFormData.Number_of_Samples = getValue('Number of Samples');
newFormData.Sample_Type = getValue('Sample Type'); newFormData.Sample_Type = getValue('Sample Type');
@ -124,7 +75,6 @@ const SampleFormContainer = () => {
newFormData.Pathogenicity = getValue('Pathogenicity'); newFormData.Pathogenicity = getValue('Pathogenicity');
newFormData.Sample_Remarks = getValue('Sample Remarks'); newFormData.Sample_Remarks = getValue('Sample Remarks');
// Service Information
newFormData.Service_Requested = getValue('Service Requested'); newFormData.Service_Requested = getValue('Service Requested');
newFormData.Service_Requested_Other = getValue('Service Requested Other'); newFormData.Service_Requested_Other = getValue('Service Requested Other');
newFormData.Type_of_Library = getValue('Type of Library'); newFormData.Type_of_Library = getValue('Type of Library');
@ -140,7 +90,6 @@ const SampleFormContainer = () => {
newFormData.Total_Data_Requirement = getValue('Total Data Requirement'); newFormData.Total_Data_Requirement = getValue('Total Data Requirement');
newFormData.Service_Remarks = getValue('Service Remarks'); newFormData.Service_Remarks = getValue('Service Remarks');
// Bioinformatics Information
newFormData.Analysis_Requested = getValue('Analysis Requested'); newFormData.Analysis_Requested = getValue('Analysis Requested');
newFormData.Analysis_Details = getValue('Analysis Details'); newFormData.Analysis_Details = getValue('Analysis Details');
newFormData.Reference_Genome_Available = getValue('Reference Genome Available'); newFormData.Reference_Genome_Available = getValue('Reference Genome Available');
@ -149,21 +98,20 @@ const SampleFormContainer = () => {
setFormData(newFormData); setFormData(newFormData);
// Handle Sample Details const sampleDetailsData = jsonData.filter(row =>
const sampleDetailsData = jsonData.filter(row => row['Serial Number'] || row['Sample Name'] ||
row['Serial Number'] || row['Sample Name'] || row['Storage Temp'] || row['Preservative Reagent'] ||
row['Storage Temp'] || row['Preservative Reagent'] ||
row['Temp Information'] || row['Comments'] row['Temp Information'] || row['Comments']
); );
if (sampleDetailsData.length > 0) { if (sampleDetailsData.length > 0) {
const newSampleDetails = sampleDetailsData.map(sample => ({ const newSampleDetails = sampleDetailsData.map(sample => ({
Serial_Number: getValue('Serial Number'), Serial_Number: sample['Serial Number'] || '',
Sample_Name: getValue('Sample Name'), Sample_Name: sample['Sample Name'] || '',
Storage_Temp: getValue('Storage Temp'), Storage_Temp: sample['Storage Temp'] || '',
Preservative_Reagent: getValue('Preservative Reagent'), Preservative_Reagent: sample['Preservative Reagent'] || '',
Temp_Information: getValue('Temp Information'), Temp_Information: sample['Temp Information'] || '',
Comments: getValue('Comments') Comments: sample['Comments'] || ''
})); }));
setSampleDetails(newSampleDetails); setSampleDetails(newSampleDetails);
} }
@ -179,37 +127,28 @@ const SampleFormContainer = () => {
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();
setIsSubmitting(true); setIsSubmitting(true);
setMessage(''); // Clear previous messages setMessage('');
try { try {
const formDataToSend = new FormData(); const formDataToSend = new FormData();
// Add form data
Object.keys(formData).forEach(key => { Object.keys(formData).forEach(key => {
if (formData[key]) { if (formData[key]) {
formDataToSend.append(key, formData[key]); formDataToSend.append(key, formData[key]);
} }
}); });
// Add sample details as JSON string
formDataToSend.append('sample_details', JSON.stringify(sampleDetails)); formDataToSend.append('sample_details', JSON.stringify(sampleDetails));
formDataToSend.append('form_type', 'sample'); formDataToSend.append('form_type', 'sample');
console.log('Submitting form data:', formData);
console.log('Sample details:', sampleDetails);
const response = await fetch('/api/forms', { const response = await fetch('/api/forms', {
method: 'POST', method: 'POST',
body: formDataToSend, body: formDataToSend,
}); });
const result = await response.json(); const result = await response.json();
console.log('API Response:', result);
if (response.ok) { if (response.ok) {
setMessage(result.message); setMessage(result.message);
setShowSuccessModal(true); // show modal instead of green alert
// Reset form after successful submission
setFormData({ setFormData({
Principal_Investigator: '', Email: '', Company_Institution: '', Contact_Number: '', Principal_Investigator: '', Email: '', Company_Institution: '', Contact_Number: '',
Address: '', City: '', State: '', Pin: '', Secondary_Contact: '', Secondary_Email: '', Address: '', City: '', State: '', Pin: '', Secondary_Contact: '', Secondary_Email: '',
@ -223,7 +162,6 @@ const SampleFormContainer = () => {
Service_Remarks: '', Analysis_Requested: '', Analysis_Details: '', Service_Remarks: '', Analysis_Requested: '', Analysis_Details: '',
Reference_Genome_Available: '', Genome_Size: '', Special_Consideration: '' Reference_Genome_Available: '', Genome_Size: '', Special_Consideration: ''
}); });
setSampleDetails([{ setSampleDetails([{
Serial_Number: '', Sample_Name: '', Storage_Temp: '', Serial_Number: '', Sample_Name: '', Storage_Temp: '',
Preservative_Reagent: '', Temp_Information: '', Comments: '' Preservative_Reagent: '', Temp_Information: '', Comments: ''
@ -231,7 +169,6 @@ const SampleFormContainer = () => {
} else { } else {
setMessage('Error: ' + (result.error || 'Form submission failed')); setMessage('Error: ' + (result.error || 'Form submission failed'));
} }
} catch (error) { } catch (error) {
console.error('Error submitting form:', error); console.error('Error submitting form:', error);
setMessage('Error: Network error. Please check your connection and try again.'); setMessage('Error: Network error. Please check your connection and try again.');
@ -244,41 +181,22 @@ const SampleFormContainer = () => {
<div className="bg-teal-50 min-h-screen py-8"> <div className="bg-teal-50 min-h-screen py-8">
<div className="max-w-4xl mx-auto bg-teal-50 shadow-lg border border-gray-300 font-arial text-xs"> <div className="max-w-4xl mx-auto bg-teal-50 shadow-lg border border-gray-300 font-arial text-xs">
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
{/* Show message if exists */}
{message && ( {/* Only show red alert for errors */}
{message && message.includes('Error') && (
<div className="mx-6 mt-6"> <div className="mx-6 mt-6">
<div className={`p-4 rounded ${message.includes('Error') ? 'bg-red-100 text-red-800' : 'bg-green-100 text-green-800'}`}> <div className="p-4 rounded bg-red-100 text-red-800">
{message} {message}
</div> </div>
</div> </div>
)} )}
<CustomerInfoSection <CustomerInfoSection formData={formData} onInputChange={handleInputChange} />
formData={formData} <SampleInfoSection formData={formData} onInputChange={handleInputChange} />
onInputChange={handleInputChange} <ServiceInfoSection formData={formData} onInputChange={handleInputChange} />
/> <BioinformaticsSection formData={formData} onInputChange={handleInputChange} />
<SampleDetailsSection sampleDetails={sampleDetails} setSampleDetails={setSampleDetails} />
<SampleInfoSection
formData={formData}
onInputChange={handleInputChange}
/>
<ServiceInfoSection
formData={formData}
onInputChange={handleInputChange}
/>
<BioinformaticsSection
formData={formData}
onInputChange={handleInputChange}
/>
<SampleDetailsSection
sampleDetails={sampleDetails}
setSampleDetails={setSampleDetails}
/>
{/* Submit Button */}
<div className="text-center py-6"> <div className="text-center py-6">
<button <button
type="submit" type="submit"
@ -290,8 +208,50 @@ const SampleFormContainer = () => {
</div> </div>
</form> </form>
</div> </div>
{/* Success Modal */}
{/* Success Modal */}
{showSuccessModal && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-lg p-6 max-w-sm w-full text-center animate-pulse">
{/* Animated Check Circle */}
<div className="flex justify-center mb-4">
<div className="relative">
{/* Outer ring animation */}
<div className="w-20 h-20 border-4 border-green-200 rounded-full animate-ping absolute"></div>
<div className="w-16 h-16 bg-green-500 rounded-full flex items-center justify-center animate-bounce relative z-10">
{/* Checkmark */}
<svg
className="w-10 h-10 text-white animate-pulse"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="4"
d="M5 13l4 4L19 7"
/>
</svg>
</div>
</div>
</div>
<h2 className="text-lg font-semibold text-green-700 mb-4 animate-pulse">Submitted Successfully!</h2>
<p className="text-gray-700 mb-6">{message}</p>
<button
onClick={() => setShowSuccessModal(false)}
className="bg-teal-600 hover:bg-teal-700 text-white py-2 px-4 rounded transition-all duration-200 transform hover:scale-105"
>
OK
</button>
</div>
</div>
)}
</div> </div>
); );
}; };
export default SampleFormContainer; export default SampleFormContainer;

View File

@ -1,96 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const EnrichmentPipeline = ({ const EnrichmentPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/resequencing.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
],
rightSteps = [
"Downstream Advanced Analysis",
"Annotation",
"Variants Calling - SNVs, Indels, CNVs",
"Mark Duplicates and Post-Processing"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow positioned between Primary and Secondary Assembly */} // Fallback message
<div className="absolute bottom-2 sm:bottom-4 lg:bottom-[0.7rem] left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-6 h-6 sm:w-8 sm:h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,126 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const EpigenomicsPipeline = ({ const EpigenomicsPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/epigenomics.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Aligned to Reference Genome"
],
middleSteps = [
"Downstream Advanced Analysis",
"DMR Annotation",
"DMR Identification",
"Peak Calling"
],
rightSteps = [
"Distribution in genes & repeats",
"Methylated Distribution",
"Motif Identification",
"Relationship with gene expression",
"Go clustering",
"Pathway analysis"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...middleSteps, ...rightSteps];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-7xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block lg:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Desktop Layout - Three Columns */}
<div className="hidden lg:block">
<div className="grid grid-cols-3 gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full max-w-76 text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Middle Column */}
<div className="flex flex-col items-center space-y-3">
{middleSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full max-w-76 text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < middleSteps.length - 1 && (
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center justify-center">
<div className={`${cardColor} rounded-lg p-12 w-full max-w-76 text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<div className="space-y-6">
{rightSteps.map((step, index) => (
<div key={index} className={`text-sm font-medium ${textColor}`}>
{step}
</div>
))}
</div>
</div>
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrows */} // Fallback message
{/* Arrow from Aligned to Reference Genome to Peak Calling */} <div className="flex items-center justify-center h-40 text-gray-500">
<div className="absolute bottom-4 left-1/3 transform -translate-x-1/2"> <p>Please provide SVG content or URL</p>
<ArrowRight className={`w-8 h-8 ${arrowColor}`} />
</div> </div>
{/* Arrow from DMR Annotation to right box */} )}
<div className="absolute top-28 left-2/3 transform -translate-x-1/2">
<ArrowRight className={`w-8 h-8 ${arrowColor}`} />
</div>
{/* Arrow from Peak Calling to right box */}
<div className="absolute bottom-4 left-2/3 transform -translate-x-1/2">
<ArrowRight className={`w-8 h-8 ${arrowColor}`} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,96 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const GenomeMappingPipeline = ({ const GenomeMappingPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/genoemapping.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
],
rightSteps = [
"Evolutionary Analysis",
"Annotation",
"Variants Calling - structural variants and genomic rearrangements",
"Post-Processing"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow positioned between Primary and Secondary Assembly */} // Fallback message
<div className="absolute bottom-2 sm:bottom-4 lg:bottom-[0.7rem] left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-6 h-6 sm:w-8 sm:h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,124 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const MetagenomicsPipeline = ({ const MetagenomicsPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftColumn = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/metagenomics.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Host Genome"
],
middleColumn = [
"Assembly Validation",
"Secondary Assembly (Scaffolds)",
"Primary Assembly (Contigs) using Unaligned Data",
"Remove Aligned reads to Host Genome and Retain only Unaligned Reads"
],
rightColumn = [
"Gene Prediction and Gene Annotation",
"Downstream Advanced Analysis"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine all steps for mobile layout
const mobileSteps = [
...leftColumn,
...middleColumn.slice().reverse(),
...rightColumn
];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-600 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-6xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block lg:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Desktop Layout - Three Columns */}
<div className="hidden lg:block">
<div className="grid grid-cols-3 gap-6 lg:gap-10">
{/* Left Column */}
<div className="flex flex-col items-center space-y-3">
{leftColumn.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftColumn.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Middle Column */}
<div className="flex flex-col items-center space-y-3">
{middleColumn.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < middleColumn.length - 1 && (
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-3">
{rightColumn.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightColumn.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrows */} // Fallback message
{/* Arrow from left to middle column */} <div className="flex items-center justify-center h-40 text-gray-500">
<div className="absolute bottom-8 left-1/3 transform -translate-x-1/2 flex items-center justify-center"> <p>Please provide SVG content or URL</p>
<ArrowRight className={`w-8 h-8 ${arrowColor}`} />
</div> </div>
)}
{/* Arrow from middle to right column */}
<div className="absolute top-4 right-1/3 transform translate-x-1/2 flex items-center justify-center">
<ArrowRight className={`w-8 h-8 ${arrowColor}`} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,96 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const SingleCellPipeline = ({ const SingleCellPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/singlecell.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
],
rightSteps = [
"Evolutionary Analysis",
"Annotation",
"Variants Calling - SNVs, Indels, CNVs",
"Mark Duplicates and Post-Processing"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow positioned between Primary and Secondary Assembly */} // Fallback message
<div className="absolute bottom-2 sm:bottom-4 lg:bottom-[0.7rem] left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-6 h-6 sm:w-8 sm:h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,96 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const WGSDeNovoPipeline = ({ const WGSDeNovoPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/denovo.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Primary Assembly (Contigs)"
],
rightSteps = [
"Downstream Advanced Analysis",
"Gene Prediction and Gene Annotation",
"Assembly Validation",
"Secondary Assembly (Scaffolds)"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow positioned between Primary and Secondary Assembly */} // Fallback message
<div className="absolute bottom-2 sm:bottom-4 lg:bottom-[0.7rem] left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-6 h-6 sm:w-8 sm:h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,96 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const WGSResequencingPipeline = ({ const WGSResequencingPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/resequencing.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
],
rightSteps = [
"Downstream Advanced Analysis",
"Annotation",
"Variants Calling - SNVs, Indels, CNVs",
"Mark Duplicates and Post-Processing"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow positioned between Primary and Secondary Assembly */} // Fallback message
<div className="absolute bottom-2 sm:bottom-4 lg:bottom-[0.7rem] left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-6 h-6 sm:w-8 sm:h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,130 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const CircularRNAPipeline = ({ const CircularRNAPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/circularrna.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
],
rightSteps = [
"Downstream Advanced Analysis",
"Circular RNA Identification",
"Circular RNA Prediction",
"Back Splicing Junction Reads"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Tablet and Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-2 sm:space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 sm:p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-xs sm:text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-5 h-5 sm:w-6 sm:h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Custom arrows from "Alignment to Reference Genome" */} // Fallback message
<div className="absolute bottom-12 sm:bottom-16 lg:bottom-[2rem] left-1/2 transform -translate-x-1/2"> <div className="flex items-center justify-center h-40 text-gray-500">
<div className="relative w-0 h-0"> <p>Please provide SVG content or URL</p>
{/* Arrow 1: Straight horizontal to "Back Splicing Junction Reads" (Unmapped Reads) */}
<div className="absolute top-0 left-0">
<div className="relative">
{/* Horizontal line */}
<div className="w-16 sm:w-20 lg:w-28 h-0.5 bg-gray-600"></div>
{/* Arrowhead */}
<div className="absolute right-0 -top-1 w-2 h-2 border-r-2 border-t-2 border-gray-600 rotate-45"></div>
{/* Label */}
<div className="absolute top-2 left-4 sm:left-6 lg:left-10 text-xs text-gray-700 font-medium whitespace-nowrap">
Unmapped Reads
</div>
</div>
</div>
{/* Arrow 2: Diagonal upward to "Circular RNA Prediction" (Mapped Reads) */}
<div className="absolute top-0 left-0">
<div className="relative">
{/* Diagonal line going up and right */}
<div className="absolute origin-left w-20 sm:w-24 lg:w-32 h-0.5 bg-gray-600 transform -rotate-45"></div>
{/* Arrowhead positioned at the end of diagonal line */}
<div className="absolute w-2 h-2 border-r-2 border-t-2 border-gray-600 transform rotate-0"
style={{
left: 'calc(20 * 0.25rem * 0.707 - 4px)', // cos(45deg) ≈ 0.707
top: 'calc(-20 * 0.25rem * 0.707 - 4px)' // -sin(45deg) ≈ -0.707
}}></div>
{/* Label */}
<div className="absolute -top-8 left-6 sm:left-8 lg:left-12 text-xs text-gray-700 font-medium whitespace-nowrap">
Mapped Reads
</div>
</div>
</div>
</div>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,123 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const DegradomeSequencingPipeline = ({ const DegradomeSequencingPipeline = ({
title = "Degradome Sequencing", title = "Bioinformatics Pipeline",
svgContent = null, // Pass your SVG content here as JSX
svgUrl = "/images/flowchart/degradomerna.svg",
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-blue-200", textColor = "text-gray-700",
textColor = "text-gray-800",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
const leftSteps = [
"Raw Sequencing Data (fastq files)",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Alignment to Reference Genome"
];
const rightSteps = [
"Related miRNA Identification",
"mRNAs Degradome Sites",
"Identify Target mRNAs",
"Retain mRNA data Remove rRNA, tRNA and other RNA"
];
const middleSteps = [
"Functional Analysis"
];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-6xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block lg:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{[...leftSteps, ...rightSteps.slice().reverse(), ...middleSteps].map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < leftSteps.length + rightSteps.length + middleSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Desktop Layout - Complex Flow */}
<div className="hidden lg:block">
<div className="grid grid-cols-3 gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Middle Column */}
<div className="flex flex-col items-center justify-center space-y-3">
{middleSteps.map((step, index) => (
<div key={index} className={`${cardColor} rounded-lg p-4 w-full max-w-60 text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full max-w-80 text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow from left to right (after alignment) */} // Fallback message
<div className="absolute bottom-4 left-1/3 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-8 h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
)}
{/* Bidirectional arrows between middle and right columns */}
<div className="absolute top-1/2 right-1/3 transform translate-x-1/2 -translate-y-1/2 flex flex-col items-center space-y-2">
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
</div>
{/* Additional arrows for the circular flow in right column */}
<div className="absolute top-1/4 right-6 flex items-center justify-center">
<ArrowUp className={`w-5 h-5 ${arrowColor}`} />
</div>
<div className="absolute top-2/3 right-6 flex items-center justify-center">
<ArrowUp className={`w-5 h-5 ${arrowColor}`} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,127 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const IsoformPipeline = ({ const IsoformPipeline = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/isoseqrna.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Build Similarity Graph and Polishing"
],
rightSteps = [
"Downstream Analysis (Fusion Analysis, Splicing Analysis)",
"Transcript Annotation and Classification",
"Sequencing Merge and Redundancy Removal",
"Alignment to Reference Genome"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Diagonal Arrow from High Quality Sequencing Data to Alignment to Reference Genome */} // Fallback message
<div className="absolute top-80 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> <div className="flex items-center justify-center h-40 text-gray-500">
<svg <p>Please provide SVG content or URL</p>
width="180"
height="60"
viewBox="0 0 180 60"
className={arrowColor}
style={{transform: 'rotate(20deg)'}}
>
<defs>
<marker
id="arrowhead"
markerWidth="10"
markerHeight="7"
refX="9"
refY="3.5"
orient="auto"
>
<polygon
points="0 0, 10 3.5, 0 7"
fill="currentColor"
/>
</marker>
</defs>
<line
x1="10"
y1="10"
x2="170"
y2="50"
stroke="currentColor"
strokeWidth="2"
markerEnd="url(#arrowhead)"
/>
</svg>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,28 +1,51 @@
// app/rna-sequencing/lncrna-sequencing/components/LncRNABioinformatics.jsx import React from 'react';
const LncRNABioinformatics = () => { const LncRNABioinformatics = ({
title = "Bioinformatics Pipeline",
svgContent = null, // Pass your SVG content here as JSX
svgUrl = "/images/flowchart/totalrna.svg",
backgroundColor = "bg-gray-50",
textColor = "text-gray-700",
className = "",
titleClassName = "",
svgClassName = "",
containerClassName = ""
}) => {
return ( return (
<section className="py-8 lg:py-12 bg-gray-50"> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className="text-2xl lg:text-3xl text-gray-700 text-left pb-2 mb-6 lg:mb-6"> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
Bioinformatics Pipeline {title}
</h2> </h2>
{/* Pipeline Image */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<img <div className="w-full max-w-6xl">
src="/images/lncrna-bioinformatics-pipeline.jpg" {/* SVG Container with responsive sizing */}
alt="lncRNA Sequencing Bioinformatics Pipeline Workflow" <div className={`w-full ${svgClassName}`}>
className="max-w-full h-auto rounded-lg" {svgUrl ? (
/> // If SVG URL/path is provided
</div> <img
src={svgUrl}
{/* Pipeline Description */} alt="Flowchart diagram"
<div className="mt-6 text-center"> className="w-full h-auto object-contain"
<p className="text-gray-600 text-sm lg:text-base"> />
lncRNA sequencing bioinformatics pipeline for long non-coding RNA analysis and expression profiling ) : svgContent ? (
</p> // If SVG content is provided as JSX
<div className="w-full">
<div className="w-full">
{svgContent}
</div>
</div>
) : (
// Fallback message
<div className="flex items-center justify-center h-40 text-gray-500">
<p>Please provide SVG content or URL</p>
</div>
)}
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -30,4 +53,4 @@ const LncRNABioinformatics = () => {
); );
}; };
export default LncRNABioinformatics export default LncRNABioinformatics;

View File

@ -1,188 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const MetatranscriptomicsPipeline = ({ const MetatranscriptomicsPipeline = ({
title = "Metatranscriptomics", title = "Bioinformatics Pipeline",
svgContent = null, // Pass your SVG content here as JSX
svgUrl = "/images/flowchart/metatranscriptomicsrna.svg",
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-blue-200", textColor = "text-gray-700",
textColor = "text-blue-800",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
const topSteps = [
"Raw Sequencing Data (fastq files)",
"Quality Control",
"High Quality Sequencing Data (fastq file)",
"Retain mRNA reads and remove rRNA Reads"
];
const bottomLeftSteps = [
"Reference Genome Alignment",
"Gene Expression Analysis",
"Differential Analysis"
];
const bottomCenterSteps = [
"Transcript Assembly",
"Structural Identification",
"SNPs, SSRs Analysis eQTLs Analysis"
];
const bottomRightSteps = [
"Functional Annotation",
"Statistical Analysis"
];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-6xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block lg:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{topSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < topSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
{/* Bottom sections for mobile */}
<div className="grid grid-cols-1 gap-4 w-full mt-6">
{bottomLeftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}>
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomLeftSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 ${arrowColor} mx-auto`} />
)}
</React.Fragment>
))}
{bottomCenterSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}>
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomCenterSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 ${arrowColor} mx-auto`} />
)}
</React.Fragment>
))}
{bottomRightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}>
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomRightSteps.length - 1 && (
<ArrowDown className={`w-5 h-5 ${arrowColor} mx-auto`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
</div> ) : (
// Fallback message
{/* Desktop Layout */} <div className="flex items-center justify-center h-40 text-gray-500">
<div className="hidden lg:block"> <p>Please provide SVG content or URL</p>
{/* Top vertical sequence */}
<div className="flex flex-col items-center space-y-4 mb-8">
{topSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-96 text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < topSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
)}
{/* Branching arrows from "Retain mRNA reads and remove rRNA Reads" */}
<div className="flex justify-center mb-8">
<div className="relative">
{/* Left branch arrow */}
<div className="absolute -left-32 top-0">
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
</div>
{/* Right branch arrow */}
<div className="absolute left-32 top-0">
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
</div>
</div>
</div>
{/* Bottom three columns */}
<div className="grid grid-cols-3 gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-4">
{bottomLeftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomLeftSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Center Column */}
<div className="flex flex-col items-center space-y-4">
{bottomCenterSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomCenterSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-4">
{bottomRightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < bottomRightSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
</div>
{/* Horizontal arrows connecting bottom sections */}
<div className="absolute bottom-4 left-1/3 transform -translate-x-1/2">
<ArrowRight className={`w-6 h-6 ${arrowColor}`} />
</div>
<div className="absolute bottom-4 right-1/3 transform translate-x-1/2">
<ArrowRight className={`w-6 h-6 ${arrowColor}`} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,98 +1,49 @@
import React from 'react'; import React from 'react';
import { ArrowDown, ArrowRight, ArrowUp } from 'lucide-react';
const SRNABioinformatics = ({ const SRNABioinformatics = ({
title = "Bioinformatics Pipeline", title = "Bioinformatics Pipeline",
leftSteps = [ svgContent = null, // Pass your SVG content here as JSX
"Raw Sequencing Data (fastq files)", svgUrl = "/images/flowchart/smallrna.svg",
"Quality Control and Preprocessing of Data",
"High Quality Sequencing Data (fastq file)",
"Blast Against mRNA, Rfam and RepBase",
"Retained data with no annotation and remove data annotated with mRNA, Rfam and RepBase"
],
rightSteps = [
"Downstream Advanced Analysis",
"Identification of known and Novel microRNA",
"Hairpin Prediction",
"Aligned to Genome",
"Aligned to Genome"
],
backgroundColor = "bg-gray-50", backgroundColor = "bg-gray-50",
cardColor = "bg-gray-300", textColor = "text-gray-700",
textColor = "text-teal-600",
arrowColor = "text-gray-600",
className = "", className = "",
cardClassName = "", titleClassName = "",
titleClassName = "" svgClassName = "",
containerClassName = ""
}) => { }) => {
// Combine steps for mobile layout
const mobileSteps = [...leftSteps, ...rightSteps.slice().reverse()];
return ( return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}> <section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className="container mx-auto max-w-none px-3 sm:px-4 lg:px-6"> <div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`text-gray-700 text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}> <h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title} {title}
</h2> </h2>
{/* Pipeline Flowchart */} {/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8"> <div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center"> <div className="flex justify-center">
<div className="w-full max-w-5xl"> <div className="w-full max-w-6xl">
<div className="relative"> {/* SVG Container with responsive sizing */}
{/* Mobile Layout - Single Column */} <div className={`w-full ${svgClassName}`}>
<div className="block sm:hidden"> {svgUrl ? (
<div className="flex flex-col items-center space-y-3"> // If SVG URL/path is provided
{mobileSteps.map((step, index) => ( <img
<React.Fragment key={index}> src={svgUrl}
<div className={`${cardColor} rounded-lg p-3 w-full text-center border ${cardClassName}`}> alt="Flowchart diagram"
<h3 className={`text-xs font-medium ${textColor}`}>{step}</h3> className="w-full h-auto object-contain"
</div> />
{index < mobileSteps.length - 1 && ( ) : svgContent ? (
<ArrowDown className={`w-5 h-5 ${arrowColor}`} /> // If SVG content is provided as JSX
)} <div className="w-full">
</React.Fragment> <div className="w-full">
))} {svgContent}
</div>
</div>
{/* Desktop Layout - Two Columns */}
<div className="hidden sm:block">
<div className="grid grid-cols-2 gap-4 sm:gap-6 lg:gap-8">
{/* Left Column */}
<div className="flex flex-col items-center space-y-3">
{leftSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < leftSteps.length - 1 && (
<ArrowDown className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div>
{/* Right Column */}
<div className="flex flex-col items-center space-y-3">
{rightSteps.map((step, index) => (
<React.Fragment key={index}>
<div className={`${cardColor} rounded-lg p-4 w-full text-center border ${cardClassName}`} style={{maxWidth: '19rem'}}>
<h3 className={`text-sm font-medium ${textColor}`}>{step}</h3>
</div>
{index < rightSteps.length - 1 && (
<ArrowUp className={`w-6 h-6 ${arrowColor}`} />
)}
</React.Fragment>
))}
</div> </div>
</div> </div>
) : (
{/* Horizontal Arrow from Transcript Assembly to Transcript Assembly Validation */} // Fallback message
<div className="absolute bottom-4 left-1/2 transform -translate-x-1/2 flex items-center justify-center"> <div className="flex items-center justify-center h-40 text-gray-500">
<ArrowRight className={`w-8 h-8 ${arrowColor}`} /> <p>Please provide SVG content or URL</p>
</div> </div>
</div> )}
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,56 @@
import React from 'react';
const WTSPipeline = ({
title = "Bioinformatics Pipeline",
svgContent = null, // Pass your SVG content here as JSX
svgUrl = "/images/flowchart/totalrna.svg",
backgroundColor = "bg-gray-50",
textColor = "text-gray-700",
className = "",
titleClassName = "",
svgClassName = "",
containerClassName = ""
}) => {
return (
<section className={`py-6 sm:py-8 lg:py-12 ${backgroundColor} ${className}`}>
<div className={`container mx-auto max-w-none px-3 sm:px-4 lg:px-6 ${containerClassName}`}>
<h2 className={`${textColor} text-left pb-4 sm:pb-6 text-xl sm:text-2xl lg:text-3xl font-normal ${titleClassName}`}>
{title}
</h2>
{/* SVG Flowchart Container */}
<div className="bg-white rounded-xl shadow-lg p-4 sm:p-6 lg:p-8">
<div className="flex justify-center">
<div className="w-full max-w-6xl">
{/* SVG Container with responsive sizing */}
<div className={`w-full ${svgClassName}`}>
{svgUrl ? (
// If SVG URL/path is provided
<img
src={svgUrl}
alt="Flowchart diagram"
className="w-full h-auto object-contain"
/>
) : svgContent ? (
// If SVG content is provided as JSX
<div className="w-full">
<div className="w-full">
{svgContent}
</div>
</div>
) : (
// Fallback message
<div className="flex items-center justify-center h-40 text-gray-500">
<p>Please provide SVG content or URL</p>
</div>
)}
</div>
</div>
</div>
</div>
</div>
</section>
);
};
export default WTSPipeline;

View File

@ -2,6 +2,7 @@
import TitleBar from '../../components/shared/TitleBar'; import TitleBar from '../../components/shared/TitleBar';
import WTSIntroduction from './components/WTSIntroduction'; import WTSIntroduction from './components/WTSIntroduction';
import WTSAdvantages from './components/WTSAdvantages'; import WTSAdvantages from './components/WTSAdvantages';
import WTSPipeline from './components/WTSPipeline';
import WTSApplications from './components/WTSApplications'; import WTSApplications from './components/WTSApplications';
import WTSSpecifications from './components/WTSSpecifications'; import WTSSpecifications from './components/WTSSpecifications';
import PageLayout from '../../components/Layout/PageLayout'; import PageLayout from '../../components/Layout/PageLayout';
@ -21,6 +22,7 @@ export default function WholeTranscriptomeSequencingPage() {
/> />
<WTSIntroduction /> <WTSIntroduction />
<WTSAdvantages /> <WTSAdvantages />
<WTSPipeline/>
<WTSApplications /> <WTSApplications />
<WTSSpecifications /> <WTSSpecifications />
</PageLayout> </PageLayout>

10
package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "nextjs", "name": "nextjs",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@heroicons/react": "^2.2.0",
"lucide-react": "^0.525.0", "lucide-react": "^0.525.0",
"next": "^15.2.0", "next": "^15.2.0",
"nodemailer": "^7.0.3", "nodemailer": "^7.0.3",
@ -214,6 +215,15 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@heroicons/react": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz",
"integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==",
"license": "MIT",
"peerDependencies": {
"react": ">= 16 || ^19.0.0-rc"
}
},
"node_modules/@humanfs/core": { "node_modules/@humanfs/core": {
"version": "0.19.1", "version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",

View File

@ -9,6 +9,7 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.2.0",
"lucide-react": "^0.525.0", "lucide-react": "^0.525.0",
"next": "^15.2.0", "next": "^15.2.0",
"nodemailer": "^7.0.3", "nodemailer": "^7.0.3",

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 224 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 217 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 202 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 274 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 204 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 249 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 295 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 246 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 222 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 205 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 196 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 257 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 282 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 274 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.4 KiB