mirror of
https://github.com/davegallant/rfd-fyi.git
synced 2025-10-03 07:06:02 +00:00
Migrate to vuetify and vite (#251)
This commit is contained in:
187
src/App.vue
187
src/App.vue
@@ -5,6 +5,7 @@ import Loading from "vue-loading-overlay";
|
||||
import { install } from "@github/hotkey";
|
||||
|
||||
import "vue-loading-overlay/dist/css/index.css";
|
||||
import { ref } from "vue";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@@ -43,43 +44,11 @@ export default {
|
||||
.then((response) => {
|
||||
this.topics = response.data;
|
||||
this.isLoading = false;
|
||||
this.sortTable(this.sortColumn, false);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response);
|
||||
});
|
||||
},
|
||||
sortTable: function sortTable(col, flipAscending) {
|
||||
if (this.sortColumn === col && flipAscending) {
|
||||
this.ascending = !this.ascending;
|
||||
}
|
||||
|
||||
var ascending = this.ascending;
|
||||
|
||||
localStorage.setItem("ascending", this.ascending);
|
||||
localStorage.setItem("sortColumn", col);
|
||||
this.sortColumn = col;
|
||||
|
||||
this.topics.sort(function (a, b) {
|
||||
if (a[col] > b[col]) {
|
||||
return ascending ? -1 : 1;
|
||||
} else if (a[col] < b[col]) {
|
||||
return ascending ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
},
|
||||
isMobile() {
|
||||
if (
|
||||
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
||||
navigator.userAgent
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
formatDate() {
|
||||
@@ -87,14 +56,6 @@ export default {
|
||||
return moment(String(v)).format("hh:mm A z (MM/DD)");
|
||||
};
|
||||
},
|
||||
columns() {
|
||||
return {
|
||||
Deal: "deal",
|
||||
Score: "score",
|
||||
Views: "total_views",
|
||||
"Last Reply": "last_post_time",
|
||||
};
|
||||
},
|
||||
filteredTopics() {
|
||||
return this.topics.filter((row) => {
|
||||
const titles = (
|
||||
@@ -117,11 +78,6 @@ export default {
|
||||
return v.replace(re, (matchedText) => `<mark>${matchedText}</mark>`);
|
||||
};
|
||||
},
|
||||
showBeforeTargetDate() {
|
||||
const now = new Date();
|
||||
const target = new Date('2025-08-20T00:00:00');
|
||||
return now < target;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Loading,
|
||||
@@ -129,92 +85,80 @@ export default {
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
|
||||
<body>
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
id="filter"
|
||||
placeholder="Filter"
|
||||
<script setup>
|
||||
const headers = [
|
||||
{ title: "Deal", value: "title", align: "center" },
|
||||
{ title: "Score", value: "score", align: "center", sortable: true },
|
||||
{ title: "Views", value: "total_views", align: "center", sortable: true },
|
||||
{
|
||||
title: "Last Post",
|
||||
value: "last_post_time",
|
||||
align: "center",
|
||||
sortable: true,
|
||||
},
|
||||
];
|
||||
const sortBy = ref([{ key: "score", order: "desc" }]); // Vuetify 3 format
|
||||
</script>
|
||||
|
||||
data-hotkey="/"
|
||||
v-model="filter"
|
||||
v-on:keyup.enter="createFilterRoute(this.filter.toString())"
|
||||
v-on:keyup.escape="this.$refs.filter.blur()"
|
||||
ref="filter"
|
||||
/>
|
||||
<table class="table table-hover">
|
||||
<thead class="thead text-muted">
|
||||
<tr>
|
||||
<th
|
||||
v-for="(col, key) in columns"
|
||||
v-on:click="sortTable(col, true)"
|
||||
:key="col"
|
||||
>
|
||||
{{ key }}
|
||||
<div
|
||||
class="arrow"
|
||||
v-if="col == sortColumn"
|
||||
v-bind:class="ascending ? 'arrow_up' : 'arrow_down'"
|
||||
></div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<loading
|
||||
v-model:active="isLoading"
|
||||
color="#ccc"
|
||||
opacity="0"
|
||||
loader="bars"
|
||||
:is-full-page="false"
|
||||
<template>
|
||||
<v-app>
|
||||
<v-main>
|
||||
<link rel="shortcut icon" type="image/png" href="/favicon.png" />
|
||||
<body>
|
||||
<v-text-field
|
||||
v-model="filter"
|
||||
label="Filter"
|
||||
density="comfortable"
|
||||
ref="filter"
|
||||
@keyup.enter="createFilterRoute(filter.toString())"
|
||||
@keyup.esc="$refs.filter.blur()"
|
||||
data-hotkey="/"
|
||||
hide-details
|
||||
/>
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="filteredTopics"
|
||||
:sort-by="sortColumn"
|
||||
:sort-desc="!ascending"
|
||||
v-model:sortBy="sortBy"
|
||||
>
|
||||
</loading>
|
||||
<tr
|
||||
scope="row"
|
||||
v-for="(topic, index) in filteredTopics"
|
||||
:key="`topic.topic_id-${index}`"
|
||||
>
|
||||
<td scope="col">
|
||||
<template #item.title="{ item }">
|
||||
<a
|
||||
:href="`https://forums.redflagdeals.com${topic.web_path}`"
|
||||
:href="`https://forums.redflagdeals.com${item.web_path}`"
|
||||
target="_blank"
|
||||
v-html="
|
||||
highlightMatches(
|
||||
topic.title + ' [' + topic.Offer.dealer_name + '] '
|
||||
item.title + ' [' + item.Offer.dealer_name + '] '
|
||||
)
|
||||
"
|
||||
></a>
|
||||
<a
|
||||
:href="`${topic.Offer.url}`"
|
||||
target="_blank"
|
||||
v-if="topic.Offer.url"
|
||||
><span class="material-symbols-outlined"> link </span></a
|
||||
<a :href="item.Offer.url" target="_blank" v-if="item.Offer.url">
|
||||
<span class="material-symbols-outlined"> link </span>
|
||||
</a>
|
||||
<span v-else class="material-symbols-outlined"> link_off </span>
|
||||
</template>
|
||||
|
||||
<template #item.score="{ item }">
|
||||
<span v-if="item.score > 0" class="green-score"
|
||||
>+{{ item.score }}</span
|
||||
>
|
||||
<span v-if="!topic.Offer.url" class="material-symbols-outlined">
|
||||
link_off
|
||||
</span>
|
||||
</td>
|
||||
<td v-if="topic.score > 0" scope="col" class="green-score">
|
||||
+{{ topic.score }}
|
||||
</td>
|
||||
<td v-if="topic.score < 0" scope="col" class="red-score">
|
||||
{{ topic.score }}
|
||||
</td>
|
||||
<td v-if="topic.score == 0" scope="col">
|
||||
{{ topic.score }}
|
||||
</td>
|
||||
<td scope="col">{{ topic.total_views }}</td>
|
||||
<td scope="col">{{ formatDate(topic.last_post_time) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-if="showBeforeTargetDate">
|
||||
<footer class="fixed-bottom">
|
||||
PSA: <a href="https://rfd.fyi">rfd.fyi</a> will not be renewed after 2025-08-20. Please use <a href="https://rfd.davegallant.ca">rfd.davegallant.ca</a>.
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
<span v-else-if="item.score < 0" class="red-score">{{
|
||||
item.score
|
||||
}}</span>
|
||||
<span v-else>{{ item.score }}</span>
|
||||
</template>
|
||||
|
||||
<template #item.last_post_time="{ item }">
|
||||
{{ formatDate(item.last_post_time) }}
|
||||
</template>
|
||||
|
||||
<template #loading>
|
||||
<v-progress-linear indeterminate color="grey" />
|
||||
</template>
|
||||
</v-data-table>
|
||||
</body>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@@ -230,5 +174,4 @@ export default {
|
||||
background: #ffc;
|
||||
color: black;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user