Skip to content

Commit a600503

Browse files
committed
fix: job positions logic
1 parent d1ff89e commit a600503

File tree

3 files changed

+71
-20
lines changed

3 files changed

+71
-20
lines changed

src/components/post/JobPositions.tsx

+23-11
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,27 @@ import { themedPalette } from '../../lib/styles/themes';
88
import { ellipsis } from '../../lib/styles/utils';
99
import media from '../../lib/styles/media';
1010
import gtag from '../../lib/gtag';
11+
import { getJobs, Job } from '../../lib/api/jobs';
1112

1213
type Props = {
1314
category: 'frontend' | 'backend' | 'mobile' | 'python' | 'node' | 'ai' | null;
1415
};
1516

1617
function JobPositions({ category }: Props) {
1718
const [isObserved, setIsObserved] = useState(false);
18-
const { data } = useQuery<{ jobPositions: JobPosition[] }>(JOB_POSITIONS, {
19-
variables: {
20-
category: category ?? undefined,
21-
},
22-
skip: !isObserved,
23-
});
19+
const [data, setData] = useState<Job[]>([]);
2420

2521
const ref = useRef<HTMLDivElement>(null);
2622
const initializedRef = useRef(false);
2723

24+
useEffect(() => {
25+
getJobs(category || 'general').then((jobs) => {
26+
const shuffled = jobs.sort(() => Math.random() - 0.5);
27+
const sliced = shuffled.slice(0, 3);
28+
setData(sliced);
29+
});
30+
}, [category]);
31+
2832
useEffect(() => {
2933
const observer = new IntersectionObserver(
3034
(entries) => {
@@ -57,7 +61,7 @@ function JobPositions({ category }: Props) {
5761
gtag('event', 'job_position_view');
5862
}, [isObserved]);
5963

60-
if (!data?.jobPositions)
64+
if (!data)
6165
return (
6266
<Block>
6367
<div ref={ref}></div>
@@ -70,7 +74,7 @@ function JobPositions({ category }: Props) {
7074
<Typography>
7175
<h4>관련 채용 정보</h4>
7276
<Container>
73-
{data.jobPositions.map((jobPosition) => (
77+
{data.map((jobPosition) => (
7478
<Card key={jobPosition.id} onClick={onClick}>
7579
<a href={jobPosition.url}>
7680
<Thumbnail src={jobPosition.thumbnail} />
@@ -84,6 +88,7 @@ function JobPositions({ category }: Props) {
8488
</div>
8589
</Company>
8690
<JobTitle href={jobPosition.url}>{jobPosition.name}</JobTitle>
91+
<JobDescription>{jobPosition.summary}</JobDescription>
8792
</Card>
8893
))}
8994
</Container>
@@ -122,10 +127,10 @@ const Container = styled.div`
122127
`;
123128

124129
const Card = styled.div`
125-
width: 25%;
130+
width: 33.33%;
126131
${media.small} {
127132
flex-shrink: 0;
128-
width: 27vw;
133+
width: 60vw;
129134
}
130135
`;
131136

@@ -152,9 +157,16 @@ const Company = styled.div`
152157
`;
153158

154159
const JobTitle = styled.a`
155-
font-size: 12px;
160+
font-size: 14px;
156161
font-weight: 600;
157162
line-height: 1.25;
158163
`;
159164

165+
const JobDescription = styled.div`
166+
margin-top: 8px;
167+
color: ${themedPalette.text2};
168+
font-size: 12px;
169+
line-height: 1.5;
170+
`;
171+
160172
export default JobPositions;

src/containers/post/PostViewer.tsx

+27-9
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ const PostViewer: React.FC<PostViewerProps> = ({
223223
const isOwnPost = post.user.id === userId;
224224
const isVeryOld =
225225
Date.now() - new Date(post.released_at).getTime() >
226-
1000 * 60 * 60 * 24 * 30;
226+
1000 * 60 * 60 * 24 * 10;
227227

228228
if (isOwnPost) return false;
229229
if (!isVeryOld) return false;
@@ -254,16 +254,24 @@ const PostViewer: React.FC<PostViewerProps> = ({
254254
}, [customAd, shouldShowBanner, shouldShowFooterBanner]);
255255

256256
const category = useMemo(() => {
257-
const frontendKeywords = ['프런트엔드', '리액트', 'vue', 'react', 'next'];
257+
const frontendKeywords = [
258+
'프런트엔드',
259+
'리액트',
260+
'vue',
261+
'react',
262+
'next',
263+
'프론트엔드',
264+
];
258265
const backendKeywords = ['백엔드', '서버', '데이터베이스', 'db'];
259-
const aiKeywords = ['인공지능', '머신러닝', '딥러닝', 'ai'];
266+
const aiKeywords = ['인공지능', '머신러닝', '딥러닝', 'nlp', 'llm'];
260267
const mobileKeywords = [
261-
'모바일',
262268
'안드로이드',
263269
'ios',
264270
'react native',
265271
'플러터',
266272
'flutter',
273+
'swift',
274+
'xcode',
267275
];
268276
const pythonKeywords = ['파이썬', 'python'];
269277
const nodeKeywords = ['노드', 'node', 'express', 'koa', 'nest'];
@@ -274,15 +282,25 @@ const PostViewer: React.FC<PostViewerProps> = ({
274282
.concat(post.tags.join(','))
275283
.concat(post.body)
276284
.toLowerCase();
285+
if (
286+
aiKeywords.some((keyword) => {
287+
const value = merged.includes(keyword);
288+
if (value) {
289+
console.log(merged);
290+
console.log(keyword);
291+
}
292+
return value;
293+
})
294+
)
295+
return 'ai';
277296
if (frontendKeywords.some((keyword) => merged.includes(keyword)))
278297
return 'frontend';
279-
if (backendKeywords.some((keyword) => merged.includes(keyword)))
280-
return 'backend';
281-
if (aiKeywords.some((keyword) => merged.includes(keyword))) return 'ai';
282298
if (mobileKeywords.some((keyword) => merged.includes(keyword)))
283299
return 'mobile';
284300
if (pythonKeywords.some((keyword) => merged.includes(keyword)))
285301
return 'python';
302+
if (backendKeywords.some((keyword) => merged.includes(keyword)))
303+
return 'backend';
286304
if (nodeKeywords.some((keyword) => merged.includes(keyword))) return 'node';
287305
return null;
288306
}, [data]);
@@ -522,10 +540,10 @@ const PostViewer: React.FC<PostViewerProps> = ({
522540
/>
523541
</UserProfileWrapper>
524542
<LinkedPostList linkedPosts={post.linked_posts} />
525-
{shouldShowBanner && isContentLongEnough && customAd ? (
543+
{shouldShowBanner && isContentLongEnough ? (
526544
<PostBanner customAd={customAd} />
527545
) : null}
528-
{shouldShowFooterBanner && customAd ? (
546+
{shouldShowFooterBanner ? (
529547
<PostBanner isDisplayAd={true} customAd={customAd} />
530548
) : null}
531549
<PostComments

src/lib/api/jobs.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import axios from 'axios';
2+
3+
const secondaryApiClient = axios.create({
4+
baseURL: 'https://cdn.velev.io',
5+
});
6+
7+
export async function getJobs(category: string) {
8+
const response = await secondaryApiClient.get<Job[]>(`/jobs/${category}`);
9+
return response.data;
10+
}
11+
12+
export type Job = {
13+
id: number;
14+
name: string;
15+
companyName: string;
16+
companyLogo: string;
17+
thumbnail: string;
18+
url: string;
19+
jobId: number;
20+
summary: string;
21+
};

0 commit comments

Comments
 (0)