mirror of
https://github.com/davegallant/rfd-fyi.git
synced 2026-03-03 09:36:35 +00:00
Add more shortcuts and info panel
This commit is contained in:
58
src/App.vue
58
src/App.vue
@@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import InfoOverlay from "./components/InfoOverlay.vue";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
@@ -65,6 +66,7 @@ export default {
|
|||||||
themeChangeHandler: null,
|
themeChangeHandler: null,
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
|
infoOverlayVisible: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -242,6 +244,31 @@ export default {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.fetchDeals();
|
this.fetchDeals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.key === "i" && !isInput) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleInfoOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "Escape" && this.infoOverlayVisible) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleInfoOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "s" && !isInput) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleSort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "v" && !isInput) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleViewMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.key === "t" && !isInput) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.toggleTheme();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
parseFiltersFromUrl() {
|
parseFiltersFromUrl() {
|
||||||
@@ -377,6 +404,14 @@ export default {
|
|||||||
color: color.text,
|
color: color.text,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
toggleInfoOverlay() {
|
||||||
|
this.infoOverlayVisible = !this.infoOverlayVisible;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleInfoOverlay() {
|
||||||
|
this.infoOverlayVisible = !this.infoOverlayVisible;
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
@@ -416,8 +451,9 @@ export default {
|
|||||||
<button class="icon-button desktop-only" :title="themeTitle" @click="toggleTheme">
|
<button class="icon-button desktop-only" :title="themeTitle" @click="toggleTheme">
|
||||||
<span class="material-symbols-outlined">{{ themeIcon }}</span>
|
<span class="material-symbols-outlined">{{ themeIcon }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="icon-button desktop-only" title="Info" @click="toggleInfoOverlay">
|
||||||
<!-- Mobile hamburger menu -->
|
<span class="material-symbols-outlined">info</span>
|
||||||
|
</button>
|
||||||
<div class="mobile-menu-wrapper mobile-only">
|
<div class="mobile-menu-wrapper mobile-only">
|
||||||
<button class="icon-button" title="Menu" @click="toggleMenu">
|
<button class="icon-button" title="Menu" @click="toggleMenu">
|
||||||
<span class="material-symbols-outlined">{{ menuOpen ? 'close' : 'menu' }}</span>
|
<span class="material-symbols-outlined">{{ menuOpen ? 'close' : 'menu' }}</span>
|
||||||
@@ -435,20 +471,27 @@ export default {
|
|||||||
<span class="material-symbols-outlined">{{ viewIcon }}</span>
|
<span class="material-symbols-outlined">{{ viewIcon }}</span>
|
||||||
<span>{{ viewTitle.split('(')[0].trim() }}</span>
|
<span>{{ viewTitle.split('(')[0].trim() }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="dropdown-item" @click="toggleInfoOverlay">
|
||||||
|
<span class="material-symbols-outlined">info</span>
|
||||||
|
<span>Info</span>
|
||||||
|
</button>
|
||||||
<button class="dropdown-item" @click="handleMenuAction(toggleTheme)">
|
<button class="dropdown-item" @click="handleMenuAction(toggleTheme)">
|
||||||
<span class="material-symbols-outlined">{{ themeIcon }}</span>
|
<span class="material-symbols-outlined">{{ themeIcon }}</span>
|
||||||
<span>{{ themeTitle.split('(')[0].trim() }}</span>
|
<span>{{ themeTitle.split('(')[0].trim() }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="dropdown-item" @click="toggleInfoOverlay">
|
||||||
|
<span class="material-symbols-outlined">info</span>
|
||||||
|
<span>Info</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<InfoOverlay :visible="infoOverlayVisible" @close="toggleInfoOverlay" />
|
||||||
<div v-if="isLoading && topics.length === 0" class="loading-container">
|
<div v-if="isLoading && topics.length === 0" class="loading-container">
|
||||||
<span class="material-symbols-outlined spinning loading-spinner">refresh</span>
|
<span class="material-symbols-outlined spinning loading-spinner">refresh</span>
|
||||||
<p>Loading deals...</p>
|
<p>Loading deals...</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="cards-wrapper" v-else>
|
<div class="cards-wrapper" v-else>
|
||||||
<div v-if="isLoading" class="loading-overlay">
|
<div v-if="isLoading" class="loading-overlay">
|
||||||
<span class="material-symbols-outlined spinning loading-spinner">refresh</span>
|
<span class="material-symbols-outlined spinning loading-spinner">refresh</span>
|
||||||
@@ -485,7 +528,6 @@ export default {
|
|||||||
<span v-else>{{ topic.score }}</span>
|
<span v-else>{{ topic.score }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-meta" v-if="topic.Offer.dealer_name">
|
<div class="card-meta" v-if="topic.Offer.dealer_name">
|
||||||
<span
|
<span
|
||||||
class="dealer-name dealer-label"
|
class="dealer-name dealer-label"
|
||||||
@@ -493,7 +535,6 @@ export default {
|
|||||||
v-html="highlightText(topic.Offer.dealer_name)"
|
v-html="highlightText(topic.Offer.dealer_name)"
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-details" v-if="viewMode === 'cards'">
|
<div class="card-details" v-if="viewMode === 'cards'">
|
||||||
<div class="details-stats">
|
<div class="details-stats">
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
@@ -505,11 +546,9 @@ export default {
|
|||||||
<span class="stat-value">{{ topic.total_replies }} replies</span>
|
<span class="stat-value">{{ topic.total_replies }} replies</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-timestamp">First post: {{ formatDate(topic.post_time) }}</div>
|
<div class="card-timestamp">First post: {{ formatDate(topic.post_time) }}</div>
|
||||||
<div class="card-timestamp">Last post: {{ formatDate(topic.last_post_time) }}</div>
|
<div class="card-timestamp">Last post: {{ formatDate(topic.last_post_time) }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-stats" v-if="viewMode === 'list'">
|
<div class="row-stats" v-if="viewMode === 'list'">
|
||||||
<span class="stat-compact">{{ formatDate(topic.post_time) }} - {{ formatDate(topic.last_post_time) }}</span>
|
<span class="stat-compact">{{ formatDate(topic.post_time) }} - {{ formatDate(topic.last_post_time) }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -518,7 +557,8 @@ export default {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<InfoOverlay :visible="infoOverlayVisible" @close="toggleInfoOverlay" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.cards-wrapper {
|
.cards-wrapper {
|
||||||
|
|||||||
114
src/components/InfoOverlay.vue
Normal file
114
src/components/InfoOverlay.vue
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<template>
|
||||||
|
<div class="info-overlay" v-if="visible" @click.self="closeOverlay">
|
||||||
|
<div class="info-panel">
|
||||||
|
<strong>Source: </strong>
|
||||||
|
<a href="https://github.com/davegallant/rfd-fyi" target="_blank" rel="noopener noreferrer">
|
||||||
|
https://github.com/davegallant/rfd-fyi
|
||||||
|
</a>
|
||||||
|
<h3>Keyboard Shortcuts</h3>
|
||||||
|
<table class="shortcuts-table">
|
||||||
|
<tr>
|
||||||
|
<td><strong>r</strong></td>
|
||||||
|
<td>Refresh deals</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>s</strong></td>
|
||||||
|
<td>Toggle sort</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>v</strong></td>
|
||||||
|
<td>Toggle view mode</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>t</strong></td>
|
||||||
|
<td>Toggle theme</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>/</strong></td>
|
||||||
|
<td>Filter deals</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button class="close-button" @click="closeOverlay">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "InfoOverlay",
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeOverlay() {
|
||||||
|
this.$emit("close");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.info-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel {
|
||||||
|
background: var(--bg-primary);
|
||||||
|
color: var(--text-primary);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 400px;
|
||||||
|
width: 90%;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel .shortcuts-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 16px auto;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 40px;
|
||||||
|
display: table;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-panel .shortcuts-table td {
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #007bff;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-button:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user