Skip to content

Commit a83fe42

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

2 files changed

Lines changed: 101 additions & 88 deletions

File tree

src/components/feed-item.vue

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