diff --git a/src/App.vue b/src/App.vue index 135c1b8..ba3be2f 100644 --- a/src/App.vue +++ b/src/App.vue @@ -16,10 +16,6 @@ export default { filter: window.location.href.split("filter=")[1] || "", sortColumn: this.sortColumn, topics: [], - hoveredTopicId: null, - tooltipData: {}, - loadingTooltip: {}, - tooltipPosition: { x: 0, y: 0 }, isMobile: false, currentTheme: 'dark', mediaQueryListener: null, @@ -81,13 +77,22 @@ export default { this.darkModeQuery = darkModeQuery; }, applyTheme(theme) { - // Apply theme using Vuetify's theme API - this.$vuetify.theme.global.name = theme; + // Apply theme using Vuetify's theme API (using .value for reactive ref) + this.$vuetify.theme.global.name.value = theme; this.currentTheme = theme; localStorage.setItem('vuetify-theme', theme); - // Also update data-bs-theme for any custom CSS that uses it + // Update data-bs-theme attribute for CSS variables to work document.documentElement.setAttribute('data-bs-theme', theme === 'dark' ? 'dark' : 'light'); + + // Update HTML class for theme-based CSS selectors + if (theme === 'dark') { + document.documentElement.classList.add('dark-theme'); + document.documentElement.classList.remove('light-theme'); + } else { + document.documentElement.classList.add('light-theme'); + document.documentElement.classList.remove('dark-theme'); + } }, toggleTheme() { const newTheme = this.currentTheme === 'dark' ? 'light' : 'dark'; @@ -121,63 +126,7 @@ export default { this.$refs.filter.focus(); } }, - handleTitleHover(topic, event) { - // Don't load tooltips on mobile devices - if (this.isMobile) { - return; - } - this.hoveredTopicId = topic.topic_id; - this.tooltipPosition = { - x: event.clientX, - y: event.clientY, - }; - this.loadTopicDetails(topic.topic_id); - }, - handleTitleLeave() { - if (this.isMobile) { - return; - } - this.hoveredTopicId = null; - }, - handleMouseMove(event) { - if (this.isMobile) { - return; - } - if (this.hoveredTopicId !== null) { - this.tooltipPosition = { - x: event.clientX, - y: event.clientY, - }; - } - }, - loadTopicDetails(topicId) { - if (!topicId) { - console.warn("Topic ID is undefined"); - return; - } - if (this.tooltipData[topicId]) { - return; // Already loaded - } - - if (this.loadingTooltip[topicId]) { - return; // Already loading - } - - this.loadingTooltip[topicId] = true; - - axios - .get(`api/v1/topics/${topicId}`) - .then((response) => { - this.tooltipData[topicId] = response.data; - }) - .catch((err) => { - console.log("Error loading topic details:", err); - }) - .finally(() => { - this.loadingTooltip[topicId] = false; - }); - }, createFilterRoute(params) { this.$refs.filter.blur(); history.pushState( @@ -205,16 +154,18 @@ export default { }; }, filteredTopics() { - return this.topics.filter((row) => { - const titles = ( - row.title.toString() + - " [" + - row.Offer.dealer_name + - "]" - ).toLowerCase(); - const filterTerm = this.filter.toLowerCase(); - return titles.includes(filterTerm); - }); + return this.topics + .filter((row) => { + const titles = ( + row.title.toString() + + " [" + + row.Offer.dealer_name + + "]" + ).toLowerCase(); + const filterTerm = this.filter.toLowerCase(); + return titles.includes(filterTerm); + }) + .sort((a, b) => b.score - a.score); // Always sort by score descending }, highlightMatches() { return (v) => { @@ -226,46 +177,14 @@ export default { return v.replace(re, (matchedText) => `${matchedText}`); }; }, - visibleHeaders() { - const baseHeaders = [ - { title: "Deal", value: "title", align: "center" }, - { title: "Score", value: "score", align: "center" }, - ]; + highlightDealerName() { + return (dealerName) => { + if (this.filter == "") return dealerName; + const matchExists = dealerName.toLowerCase().includes(this.filter.toLowerCase()); + if (!matchExists) return dealerName; - // Only show Last Post column on desktop - if (!this.isMobile) { - baseHeaders.push({ - title: "Last Post", - value: "last_post_time", - align: "center", - }); - } - - return baseHeaders; - }, - tooltipStyle() { - if (this.hoveredTopicId === null || !this.tooltipData[this.hoveredTopicId]) { - return {}; - } - - let top = this.tooltipPosition.y + 10; - let left = this.tooltipPosition.x + 10; - const tooltipWidth = 420; - - // Check if tooltip would go off right side of screen - if (left + tooltipWidth > window.innerWidth) { - // Position to the left of cursor instead - left = Math.max(10, this.tooltipPosition.x - tooltipWidth - 10); - } - - // Keep tooltip within vertical bounds, allowing scrolling of content - top = Math.max(10, Math.min(top, window.innerHeight - 100)); - - return { - position: 'fixed', - left: Math.max(10, left) + 'px', - top: top + 'px', - zIndex: 9999, + const re = new RegExp(this.filter, "ig"); + return dealerName.replace(re, (matchedText) => `${matchedText}`); }; }, }, @@ -280,195 +199,281 @@ const sortBy = ref([{ key: "score", order: "desc" }]); - - - - +
+
+ +
- - - - - - - - -
-
-
- - visibility - {{ tooltipData[hoveredTopicId].topic.total_views }} views - - - chat - {{ tooltipData[hoveredTopicId].topic.total_replies }} replies - +
+
+
+ +
+ +{{ topic.score }} + {{ topic.score }}
-
- Description: - {{ tooltipData[hoveredTopicId].description }}
-
- {{ tooltipData[hoveredTopicId].topic.Offer.dealer_name }} + +
+
-
- First Post: - {{ tooltipData[hoveredTopicId].first_post }} -
-
-
Posted: {{ formatDate(tooltipData[hoveredTopicId].topic.post_time) }}
-
Last Post: {{ formatDate(tooltipData[hoveredTopicId].topic.last_post_time) }}
+ + +
+
+
+ visibility + {{ topic.total_views }} views +
+
+ chat + {{ topic.total_replies }} replies +
+
+ +
+ Last post: {{ formatDate(topic.last_post_time) }} +
+
- +
diff --git a/src/theme.css b/src/theme.css index ec471ab..711f745 100644 --- a/src/theme.css +++ b/src/theme.css @@ -15,16 +15,12 @@ /* Theme-aware CSS variables */ :root { /* Light theme (default) */ - --bg-primary: #ffffff; - --bg-secondary: #f5f5f5; + --bg-primary: #dddddd; + --bg-secondary: #eeeeee; --text-primary: #212529; --text-secondary: #6c757d; - --border-color: #dee2e6; - --tooltip-bg: #f8f9fa; - --tooltip-border: #dee2e6; - --tooltip-text: #212529; - --link-color: #0d6efd; - --link-visited: #990000; + --border-color: #d0d0d0; + --link-color: #212529; --footer-bg: #f8f9fa; --footer-text: #212529; } @@ -37,11 +33,7 @@ --text-primary: #e0e0e0; --text-secondary: #a0a0a0; --border-color: #3a3a3a; - --tooltip-bg: #2a2a2a; - --tooltip-border: #444444; - --tooltip-text: #e0e0e0; - --link-color: #5b9cf5; - --link-visited: #990000; + --link-color: #212529; --footer-bg: #1a1a1a; --footer-text: #e0e0e0; } @@ -54,42 +46,39 @@ html[data-bs-theme="dark"] { --text-primary: #e0e0e0; --text-secondary: #a0a0a0; --border-color: #3a3a3a; - --tooltip-bg: #2a2a2a; - --tooltip-border: #444444; - --tooltip-text: #e0e0e0; - --link-color: #e8e8e8; - --link-visited: #990000; + --link-color: ##e0e0e0; --footer-bg: #1a1a1a; --footer-text: #e0e0e0; } -html[data-bs-theme="light"] { - --bg-primary: #ffffff; - --bg-secondary: #f5f5f5; +html[data-bs-theme="light"], +html.light-theme { + --bg-primary: #dddddd; + --bg-secondary: #eeeeee; --text-primary: #212529; --text-secondary: #6c757d; - --border-color: #dee2e6; - --tooltip-bg: #f8f9fa; - --tooltip-border: #dee2e6; - --tooltip-text: #212529; - --link-color: #333333; - --link-visited: #990000; + --border-color: #d0d0d0; + --link-color: #212529; --footer-bg: #f8f9fa; --footer-text: #212529; } -body { - max-width: 100%; - background-color: var(--bg-primary); - color: var(--text-primary); - transition: background-color 0.3s ease, color 0.3s ease; -} - html { font-family: sans-serif; min-width: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; + background-color: var(--bg-primary); + color: var(--text-primary); +} + +body { + max-width: 100%; + background-color: var(--bg-primary); + color: var(--text-primary); + transition: background-color 0.3s ease, color 0.3s ease; + margin: 0; + padding: 0; } footer { @@ -130,10 +119,8 @@ a { transition: color 0.2s ease; } - - a:visited { - color: var(--link-visited); + color: var(--link-color); } @media (min-width: 769px) { @@ -144,89 +131,70 @@ a:visited { } } -/* Tooltip theme support */ -.deal-tooltip { - pointer-events: none; - max-width: 400px; +/* Vuetify table dark theme overrides */ +html.dark-theme .v-data-table { + background-color: #1a1a1a !important; + color: #e0e0e0 !important; } -.tooltip-content { - background: var(--tooltip-bg); - border: 2px solid var(--tooltip-border); - border-radius: 8px; - padding: 16px; - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); - font-size: 13px; - color: var(--tooltip-text); - text-align: left; - transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease; +html.dark-theme .v-data-table__tr { + background-color: #1a1a1a !important; + color: #e0e0e0 !important; } -.tooltip-header { - font-weight: bold; - font-size: 14px; - color: var(--text-primary); - margin-bottom: 8px; - white-space: normal; - word-wrap: break-word; +html.dark-theme .v-data-table__td { + background-color: #1a1a1a !important; + color: #e0e0e0 !important; + border-color: #888888 !important; } -.tooltip-dealer { - font-size: 12px; - color: var(--text-secondary); - margin-bottom: 8px; +html.dark-theme .v-data-table-header { + background-color: #2a2a2a !important; } -.tooltip-stats { - display: flex; - gap: 12px; - margin-bottom: 8px; - font-size: 12px; - color: var(--text-secondary); +html.dark-theme .v-data-table-header th { + background-color: #2a2a2a !important; + color: #e0e0e0 !important; + border-color: #888888 !important; } -.stat-item { - display: flex; - align-items: center; - gap: 4px; +html.dark-theme .v-data-footer { + background-color: #2a2a2a !important; + color: #e0e0e0 !important; + border-color: #888888 !important; } -.stat-item .material-symbols-outlined { - font-size: 16px; +html.dark-theme .v-data-table__divider { + border-color: #888888 !important; } -.tooltip-description { - margin-bottom: 8px; - padding: 8px; - background: var(--bg-secondary); - border-left: 2px solid var(--tooltip-border); - border-radius: 2px; - font-size: 12px; - white-space: normal; - word-wrap: break-word; - max-height: 60px; - overflow-y: auto; - color: var(--text-primary); +html.dark-theme .v-table__wrapper { + background-color: #1a1a1a !important; } -.tooltip-first-post { - margin-bottom: 8px; - padding: 8px; - background: var(--bg-secondary); - border-left: 2px solid var(--tooltip-border); - border-radius: 2px; - font-size: 12px; - white-space: normal; - word-wrap: break-word; - max-height: 60px; - overflow-y: auto; - color: var(--text-primary); +/* Light theme table overrides */ +html.light-theme .v-data-table { + background-color: #ffffff !important; + color: #212529 !important; } -.tooltip-times { - font-size: 11px; - color: var(--text-secondary); - border-top: 1px solid var(--border-color); - padding-top: 8px; - margin-top: 8px; +html.light-theme .v-data-table__tr { + background-color: #ffffff !important; + color: #212529 !important; +} + +html.light-theme .v-data-table__td { + background-color: #ffffff !important; + color: #212529 !important; + border-color: #dee2e6 !important; +} + +html.light-theme .v-data-table-header { + background-color: #f5f5f5 !important; +} + +html.light-theme .v-data-table-header th { + background-color: #f5f5f5 !important; + color: #212529 !important; + border-color: #dee2e6 !important; }