// External Library Integration System for Marketplace
class ExternalLibraryIntegration {
constructor() {
this.activeLibrary = 'grabcad';
this.searchTimeout = null;
this.libraryData = {
grabcad: {
name: 'GrabCAD',
baseUrl: 'https://grabcad.com/library',
apiUrl: 'https://grabcad.com/community_api/v1/models',
categories: ['Mechanical', 'Architecture', 'Electronics', 'Tools'],
formats: ['STEP', 'IGES', 'STL', 'DWG']
},
thingiverse: {
name: 'Thingiverse',
baseUrl: 'https://www.thingiverse.com/',
categories: ['3D Printing', 'Toys & Games', 'Art', 'Tools'],
formats: ['STL', 'OBJ', '3MF']
},
ultralibrarian: {
name: 'Ultra Librarian',
baseUrl: 'https://www.ultralibrarian.com/',
categories: ['Electronics', 'PCB', 'Schematic'],
formats: ['STEP', 'IGES', 'Library']
},
wikifactory: {
name: 'Wikifactory',
baseUrl: 'https://wikifactory.com/',
categories: ['Open Source', 'Hardware', 'Industrial'],
formats: ['STL', 'STEP', 'DWG']
},
fusion360: {
name: 'Fusion 360',
baseUrl: 'https://gallery.autodesk.com/',
categories: ['CAD', 'CAM', 'CAE'],
formats: ['F3D', 'STEP', 'IGES']
},
cults: {
name: 'Cults3D',
baseUrl: 'https://cults3d.com/',
categories: ['3D Models', 'Miniatures', 'Art'],
formats: ['STL', 'OBJ']
},
stlfinder: {
name: 'STLFinder',
baseUrl: 'https://www.stlfinder.com/',
categories: ['3D Models', 'STL Files'],
formats: ['STL']
},
actcad: {
name: 'ActCAD',
baseUrl: 'https://www.actcad.com/',
categories: ['CAD', 'Drawing', 'Design'],
formats: ['DWG', 'DXF']
},
canva: {
name: 'Canva',
baseUrl: 'https://www.canva.com/',
categories: ['Templates', 'Graphics', 'Design'],
formats: ['PNG', 'PDF', 'SVG']
}
};
this.init();
}
init() {
this.setupTabNavigation();
this.setupSearch();
this.setupFilters();
this.loadLibraryContent();
}
setupTabNavigation() {
const tabs = document.querySelectorAll('.library-tab');
tabs.forEach(tab => {
tab.addEventListener('click', (e) => {
const library = e.currentTarget.getAttribute('data-library');
this.switchLibrary(library);
});
});
}
setupSearch() {
const searchInput = document.getElementById('global-search');
const searchBtn = document.getElementById('search-btn');
if (searchInput) {
searchInput.addEventListener('input', (e) => {
clearTimeout(this.searchTimeout);
this.searchTimeout = setTimeout(() => {
this.performSearch(e.target.value);
}, 500);
});
}
if (searchBtn) {
searchBtn.addEventListener('click', () => {
const searchTerm = searchInput ? searchInput.value : '';
this.performSearch(searchTerm);
});
}
}
setupFilters() {
const categoryFilter = document.getElementById('category-filter');
const formatFilter = document.getElementById('format-filter');
if (categoryFilter) {
categoryFilter.addEventListener('change', () => {
this.applyFilters();
});
}
if (formatFilter) {
formatFilter.addEventListener('change', () => {
this.applyFilters();
});
}
}
switchLibrary(library) {
// Update active tab
document.querySelectorAll('.library-tab').forEach(tab => {
tab.classList.remove('active');
tab.classList.remove('bg-[var(--primary-color)]', 'text-white');
tab.classList.add('bg-white', 'text-[var(--gray-text-color)]');
});
const activeTab = document.querySelector(`[data-library="${library}"]`);
if (activeTab) {
activeTab.classList.add('active');
activeTab.classList.add('bg-[var(--primary-color)]', 'text-white');
activeTab.classList.remove('bg-white', 'text-[var(--gray-text-color)]');
}
// Update content panels
document.querySelectorAll('.library-panel').forEach(panel => {
panel.classList.add('hidden');
panel.classList.remove('active');
});
let activePanel = document.getElementById(`${library}-panel`);
if (!activePanel) {
// Create panel if it doesn't exist
activePanel = this.createLibraryPanel(library);
}
if (activePanel) {
activePanel.classList.remove('hidden');
activePanel.classList.add('active');
}
this.activeLibrary = library;
this.loadLibraryContent();
}
createLibraryPanel(library) {
const libraryContent = document.getElementById('library-content');
if (!libraryContent) return null;
const data = this.libraryData[library];
if (!data) return null;
const panel = document.createElement('div');
panel.className = 'library-panel';
panel.id = `${library}-panel`;
const colors = {
grabcad: 'blue',
thingiverse: 'red',
ultralibrarian: 'purple',
wikifactory: 'green',
fusion360: 'orange',
cults: 'pink',
stlfinder: 'indigo',
actcad: 'teal',
canva: 'yellow'
};
const color = colors[library] || 'blue';
panel.innerHTML = `
${data.name} Integration
Access thousands of models from ${data.name}. Search, preview, and download directly through Serene Creations.
${data.categories.map(cat =>
`${cat}`
).join('')}
${data.formats.map(format =>
`${format}`
).join('')}
`;
libraryContent.appendChild(panel);
return panel;
}
performSearch(searchTerm) {
console.log(`Searching ${this.activeLibrary} for: ${searchTerm}`);
// Show loading state
this.showSearchLoading();
// Simulate API call with timeout
setTimeout(() => {
const results = this.simulateSearchResults(searchTerm);
this.displaySearchResults(results);
}, 1000);
}
simulateSearchResults(searchTerm) {
// Simulate search results based on active library
const library = this.libraryData[this.activeLibrary];
const sampleResults = [];
for (let i = 0; i < 8; i++) {
sampleResults.push({
title: `${searchTerm || 'Sample'} Model ${i + 1}`,
description: `Professional ${library.name} model for ${searchTerm || 'general use'}`,
format: library.formats[Math.floor(Math.random() * library.formats.length)],
category: library.categories[Math.floor(Math.random() * library.categories.length)],
downloads: Math.floor(Math.random() * 10000),
rating: (Math.random() * 2 + 3).toFixed(1),
url: `${library.baseUrl}/model-${i + 1}`
});
}
return sampleResults;
}
showSearchLoading() {
const activePanel = document.querySelector('.library-panel.active');
if (activePanel) {
const loadingDiv = document.createElement('div');
loadingDiv.id = 'search-loading';
loadingDiv.className = 'text-center py-12';
loadingDiv.innerHTML = `
Searching ${this.libraryData[this.activeLibrary].name}...
`;
// Remove existing loading
const existingLoading = document.getElementById('search-loading');
if (existingLoading) {
existingLoading.remove();
}
activePanel.appendChild(loadingDiv);
}
}
displaySearchResults(results) {
// Remove loading
const loading = document.getElementById('search-loading');
if (loading) {
loading.remove();
}
// Remove existing results
const existingResults = document.getElementById('search-results');
if (existingResults) {
existingResults.remove();
}
const activePanel = document.querySelector('.library-panel.active');
if (!activePanel) return;
const resultsDiv = document.createElement('div');
resultsDiv.id = 'search-results';
resultsDiv.className = 'mt-8';
resultsDiv.innerHTML = `
Search Results (${results.length} found)
Updated just now
${results.map(result => `
${result.title}
${result.description}
${result.format}
${result.rating}
${result.downloads.toLocaleString()}
`).join('')}
`;
activePanel.appendChild(resultsDiv);
}
applyFilters() {
const category = document.getElementById('category-filter')?.value || 'All Categories';
const format = document.getElementById('format-filter')?.value || 'All Formats';
console.log(`Applying filters - Category: ${category}, Format: ${format}`);
// Re-perform search with filters
const searchTerm = document.getElementById('global-search')?.value || '';
this.performSearch(searchTerm);
}
loadLibraryContent() {
// Load initial content for the active library
const activePanel = document.querySelector('.library-panel.active');
if (activePanel && !activePanel.querySelector('#search-results')) {
// Load featured content
this.performSearch('');
}
}
}
// Dropdown functionality for services section
function handleDropdownToggles() {
const dropdownButtons = document.querySelectorAll('[class*="dropdown-btn"]');
dropdownButtons.forEach(button => {
button.addEventListener('click', function() {
const buttonClass = this.className;
let contentClass = '';
if (buttonClass.includes('architecture-dropdown-btn')) {
contentClass = 'architecture-dropdown-content';
} else if (buttonClass.includes('engineering-dropdown-btn')) {
contentClass = 'engineering-dropdown-content';
} else if (buttonClass.includes('consultancy-dropdown-btn')) {
contentClass = 'consultancy-dropdown-content';
} else if (buttonClass.includes('project-dropdown-btn')) {
contentClass = 'project-dropdown-content';
}
const content = document.querySelector(`.${contentClass}`);
const icon = this.querySelector('i');
if (content) {
const isHidden = content.classList.contains('hidden');
if (isHidden) {
content.classList.remove('hidden');
if (icon) {
icon.classList.remove('fa-chevron-down');
icon.classList.add('fa-chevron-up');
}
} else {
content.classList.add('hidden');
if (icon) {
icon.classList.remove('fa-chevron-up');
icon.classList.add('fa-chevron-down');
}
}
}
});
});
}
// Initialize everything
let libraryIntegration;
function init() {
// Initialize external library integration
libraryIntegration = new ExternalLibraryIntegration();
// Initialize dropdown functionality
handleDropdownToggles();
console.log('Marketplace with external library integration initialized');
}
function teardown() {
// Clear any intervals or timeouts
if (libraryIntegration && libraryIntegration.searchTimeout) {
clearTimeout(libraryIntegration.searchTimeout);
}
// Remove event listeners would go here if needed
console.log('Marketplace teardown complete');
}
// Export functions for the page system
export { init, teardown };