Skip to content

Commit b6e35ba

Browse files
committed
add indiehackers source
1 parent 7c1202b commit b6e35ba

4 files changed

Lines changed: 101 additions & 2 deletions

File tree

src/App.css

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ a {
344344
font-size: 16px;
345345
text-decoration: none;
346346
display: flex;
347+
flex-direction: row;
348+
flex-wrap: wrap;
347349
}
348350
.rowTitle:hover {
349351
color: var(--primary-hover-text-color);
@@ -392,10 +394,12 @@ a {
392394
.rowDescription .rowItem {
393395
font-size: 12px;
394396
}
395-
.rowDetails .hnRowItem {
397+
.rowDetails .hnRowItem {
396398
color: #F6682F
397399
}
398-
400+
.rowDetails .inRowItem {
401+
color: #4799EB
402+
}
399403
.rowDetails .redditRowItem {
400404
color: #FA481D;
401405
}

src/Constants.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ProductHuntCard from './cards/ProductHuntCard'
77
import RedditCard from './cards/RedditCard'
88
import LobstersCard from './cards/LobstersCard'
99
import HashNodeCard from './cards/HashNodeCard'
10+
import IndieHackersCard from './cards/IndieHackersCard'
1011
import FreeCodeCampCard from './cards/FreeCodeCampCard'
1112
import { SiGithub } from 'react-icons/si'
1213
import { SiYcombinator } from 'react-icons/si'
@@ -17,6 +18,7 @@ import { HiTicket } from 'react-icons/hi'
1718
import HashNodeIcon from './static/icon_hashnode.png'
1819
import LobstersIcon from './static/icon_lobsters.png'
1920
import { FaFreeCodeCamp } from 'react-icons/fa'
21+
import { CgIndieHackers } from 'react-icons/cg'
2022

2123
const APP = {
2224
name: 'Hackertab.dev',
@@ -100,6 +102,13 @@ export const SUPPORTED_CARDS = [
100102
label: 'FreeCodeCamp',
101103
component: FreeCodeCampCard,
102104
},
105+
{
106+
value: 'indiehackers',
107+
icon: <CgIndieHackers className="blockHeaderWhite" />,
108+
analyticsTag: 'indiehackers',
109+
label: 'IndieHackers',
110+
component: IndieHackersCard,
111+
},
103112
]
104113

105114
export const SUPPORTED_SEARCH_ENGINES = [

src/cards/IndieHackersCard.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import React, { useContext } from 'react'
2+
import { VscTriangleUp } from 'react-icons/vsc'
3+
import CardComponent from '../components/CardComponent'
4+
import ListComponent from '../components/ListComponent'
5+
import indiehackersApi from '../services/indiehackers'
6+
import { BiCommentDetail } from 'react-icons/bi'
7+
import { MdAccessTime } from 'react-icons/md'
8+
import CardLink from '../components/CardLink'
9+
import CardItemWithActions from '../components/CardItemWithActions'
10+
import PreferencesContext from '../preferences/PreferencesContext'
11+
import { FaChevronUp } from 'react-icons/fa'
12+
import { format } from 'timeago.js'
13+
14+
const StoryItem = ({ item, index, analyticsTag }) => {
15+
const { listingMode } = useContext(PreferencesContext)
16+
17+
return (
18+
<CardItemWithActions
19+
source={'indiehackers'}
20+
index={index}
21+
item={item}
22+
key={index}
23+
cardItem={
24+
<>
25+
<p className="rowTitle">
26+
<CardLink link={item.url} analyticsSource={analyticsTag}>
27+
{listingMode === 'compact' && (
28+
<span className="counterWrapper">
29+
<VscTriangleUp />
30+
<span className="value">{item.score}</span>
31+
</span>
32+
)}
33+
34+
<span className="subTitle">{item.title}</span>
35+
</CardLink>
36+
</p>
37+
{listingMode === 'normal' && (
38+
<div className="rowDetails">
39+
<span className="rowItem inRowItem">
40+
<FaChevronUp className="rowItemIcon" /> {item.likes} points
41+
</span>
42+
<span className="rowItem">
43+
<MdAccessTime className="rowItemIcon" /> {format(new Date(item.published_at))}
44+
</span>
45+
<span className="rowItem">
46+
<BiCommentDetail className="rowItemIcon" /> {item.comments} comments
47+
</span>
48+
</div>
49+
)}
50+
</>
51+
}
52+
/>
53+
)
54+
}
55+
56+
function IndieHackersCard({ analyticsTag, label, icon, withAds }) {
57+
const fetchStories = async () => {
58+
return await indiehackersApi.getTopStories()
59+
}
60+
61+
const renderItem = (item, index) => (
62+
<StoryItem item={item} key={`st-${index}`} index={index} analyticsTag={analyticsTag} />
63+
)
64+
65+
return (
66+
<CardComponent
67+
icon={<span className="blockHeaderIcon">{icon}</span>}
68+
link="https://indiehackers.com/"
69+
title={label}>
70+
<ListComponent fetchData={fetchStories} renderItem={renderItem} withAds={withAds} />
71+
</CardComponent>
72+
)
73+
}
74+
75+
export default IndieHackersCard

src/services/indiehackers.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import cachedRequest from './cachedRequest'
2+
3+
const getTopStories = async () => {
4+
const url = `/data/indiehackers.json`
5+
const data = await cachedRequest(url)
6+
return data
7+
}
8+
9+
export default {
10+
getTopStories: getTopStories,
11+
}

0 commit comments

Comments
 (0)