Spaces:
Running
Running
Promote version eb0e9cf to main
Browse filesPromoted commit eb0e9cfab91d246ed3cf565ff971378f1f9f3754 to main branch
- index.html +21 -105
index.html
CHANGED
|
@@ -1002,20 +1002,18 @@
|
|
| 1002 |
<div class="card-3d-container mb-4">
|
| 1003 |
<div class="card-3d" id="card-3d">
|
| 1004 |
<div class="card-face">
|
| 1005 |
-
<div id="card-image" class="w-full h-full bg-gray-900 flex items-center justify-center
|
| 1006 |
<div class="text-center glass-card p-8">
|
| 1007 |
<i class="fas fa-cube text-5xl text-white/30 mb-4"></i>
|
| 1008 |
<p class="text-white/60">Initializing...</p>
|
| 1009 |
</div>
|
| 1010 |
-
<button id="find-similar-btn" class="absolute bottom-4 left-1/2 transform -translate-x-1/2 glass-button hidden" onclick="findSimilarForCurrentFace()">
|
| 1011 |
-
<i class="fas fa-search mr-2"></i>Find Similar
|
| 1012 |
-
</button>
|
| 1013 |
</div>
|
| 1014 |
<div id="face-indicator" class="absolute top-4 right-4 price-tag hidden">Face 1/2</div>
|
| 1015 |
</div>
|
| 1016 |
</div>
|
| 1017 |
</div>
|
| 1018 |
-
|
|
|
|
| 1019 |
<div class="flex gap-2 mb-4">
|
| 1020 |
<button id="random-btn" class="glass-button">
|
| 1021 |
<i class="fas fa-shuffle mr-2"></i>Random
|
|
@@ -1615,6 +1613,7 @@
|
|
| 1615 |
// Update gallery header back to "Similar Cards"
|
| 1616 |
$('gallery-header').textContent = 'Similar Cards';
|
| 1617 |
}
|
|
|
|
| 1618 |
function displayCardFace(card, faceIndex) {
|
| 1619 |
const hasFaces = card.card_faces?.length > 1;
|
| 1620 |
const face = hasFaces ? card.card_faces[faceIndex] : card;
|
|
@@ -1622,21 +1621,10 @@
|
|
| 1622 |
|
| 1623 |
// Update image
|
| 1624 |
if (imageUris?.large) {
|
| 1625 |
-
$('card-image').innerHTML =
|
| 1626 |
-
<img src="${imageUris.large}" alt="${face.name}" class="w-full h-full object-contain">
|
| 1627 |
-
<button id="find-similar-btn" class="absolute bottom-4 left-1/2 transform -translate-x-1/2 glass-button opacity-0 transition-opacity duration-200"
|
| 1628 |
-
onclick="findSimilarForCurrentFace()">
|
| 1629 |
-
<i class="fas fa-search mr-2"></i>Find Similar
|
| 1630 |
-
</button>
|
| 1631 |
-
`;
|
| 1632 |
-
|
| 1633 |
-
// Add hover effect to show the button
|
| 1634 |
-
const img = $('card-image').querySelector('img');
|
| 1635 |
-
const btn = $('card-image').querySelector('button');
|
| 1636 |
-
img.addEventListener('mouseenter', () => btn.classList.remove('opacity-0'));
|
| 1637 |
-
img.addEventListener('mouseleave', () => btn.classList.add('opacity-0'));
|
| 1638 |
}
|
| 1639 |
-
|
|
|
|
| 1640 |
if (hasFaces) {
|
| 1641 |
$('face-nav').classList.remove('hidden');
|
| 1642 |
$('face-indicator').classList.remove('hidden');
|
|
@@ -1868,19 +1856,13 @@
|
|
| 1868 |
// Final cleaning
|
| 1869 |
return cardStr.replace(/, ,/g, ',');
|
| 1870 |
}
|
| 1871 |
-
|
|
|
|
| 1872 |
try {
|
| 1873 |
-
|
| 1874 |
-
|
| 1875 |
-
// Build query for specific face
|
| 1876 |
-
query = buildCardQueryString(card.card_faces[faceIndex]);
|
| 1877 |
-
} else {
|
| 1878 |
-
// Build query for whole card
|
| 1879 |
-
query = buildCardQueryString(card);
|
| 1880 |
-
}
|
| 1881 |
-
|
| 1882 |
currentGalleryQuery = query;
|
| 1883 |
-
console.log('Query string:', query);
|
| 1884 |
|
| 1885 |
// Build URL with gallery color filters
|
| 1886 |
let url = `https://api.deck.doctor/v1/mtg/search?q=${encodeURIComponent(query)}&topk=12&price_threshold=0`;
|
|
@@ -1896,91 +1878,25 @@
|
|
| 1896 |
if (data?.length > 0) {
|
| 1897 |
// Filter out the current card more robustly
|
| 1898 |
const filteredResults = data.filter(([c]) => {
|
|
|
|
| 1899 |
return c.id !== card.id &&
|
| 1900 |
c.name !== card.name &&
|
| 1901 |
(!c.scryfall_uri || c.scryfall_uri !== card.scryfall_uri);
|
| 1902 |
-
});
|
| 1903 |
-
|
| 1904 |
-
// Get existing gallery cards
|
| 1905 |
-
const existingCards = Array.from($('gallery').querySelectorAll('.gallery-item'))
|
| 1906 |
-
.map(el => el.querySelector('h4')?.textContent)
|
| 1907 |
-
.filter(Boolean);
|
| 1908 |
|
| 1909 |
-
|
| 1910 |
-
|
| 1911 |
-
!existingCards.includes(c.name)
|
| 1912 |
-
).slice(0, 11); // Limit to 11 new cards
|
| 1913 |
|
| 1914 |
-
if
|
| 1915 |
-
|
| 1916 |
-
|
| 1917 |
-
const newCards = uniqueResults.map(([card, score]) => createGalleryCard(card, score)).join('');
|
| 1918 |
-
$('gallery').innerHTML = currentGallery + newCards;
|
| 1919 |
-
|
| 1920 |
-
if ($('gallery-section').classList.contains('hidden')) {
|
| 1921 |
-
$('gallery-section').classList.remove('hidden');
|
| 1922 |
-
}
|
| 1923 |
-
|
| 1924 |
-
// Update header if filters are active
|
| 1925 |
-
const colorFilterText = galleryColors.size > 0 ? ` (${Array.from(galleryColors).join('')})` : '';
|
| 1926 |
-
$('gallery-header').textContent = `Similar Cards${colorFilterText}`;
|
| 1927 |
-
}
|
| 1928 |
}
|
| 1929 |
} catch (error) {
|
| 1930 |
console.error('Gallery error:', error);
|
| 1931 |
}
|
| 1932 |
}
|
| 1933 |
-
|
| 1934 |
-
function
|
| 1935 |
-
if (!currentCard) return;
|
| 1936 |
-
setLoading(true);
|
| 1937 |
-
|
| 1938 |
-
// If card has multiple faces, search for current face
|
| 1939 |
-
if (currentCard.card_faces?.length > 1) {
|
| 1940 |
-
fetchSimilarCards(currentCard, currentFace);
|
| 1941 |
-
} else {
|
| 1942 |
-
fetchSimilarCards(currentCard);
|
| 1943 |
-
}
|
| 1944 |
-
|
| 1945 |
-
setLoading(false);
|
| 1946 |
-
}
|
| 1947 |
-
|
| 1948 |
-
function createGalleryCard(card, score) {
|
| 1949 |
-
return `
|
| 1950 |
-
<div class="gallery-item">
|
| 1951 |
-
<img src="${card.image_uris?.normal || ''}" alt="${card.name}" class="w-full h-full object-cover">
|
| 1952 |
-
${card.prices?.usd ? `<div class="absolute top-2 left-2 price-tag text-xs">${parseFloat(card.prices.usd).toFixed(2)}</div>` : ''}
|
| 1953 |
-
<div class="gallery-overlay">
|
| 1954 |
-
<div class="gallery-overlay-content">
|
| 1955 |
-
<h4 class="font-semibold text-white line-clamp-2 mb-2">${card.name}</h4>
|
| 1956 |
-
${card.mana_cost ? `<div class="gallery-mana-cost mb-2">${formatManaCost(card.mana_cost)}</div>` : ''}
|
| 1957 |
-
<p class="text-xs text-white/60 line-clamp-2 mb-2">${card.type_line}</p>
|
| 1958 |
-
${card.oracle_text ? `<p class="text-xs text-white/50 line-clamp-3 mb-3">${card.oracle_text}</p>` : ''}
|
| 1959 |
-
<p class="text-xs text-white/40 mb-3">${Math.round(score * 100)}% similar</p>
|
| 1960 |
-
|
| 1961 |
-
<div class="gallery-actions">
|
| 1962 |
-
<button onclick="loadCard('${card.id}')" class="gallery-btn gallery-btn-view">
|
| 1963 |
-
<i class="fas fa-eye"></i>
|
| 1964 |
-
View Card
|
| 1965 |
-
</button>
|
| 1966 |
-
${card.purchase_uris?.tcgplayer ? `
|
| 1967 |
-
<a href="${card.purchase_uris.tcgplayer}" target="_blank" class="gallery-btn">
|
| 1968 |
-
<i class="fas fa-shopping-cart"></i>
|
| 1969 |
-
TCG
|
| 1970 |
-
</a>
|
| 1971 |
-
` : card.purchase_uris?.cardmarket ? `
|
| 1972 |
-
<a href="${card.purchase_uris.cardmarket}" target="_blank" class="gallery-btn">
|
| 1973 |
-
<i class="fas fa-shopping-cart"></i>
|
| 1974 |
-
CM
|
| 1975 |
-
</a>
|
| 1976 |
-
` : ''}
|
| 1977 |
-
</div>
|
| 1978 |
-
</div>
|
| 1979 |
-
</div>
|
| 1980 |
-
</div>
|
| 1981 |
-
`;
|
| 1982 |
-
}
|
| 1983 |
-
function displayGallery(cards) {
|
| 1984 |
$('gallery').innerHTML = cards.map(([card, score]) => `
|
| 1985 |
<div class="gallery-item">
|
| 1986 |
<img src="${card.image_uris?.normal || ''}" alt="${card.name}" class="w-full h-full object-cover">
|
|
|
|
| 1002 |
<div class="card-3d-container mb-4">
|
| 1003 |
<div class="card-3d" id="card-3d">
|
| 1004 |
<div class="card-face">
|
| 1005 |
+
<div id="card-image" class="w-full h-full bg-gray-900 flex items-center justify-center">
|
| 1006 |
<div class="text-center glass-card p-8">
|
| 1007 |
<i class="fas fa-cube text-5xl text-white/30 mb-4"></i>
|
| 1008 |
<p class="text-white/60">Initializing...</p>
|
| 1009 |
</div>
|
|
|
|
|
|
|
|
|
|
| 1010 |
</div>
|
| 1011 |
<div id="face-indicator" class="absolute top-4 right-4 price-tag hidden">Face 1/2</div>
|
| 1012 |
</div>
|
| 1013 |
</div>
|
| 1014 |
</div>
|
| 1015 |
+
|
| 1016 |
+
<!-- Controls -->
|
| 1017 |
<div class="flex gap-2 mb-4">
|
| 1018 |
<button id="random-btn" class="glass-button">
|
| 1019 |
<i class="fas fa-shuffle mr-2"></i>Random
|
|
|
|
| 1613 |
// Update gallery header back to "Similar Cards"
|
| 1614 |
$('gallery-header').textContent = 'Similar Cards';
|
| 1615 |
}
|
| 1616 |
+
|
| 1617 |
function displayCardFace(card, faceIndex) {
|
| 1618 |
const hasFaces = card.card_faces?.length > 1;
|
| 1619 |
const face = hasFaces ? card.card_faces[faceIndex] : card;
|
|
|
|
| 1621 |
|
| 1622 |
// Update image
|
| 1623 |
if (imageUris?.large) {
|
| 1624 |
+
$('card-image').innerHTML = `<img src="${imageUris.large}" alt="${face.name}" class="w-full h-full object-contain">`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1625 |
}
|
| 1626 |
+
|
| 1627 |
+
// Update face navigation
|
| 1628 |
if (hasFaces) {
|
| 1629 |
$('face-nav').classList.remove('hidden');
|
| 1630 |
$('face-indicator').classList.remove('hidden');
|
|
|
|
| 1856 |
// Final cleaning
|
| 1857 |
return cardStr.replace(/, ,/g, ',');
|
| 1858 |
}
|
| 1859 |
+
|
| 1860 |
+
async function fetchSimilarCards(card) {
|
| 1861 |
try {
|
| 1862 |
+
// Build the query string using the same logic as Python
|
| 1863 |
+
const query = buildCardQueryString(card);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1864 |
currentGalleryQuery = query;
|
| 1865 |
+
console.log('Query string:', query); // Debug logging
|
| 1866 |
|
| 1867 |
// Build URL with gallery color filters
|
| 1868 |
let url = `https://api.deck.doctor/v1/mtg/search?q=${encodeURIComponent(query)}&topk=12&price_threshold=0`;
|
|
|
|
| 1878 |
if (data?.length > 0) {
|
| 1879 |
// Filter out the current card more robustly
|
| 1880 |
const filteredResults = data.filter(([c]) => {
|
| 1881 |
+
// Check multiple identifiers to ensure we exclude the current card
|
| 1882 |
return c.id !== card.id &&
|
| 1883 |
c.name !== card.name &&
|
| 1884 |
(!c.scryfall_uri || c.scryfall_uri !== card.scryfall_uri);
|
| 1885 |
+
}).slice(0, 11); // Take at most 11 cards after filtering
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1886 |
|
| 1887 |
+
displayGallery(filteredResults);
|
| 1888 |
+
$('gallery-section').classList.remove('hidden');
|
|
|
|
|
|
|
| 1889 |
|
| 1890 |
+
// Update header if filters are active
|
| 1891 |
+
const colorFilterText = galleryColors.size > 0 ? ` (${Array.from(galleryColors).join('')})` : '';
|
| 1892 |
+
$('gallery-header').textContent = `Similar Cards${colorFilterText}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1893 |
}
|
| 1894 |
} catch (error) {
|
| 1895 |
console.error('Gallery error:', error);
|
| 1896 |
}
|
| 1897 |
}
|
| 1898 |
+
|
| 1899 |
+
function displayGallery(cards) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1900 |
$('gallery').innerHTML = cards.map(([card, score]) => `
|
| 1901 |
<div class="gallery-item">
|
| 1902 |
<img src="${card.image_uris?.normal || ''}" alt="${card.name}" class="w-full h-full object-cover">
|