Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit 6d864f4

Browse files
committed
Convert ProjectCard component to TypeScript and Composition API
1 parent f6eff09 commit 6d864f4

File tree

1 file changed

+66
-141
lines changed

1 file changed

+66
-141
lines changed

lib/components/base/ProjectCard.vue

Lines changed: 66 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
:class="{ 'no-image': !featuredImage }"
99
tabindex="-1"
1010
:to="`/${projectTypeUrl}/${id}`"
11-
:style="color ? `background-color: ${toColor};` : ''"
11+
:style="color ? `background-color: ${rgbColor};` : ''"
1212
>
1313
<img v-if="featuredImage" :src="featuredImage" alt="gallery image" loading="lazy" />
1414
</router-link>
@@ -57,7 +57,7 @@
5757
</div>
5858
<div v-if="showUpdatedDate" v-tooltip="updatedDate" class="stat date">
5959
<EditIcon aria-hidden="true" />
60-
<span class="date-label">Updated </span> {{ sinceUpdated }}
60+
<span class="date-label">Updated </span> {{ sinceUpdate }}
6161
</div>
6262
<div v-else v-tooltip="createdDate" class="stat date">
6363
<CalendarIcon aria-hidden="true" />
@@ -67,7 +67,10 @@
6767
</article>
6868
</template>
6969

70-
<script setup>
70+
<script setup lang="ts">
71+
/* eslint vue/require-default-prop: "off" -- https://github.com/vuejs/eslint-plugin-vue/issues/2051 */
72+
73+
import { computed } from 'vue'
7174
import { formatNumber } from '@/helpers'
7275
import {
7376
Badge,
@@ -83,147 +86,69 @@ import {
8386
import dayjs from 'dayjs'
8487
import relativeTime from 'dayjs/plugin/relativeTime.js'
8588
dayjs.extend(relativeTime)
86-
</script>
8789
88-
<script>
89-
import { defineComponent } from 'vue'
90-
export default defineComponent({
91-
props: {
92-
id: {
93-
type: String,
94-
default: 'modrinth-0',
95-
},
96-
type: {
97-
type: String,
98-
default: 'mod',
99-
},
100-
name: {
101-
type: String,
102-
default: 'Project Name',
103-
},
104-
author: {
105-
type: String,
106-
default: null,
107-
},
108-
description: {
109-
type: String,
110-
default: 'A _type description',
111-
},
112-
iconUrl: {
113-
type: String,
114-
default: '#',
115-
required: false,
116-
},
117-
downloads: {
118-
type: String,
119-
default: null,
120-
required: false,
121-
},
122-
follows: {
123-
type: String,
124-
default: null,
125-
required: false,
126-
},
127-
createdAt: {
128-
type: String,
129-
default: '0000-00-00',
130-
},
131-
updatedAt: {
132-
type: String,
133-
default: null,
134-
},
135-
categories: {
136-
type: Array,
137-
default() {
138-
return []
139-
},
140-
},
141-
filteredCategories: {
142-
type: Array,
143-
default() {
144-
return []
145-
},
146-
},
147-
projectTypeDisplay: {
148-
type: String,
149-
default: null,
150-
},
151-
projectTypeUrl: {
152-
type: String,
153-
default: null,
154-
},
155-
status: {
156-
type: String,
157-
default: null,
90+
/** Creates a type that contains original T string, but allows other string values as well. */
91+
type LaxString<T extends string> = T | (string & Record<never, never>)
92+
93+
type ProjectType = 'mod' | 'plugin' | 'modpack' | 'resourcepack'
94+
type SideRequirement = 'required' | 'optional' | 'unsupported'
95+
96+
const props = withDefaults(
97+
defineProps<{
98+
id: string
99+
type: LaxString<ProjectType>
100+
name: string
101+
author?: string
102+
description: string
103+
iconUrl?: string
104+
downloads?: string
105+
follows?: string
106+
createdAt?: string
107+
updatedAt?: string
108+
categories?: string[]
109+
projectTypeDisplay: string
110+
projectTypeUrl: string
111+
status?: string
112+
serverSide?: LaxString<SideRequirement>
113+
clientSide?: LaxString<SideRequirement>
114+
moderation?: boolean
115+
search?: boolean
116+
featuredImage?: string
117+
showUpdatedDate?: boolean
118+
hideLoaders?: boolean
119+
color?: number
120+
}>(),
121+
{
122+
id: 'modrinth-0',
123+
type: 'mod',
124+
name: 'Project Name',
125+
description: 'A _type description', // ???
126+
iconUrl: '#',
127+
createdAt: '0000-00-00',
128+
categories() {
129+
return []
158130
},
159-
serverSide: {
160-
type: String,
161-
required: false,
162-
default: '',
163-
},
164-
clientSide: {
165-
type: String,
166-
required: false,
167-
default: '',
168-
},
169-
moderation: {
170-
type: Boolean,
171-
required: false,
172-
default: false,
173-
},
174-
search: {
175-
type: Boolean,
176-
required: false,
177-
default: false,
178-
},
179-
featuredImage: {
180-
type: String,
181-
required: false,
182-
default: null,
183-
},
184-
showUpdatedDate: {
185-
type: Boolean,
186-
required: false,
187-
default: true,
188-
},
189-
hideLoaders: {
190-
type: Boolean,
191-
required: false,
192-
default: false,
193-
},
194-
color: {
195-
type: Number,
196-
required: false,
197-
default: null,
198-
},
199-
},
200-
computed: {
201-
toColor() {
202-
let color = this.color
203-
204-
color >>>= 0
205-
const b = color & 0xff
206-
const g = (color & 0xff00) >>> 8
207-
const r = (color & 0xff0000) >>> 16
208-
return 'rgba(' + [r, g, b, 1].join(',') + ')'
209-
},
210-
createdDate() {
211-
return dayjs(this.createdAt).format('MMMM D, YYYY [at] h:mm:ss A')
212-
},
213-
sinceCreation() {
214-
return dayjs(this.createdAt).fromNow()
215-
},
216-
updatedDate() {
217-
return dayjs(this.updatedAt).format('MMMM D, YYYY [at] h:mm:ss A')
218-
},
219-
sinceUpdated() {
220-
return dayjs(this.updatedAt).fromNow()
221-
},
222-
},
223-
methods: {
224-
formatNumber,
225-
},
131+
moderation: false,
132+
search: false,
133+
showUpdatedDate: false,
134+
hideLoaders: false,
135+
}
136+
)
137+
138+
const rgbColor = computed(() => {
139+
const color = (props.color ?? 0) >>> 0
140+
const b = color & 0xff
141+
const g = (color & 0xff00) >>> 8
142+
const r = (color & 0xff0000) >>> 16
143+
return `rgb(${r}, ${g}, ${b})`
226144
})
145+
146+
const dateFormat = 'MMMM D, YYYY [at] h:mm:ss A'
147+
148+
const createdDate = computed(() => dayjs(props.createdAt).format(dateFormat))
149+
const updatedDate = computed(() => dayjs(props.updatedAt).format(dateFormat))
150+
const sinceCreation = computed(() => dayjs(props.createdAt).fromNow())
151+
const sinceUpdate = computed(() => dayjs(props.updatedAt).fromNow())
227152
</script>
228153

229154
<style lang="scss" scoped>

0 commit comments

Comments
 (0)