pearsonkyle commited on
Commit
fca7899
·
verified ·
1 Parent(s): 1c9c26d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +97 -16
index.html CHANGED
@@ -680,7 +680,7 @@
680
  Deck Doctor
681
  </h1>
682
  <div class="flex justify-center gap-5 md:gap-8 text-xs md:text-sm flex-wrap">
683
- <span class="text-white/40"><i class="fas fa-shield-alt mr-2"></i>Name Search</span>
684
  <span class="text-white/40"><i class="fas fa-chart-line mr-2"></i>Deck Analysis</span>
685
  <span class="text-white/40"><i class="fas fa-search mr-2"></i>Smart Discovery</span>
686
  </div>
@@ -688,13 +688,14 @@
688
  <!-- Search -->
689
  <div class="search-container">
690
  <i class="fas fa-search search-icon"></i>
691
- <input
692
- type="text"
693
  id="search-input"
694
  class="search-input"
695
- placeholder="Search for cards or terms..."
696
  autocomplete="off"
697
- >
 
 
698
  <button class="search-clear" id="search-clear" aria-label="Clear">
699
  <i class="fas fa-times"></i>
700
  </button>
@@ -870,12 +871,28 @@
870
  });
871
  }
872
 
 
 
 
 
 
 
873
  // Search Functions
874
  function handleSearch(e) {
875
  const query = e.target.value.trim();
876
  searchClear.classList.toggle('visible', query.length > 0);
877
 
878
  clearTimeout(searchTimeout);
 
 
 
 
 
 
 
 
 
 
879
  if (query.length < 2) {
880
  hideAutocomplete();
881
  return;
@@ -886,18 +903,30 @@
886
 
887
  function handleSearchKey(e) {
888
  const query = searchInput.value.trim();
 
889
 
890
  if (e.key === 'Enter' && query.length > 0) {
891
- e.preventDefault();
892
- hideAutocomplete();
 
 
 
 
 
893
 
894
- // Check if user selected from autocomplete or is typing a custom query
895
- if (autocompleteResults.length > 0 && autocompleteResults.includes(query)) {
896
- // Exact match from autocomplete
897
- selectCard(query);
898
- } else {
899
- // Custom search query - use Deck Doctor search
900
- performDeckDoctorSearch(query);
 
 
 
 
 
 
901
  }
902
  }
903
  }
@@ -1000,6 +1029,57 @@
1000
  setLoading(false);
1001
  }
1002
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1003
 
1004
  // Search Mode Management
1005
  function enterSearchMode(query, results) {
@@ -1034,11 +1114,12 @@
1034
  searchResultsContainer.innerHTML = results.map(([card, score]) => `
1035
  <div class="gallery-item" onclick="loadCardFromSearch('${card.id}')">
1036
  <img src="${card.image_uris?.normal || ''}" alt="${card.name}" class="w-full h-full object-cover">
1037
- ${card.prices?.usd ? `<div class="absolute bottom-2 left-2 price-tag text-xs">$${parseFloat(card.prices.usd).toFixed(2)}</div>` : ''}
1038
  <div class="gallery-overlay">
1039
  <h4 class="font-semibold text-white line-clamp-2">${card.name}</h4>
1040
  <p class="text-xs text-white/60 mt-1">${card.type_line}</p>
1041
- <p class="text-xs text-white/40 mt-1">${Math.round(score * 100)}% match</p>
 
1042
  </div>
1043
  </div>
1044
  `).join('');
 
680
  Deck Doctor
681
  </h1>
682
  <div class="flex justify-center gap-5 md:gap-8 text-xs md:text-sm flex-wrap">
683
+ <span class="text-white/40"><i class="fas fa-shield-alt mr-2"></i>Card Search</span>
684
  <span class="text-white/40"><i class="fas fa-chart-line mr-2"></i>Deck Analysis</span>
685
  <span class="text-white/40"><i class="fas fa-search mr-2"></i>Smart Discovery</span>
686
  </div>
 
688
  <!-- Search -->
689
  <div class="search-container">
690
  <i class="fas fa-search search-icon"></i>
691
+ <textarea
 
692
  id="search-input"
693
  class="search-input"
694
+ placeholder="Search for cards, terms or paste a deck list..."
695
  autocomplete="off"
696
+ rows="1"
697
+ oninput="autoResize(this)"
698
+ ></textarea>
699
  <button class="search-clear" id="search-clear" aria-label="Clear">
700
  <i class="fas fa-times"></i>
701
  </button>
 
871
  });
872
  }
873
 
874
+ // Auto-resize textarea
875
+ function autoResize(textarea) {
876
+ textarea.style.height = 'auto';
877
+ textarea.style.height = Math.min(textarea.scrollHeight, 200) + 'px';
878
+ }
879
+
880
  // Search Functions
