Skip to content

Commit dc3ee04

Browse files
committed
refactor(feed): move code to component
1 parent 32234c1 commit dc3ee04

File tree

2 files changed

+102
-88
lines changed

2 files changed

+102
-88
lines changed

src/components/feed-item.vue

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<template>
2+
<li class="feed-item">
3+
<time class="feed-item__timestamp">{{ data.date }}:</time>
4+
<component :is="iconComponent" :style="{ stroke: iconColor }" class="feed-item__icon" />
5+
<span v-if="data.username.includes('github-actions')" class="feed-item__user">
6+
{{ data.username }}
7+
</span>
8+
<a
9+
v-else
10+
class="feed-item__user"
11+
:href="`https://github.com/${data.username}`"
12+
target="_blank"
13+
rel="noopener noreferrer"
14+
:title="`Go to ${data.username} profile`"
15+
>
16+
{{ data.username }}
17+
</a>
18+
{{ data.action }}
19+
<span v-if="data.eventUrl" v-dompurify-html="data.eventUrl" />
20+
<a
21+
:href="`https://github.com/${data.repo}`"
22+
target="_blank"
23+
rel="noopener noreferrer"
24+
:title="`Go to ${data.repo} repository`"
25+
>
26+
{{ data.repo }}
27+
</a>
28+
</li>
29+
</template>
30+
<script setup lang="ts">
31+
import {
32+
IconCalendarEvent,
33+
IconCircleDot,
34+
IconEye,
35+
IconGitFork,
36+
IconGitPullRequest,
37+
IconStar,
38+
IconTag,
39+
IconUser,
40+
type Icon
41+
} from "@tabler/icons-vue";
42+
import type { FeedEvent } from "@/store/events";
43+
44+
interface Props {
45+
data: FeedEvent
46+
}
47+
const props = defineProps<Props>();
48+
49+
const iconComponent: Icon = (() => {
50+
switch (props.data.type) {
51+
case "ForkEvent": return IconGitFork;
52+
case "IssuesEvent": return IconCircleDot;
53+
case "MemberEvent": return IconUser;
54+
case "PublicEvent": return IconEye;
55+
case "PullRequestEvent": return IconGitPullRequest;
56+
case "ReleaseEvent": return IconTag;
57+
case "WatchEvent": return IconStar;
58+
default: return IconCalendarEvent;
59+
}
60+
})();
61+
const iconColor: string | undefined = (() => {
62+
switch (props.data.action) {
63+
case "opened issue":
64+
case "opened pull request":
65+
case "published release":
66+
return "#3fb950"; // green
67+
case "merged pull request":
68+
return "#ab7df8"; // purple
69+
case "closed issue":
70+
case "closed pull request":
71+
return "#f85149"; // red
72+
case "made public":
73+
case "starred":
74+
return "#e3b341"; // yellow
75+
case "forked":
76+
case "joined":
77+
return "#9198a1"; // gray
78+
default:
79+
return undefined;
80+
}
81+
})();
82+
</script>
83+
<style lang="scss">
84+
.feed-item {
85+
&__timestamp {
86+
font-size: 0.875rem;
87+
color: var(--accent);
88+
}
89+
&__icon {
90+
width: 1rem;
91+
height: 1rem;
92+
margin-inline: .25rem;
93+
vertical-align: bottom;
94+
}
95+
&__user {
96+
font-weight: bold;
97+
}
98+
}
99+
</style>

src/pages/feed.vue

Lines changed: 3 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,85 +4,15 @@
44
No recent events
55
</span>
66
<ul v-else>
7-
<li v-for="{ date, type, username, action, repo, id, eventUrl } in events" :key="id">
8-
<time>{{ date }}:</time>
9-
<component :is="getIconComponent(type)" :style="composeIconStyle(action)" class="user-feed__icon" />
10-
<a
11-
:href="`https://github.com/${username}`"
12-
target="_blank"
13-
rel="noopener noreferrer"
14-
:title="`Go to ${username} profile`"
15-
>
16-
{{ username }}
17-
</a>
18-
{{ action }}
19-
<span v-if="eventUrl" v-dompurify-html="eventUrl" />
20-
<a
21-
:href="`https://github.com/${repo}`"
22-
target="_blank"
23-
rel="noopener noreferrer"
24-
:title="`Go to ${repo} repository`"
25-
>
26-
{{ repo }}
27-
</a>
28-
</li>
7+
<feed-item v-for="event in events" :key="event.id" :data="event" />
298
</ul>
309
</section>
3110
</template>
3211
<script setup lang="ts">
33-
import type { CSSProperties } from "vue";
34-
import {
35-
IconCalendarEvent,
36-
IconCircleDot,
37-
IconEye,
38-
IconGitFork,
39-
IconGitPullRequest,
40-
IconStar,
41-
IconTag,
42-
IconUser,
43-
type Icon
44-
} from "@tabler/icons-vue";
45-
import { useEventsStore, type FeedEvent } from "@/store/events";
12+
import { useEventsStore } from "@/store/events";
13+
import FeedItem from "@/components/feed-item.vue";
4614
4715
const { events, amount } = useEventsStore();
48-
49-
function getIconComponent(type: FeedEvent["type"]): Icon {
50-
switch (type) {
51-
case "ForkEvent": return IconGitFork;
52-
case "IssuesEvent": return IconCircleDot;
53-
case "MemberEvent": return IconUser;
54-
case "PublicEvent": return IconEye;
55-
case "PullRequestEvent": return IconGitPullRequest;
56-
case "ReleaseEvent": return IconTag;
57-
case "WatchEvent": return IconStar;
58-
default: return IconCalendarEvent;
59-
}
60-
}
61-
function getIconColor(action: FeedEvent["action"]): string | null {
62-
switch (action) {
63-
case "opened issue":
64-
case "opened pull request":
65-
case "published release":
66-
return "#3fb950"; // green
67-
case "merged pull request":
68-
return "#ab7df8"; // purple
69-
case "closed issue":
70-
case "closed pull request":
71-
return "#f85149"; // red
72-
case "made public":
73-
case "starred":
74-
return "#e3b341"; // yellow
75-
case "forked":
76-
case "joined":
77-
return "#9198a1"; // gray
78-
default:
79-
return null;
80-
}
81-
}
82-
function composeIconStyle(action: FeedEvent["action"]): CSSProperties | null {
83-
const color = getIconColor(action);
84-
return color ? { stroke: color } : null;
85-
}
8616
</script>
8717
<style lang="scss">
8818
.user-feed {
@@ -95,21 +25,6 @@ function composeIconStyle(action: FeedEvent["action"]): CSSProperties | null {
9525
padding-left: 0;
9626
list-style-type: none;
9727
}
98-
li {
99-
a {
100-
font-weight: bold;
101-
}
102-
time {
103-
font-size: 0.875rem;
104-
color: var(--accent);
105-
}
106-
}
107-
}
108-
&__icon {
109-
width: 1rem;
110-
height: 1rem;
111-
margin-inline: .25rem;
112-
vertical-align: bottom;
11328
}
11429
}
11530
</style>

0 commit comments

Comments
 (0)