881
  function handleSearch(e) {
882
  const query = e.target.value.trim();
883
  searchClear.classList.toggle('visible', query.length > 0);
884
 
885
  clearTimeout(searchTimeout);
886
+
887
+ // Check if this looks like a decklist (multiple lines)
888
+ const lines = query.split('\n').filter(line => line.trim().length > 0);
889
+
890
+ if (lines.length > 5) {
891
+ // This is likely a decklist - don't show autocomplete
892
+ hideAutocomplete();
893
+ return;
894
+ }
895
+
896
  if (query.length < 2) {
897
  hideAutocomplete();
898
  return;
 
903
 
904
  function handleSearchKey(e) {
905
  const query = searchInput.value.trim();
906
+ const lines = query.split('\n').filter(line => line.trim().length > 0);
907
 
908
  if (e.key === 'Enter' && query.length > 0) {
909
+ // Handle decklist if more than 5 lines
910
+ if (lines.length > 5) {
911
+ e.preventDefault();
912
+ hideAutocomplete();
913
+ processDecklist(query);
914
+ return;
915
+ }
916
 
917
+ // Handle single card search
918
+ if (!e.shiftKey) { // Allow Shift+Enter for newlines in regular searches
919
+ e.preventDefault();
920
+ hideAutocomplete();
921
+
922
+ // Check if user selected from autocomplete or is typing a custom query
923
+ if (autocompleteResults.length > 0 && autocompleteResults.includes(query)) {
924
+ // Exact match from autocomplete
925
+ selectCard(query);
926
+ } else {
927
+ // Custom search query - use Deck Doctor search
928
+ performDeckDoctorSearch(query);
929
+ }
930
  }
931
  }
932
  }
 
1029
  setLoading(false);
1030
  }
1031
  }
1032
+
1033
+ // Process decklist
1034
+ async function processDecklist(decklistText) {
1035
+ setLoading(true);
1036
+ showToast('Processing decklist...', 'success');
1037
+
1038
+ try {
1039
+ // Parse decklist - extract card names (simple parsing)
1040
+ const lines = decklistText.split('\n')
1041
+ .filter(line => line.trim().length > 0)
1042
+ .map(line => {
1043
+ // Remove quantity numbers and set codes if present
1044
+ return line.replace(/^\d+\s*/, '') // Remove leading numbers
1045
+ .replace(/\s*\(.*?\)\s*$/, '') // Remove set codes in parentheses
1046
+ .replace(/\s*\*.*?\*\s*$/, '') // Remove any *footnotes*
1047
+ .trim();
1048
+ })
1049
+ .filter(name => name.length > 0);
1050
+
1051
+ if (lines.length === 0) {
1052
+ showToast('No valid card names found in decklist', 'error');
1053
+ return;
1054
+ }
1055
+
1056
+ // Search for each card in the decklist
1057
+ const deckCards = [];
1058
+ for (const cardName of lines) {
1059
+ try {
1060
+ const response = await fetch(`https://api.scryfall.com/cards/named?exact=${encodeURIComponent(cardName)}`);
1061
+ if (response.ok) {
1062
+ const card = await response.json();
1063
+ deckCards.push([card, 1.0]); // Use 1.0 as similarity score for decklist items
1064
+ }
1065
+ } catch (error) {
1066
+ console.warn(`Could not find card: ${cardName}`);
1067
+ }
1068
+ }
1069
+
1070
+ if (deckCards.length > 0) {
1071
+ enterSearchMode(`Decklist (${deckCards.length} cards)`, deckCards);
1072
+ showToast(`Loaded ${deckCards.length} cards from decklist`, 'success');
1073
+ } else {
1074
+ showToast('No valid cards found in decklist', 'error');
1075
+ }
1076
+ } catch (error) {
1077
+ console.error('Decklist processing error:', error);
1078
+ showToast('Failed to process decklist', 'error');
1079
+ } finally {
1080
+ setLoading(false);
1081
+ }
1082
+ }
1083
 
1084
  // Search Mode Management
1085
  function enterSearchMode(query, results) {
 
1114
  searchResultsContainer.innerHTML = results.map(([card, score]) => `
1115
  <div class="gallery-item" onclick="loadCardFromSearch('${card.id}')">
1116
  <img src="${card.image_uris?.normal || ''}" alt="${card.name}" class="w-full h-full object-cover">
1117
+ ${card.prices?.usd ? `<div class="absolute bottom-2 left-2 price-tag text-xs">${parseFloat(card.prices.usd).toFixed(2)}</div>` : ''}
1118
  <div class="gallery-overlay">
1119
  <h4 class="font-semibold text-white line-clamp-2">${card.name}</h4>
1120
  <p class="text-xs text-white/60 mt-1">${card.type_line}</p>
1121
+ ${score < 1.0 ? `<p class="text-xs text-white/40 mt-1">${Math.round(score * 100)}% match</p>` :
1122
+ score === 1.0 ? `<p class="text-xs text-white/40 mt-1">From decklist</p>` : ''}
1123
  </div>
1124
  </div>
1125
  `).join('');