Skip to content

Commit

Permalink
feat: dooboo github stats (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyochan authored Aug 8, 2024
1 parent ab4c422 commit 25e90f5
Show file tree
Hide file tree
Showing 58 changed files with 1,471 additions and 22 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"lotties",
"Onesignal",
"Pressable",
"Pretendard"
"Pretendard",
"svgs"
]
}
22 changes: 14 additions & 8 deletions app/(app)/(tabs)/profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {css} from '@emotion/native';
import {Pressable} from 'react-native';
import {IC_ICON} from '../../../src/icons';
import {openURL} from '../../../src/utils/common';
import DoobooStats from '../../../src/components/fragments/DoobooStats';

const Container = styled.SafeAreaView`
flex: 1;
Expand Down Expand Up @@ -42,13 +43,20 @@ const UserName = styled(Typography.Heading5)`
margin-bottom: 8px;
`;

const UserBio = styled.Text`
const UserAffiliation = styled.Text`
font-size: 16px;
color: ${({theme}) => theme.role.secondary};
text-align: center;
margin-bottom: 16px;
`;

const UserBio = styled.Text`
font-size: 16px;
color: ${({theme}) => theme.text.label};
text-align: center;
margin-bottom: 16px;
`;

const InfoCard = styled.View`
background-color: ${({theme}) => theme.bg.paper};
border-radius: 15px;
Expand All @@ -72,9 +80,7 @@ const InfoLabel = styled(Typography.Body2)`
font-family: Pretendard-Bold;
`;

const InfoValue = styled(Typography.Body2)`
flex: 1;
`;
const InfoValue = styled(Typography.Body2)``;

const TagContainer = styled.View`
flex-direction: row;
Expand Down Expand Up @@ -114,6 +120,9 @@ export default function Profile(): JSX.Element {
source={user?.avatar_url ? {uri: user?.avatar_url} : IC_ICON}
/>
<UserName>{user?.display_name || ''}</UserName>
{user?.affiliation ? (
<UserAffiliation>{user?.affiliation}</UserAffiliation>
) : null}
{user?.introduction ? <UserBio>{user?.introduction}</UserBio> : null}
</ProfileHeader>
<Content>
Expand All @@ -134,10 +143,7 @@ export default function Profile(): JSX.Element {
<Icon name="GithubLogo" size={16} color={theme.role.link} />
<InfoValue>{user?.github_id || ''}</InfoValue>
</Pressable>
</InfoItem>
<InfoItem>
<InfoLabel>{t('onboarding.affiliation')}</InfoLabel>
<InfoValue>{user?.affiliation || ''}</InfoValue>
<DoobooStats user={user} />
</InfoItem>
</InfoCard>

Expand Down
2 changes: 0 additions & 2 deletions app/(app)/post/[id]/replies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ export default function Replies({
})),
});

console.log('newReply', newReply);

if (newReply) {
setReplies((prevReplies) => [newReply, ...prevReplies]);
}
Expand Down
4 changes: 2 additions & 2 deletions app/(auth)/sign-in.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {Redirect, Stack, useRouter} from 'expo-router';
import {useRecoilValue} from 'recoil';

import {googleClientIdIOS, googleClientIdWeb} from '../../config';
import {IC_CROSSPLATFORMS, IC_GOOGLE, IC_ICON} from '../../src/icons';
import {IMG_CROSSPLATFORMS, IC_GOOGLE, IC_ICON} from '../../src/icons';
import {authRecoilState} from '../../src/recoil/atoms';
import {t} from '../../src/STRINGS';
import {supabase} from '../../src/supabase';
Expand Down Expand Up @@ -162,7 +162,7 @@ export default function SignIn(): JSX.Element {
{t('signIn.description')}
</Typography.Heading5>
<Image
source={IC_CROSSPLATFORMS}
source={IMG_CROSSPLATFORMS}
style={css`
height: 240px;
`}
Expand Down
Binary file removed assets/icons/mask.png
Binary file not shown.
Binary file removed assets/icons/mask@2x.png
Binary file not shown.
Binary file removed assets/icons/mask@3x.png
Binary file not shown.
Binary file added assets/icons/tier_bronze.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_bronze@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_bronze@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_challenger.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_challenger@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_challenger@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_diamond.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_diamond@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_diamond@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_gold.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_gold@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_gold@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_iron.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_iron@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_iron@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_master.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_master@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_master@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_platinum.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_platinum@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_platinum@3x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_silver.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons/tier_silver@2x.png
Binary file added assets/icons/tier_silver@3x.png
File renamed without changes
File renamed without changes
File renamed without changes
Binary file added assets/images/spider_web_d.png
Binary file added assets/images/spider_web_d@2x.png
Binary file added assets/images/spider_web_d@3x.png
Binary file added assets/images/spider_web_l.png
Binary file added assets/images/spider_web_l@2x.png
Binary file added assets/images/spider_web_l@3x.png
7 changes: 5 additions & 2 deletions assets/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
"viewsWithCount": {
"one": "Views %{count}",
"other": "Views %{count}"
}
},
"bio": "Bio",
"score": "Score"
},
"error": {
"default": "Error occurred!",
Expand All @@ -70,7 +72,8 @@
"failedToGetPushToken": "Failed to get push token for push notification!",
"mustUsePhysicalDeviceForSubject": "Must use physical device for {{subject}}",
"projectIdNotFound": "Project ID not found",
"unableToOpenEmailClient": "Unable to open email client"
"unableToOpenEmailClient": "Unable to open email client",
"failedToFetchData": "Failed to fetch data"
},
"loginInfo": {
"cancel": "Cancel",
Expand Down
7 changes: 5 additions & 2 deletions assets/langs/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@
"viewsWithCount": {
"one": "조회수 %{count}",
"other": "조회수 %{count}"
}
},
"bio": "바이오",
"score": "점수"
},
"error": {
"default": "오류가 발생했습니다!",
Expand All @@ -70,7 +72,8 @@
"failedToGetPushToken": "푸시 토큰을 가져오는 데 실패했습니다",
"mustUsePhysicalDeviceForSubject": "{{subject}}을(를) 위해 실제 기기를 사용해야 합니다",
"projectIdNotFound": "프로젝트 ID를 찾을 수 없습니다",
"unableToOpenEmailClient": "이메일 클라이언트를 열 수 없습니다"
"unableToOpenEmailClient": "이메일 클라이언트를 열 수 없습니다",
"failedToFetchData": "데이터를 가져오는 데 실패했습니다"
},
"loginInfo": {
"cancel": "취소",
Expand Down
25 changes: 25 additions & 0 deletions src/apis/githubStatsQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {t} from '../STRINGS';
import {DoobooGithubStats} from '../types/github-stats';

const API_ENDPOINT = 'https://stats.dooboo.io/api/github-stats';

export const updateDoobooGithub = async (
login: string,
): Promise<{stats: DoobooGithubStats} | undefined> => {
try {
const response = await fetch(API_ENDPOINT, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({login}),
});

if (!response.ok) {
throw new Error('HTTP error! status:' + response.status);
}

return await response.json();
} catch (error) {
if (__DEV__) console.error('Error fetching data:', error);
throw new Error(t('error.failedToFetchData'));
}
};
60 changes: 60 additions & 0 deletions src/components/fragments/DoobooStats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import styled, {css} from '@emotion/native';
import {useEffect, useState} from 'react';
import {DoobooGithubStats} from '../../types/github-stats';
import {updateDoobooGithub} from '../../apis/githubStatsQueries';
import Scouter from '../uis/Scouter';
import {User} from '../../types';
import CustomLoadingIndicator from '../uis/CustomLoadingIndicator';

const Container = styled.View``;

type Props = {
user: User | null;
};

export default function DoobooStats({user}: Props): JSX.Element | null {
const [doobooStats, setDoobooStats] = useState<DoobooGithubStats | null>(
null,
);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
const fetchGithubStats = async () => {
try {
if (!user?.github_id) {
return;
}
const result = await updateDoobooGithub(user!.github_id!);

if (!!result?.stats) {
setDoobooStats(result.stats);
}
} catch (e: any) {
setError(e.message);
}
};

if (!!user?.github_id) {
fetchGithubStats();
}
}, [user, user?.github_id]);

if (error) {
return null;
}

return (
<Container>
{doobooStats ? (
<Scouter doobooStats={doobooStats} githubLogin={user?.github_id} />
) : (
<CustomLoadingIndicator
style={css`
padding: 48px;
background-color: transparent;
`}
/>
)}
</Container>
);
}
31 changes: 31 additions & 0 deletions src/components/svgs/SvgStatsDooboo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useDooboo } from 'dooboo-ui';
import {Svg, G, Path, Defs, ClipPath, Rect} from 'react-native-svg';

type Props = {
color?: string;
};

export default function SvgStatsDooboo({color}: Props) {
const {theme} = useDooboo();
const fill = color || theme.text.basic;

return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<G clipPath="url(#clip0_490_628)">
<Path
d="M10 1.26978L2.4397 5.63485V14.365L10 18.7301L17.5603 14.365V5.63485L10 1.26978ZM16.0175 13.4745L10 16.9491L3.98255 13.4745V6.52533L10 3.05072L16.0175 6.52533V13.4745Z"
fill={fill}
/>
<Path
d="M5.52539 7.41579V12.584L9.99999 15.1666L14.4746 12.584V7.41579L9.99999 4.83325L5.52539 7.41579Z"
fill={fill}
/>
</G>
<Defs>
<ClipPath id="clip0_490_628">
<Rect width="20" height="20" fill="white" />
</ClipPath>
</Defs>
</Svg>
);
}
30 changes: 30 additions & 0 deletions src/components/svgs/SvgStatsEarth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {useDooboo} from 'dooboo-ui';
import {G, Path, Svg} from 'react-native-svg';

type Props = {
color?: string;
};

export default function SvgStatsEarth({color}: Props) {
const {theme} = useDooboo();
const fill = color || theme.text.basic;

return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<G opacity="1.0">
<Path
d="M10.3016 13.3017C8.98414 12.7175 7.71113 12.7112 6.46192 13.4937C5.93811 13.8207 5.43335 14.1731 4.92541 14.5239C4.6778 14.6969 4.43176 14.8731 4.18097 15.0413C4.86538 15.8311 5.70338 16.4732 6.64394 16.9287C7.5845 17.3841 8.60794 17.6434 9.65191 17.6906C10.6959 17.7378 11.7385 17.5721 12.7164 17.2034C13.6942 16.8347 14.5868 16.2708 15.3397 15.5461C14.5385 15.3531 13.7643 15.0615 13.0349 14.6778C12.1302 14.2064 11.2365 13.7159 10.3016 13.3017Z"
fill={fill}
/>
<Path
d="M7.09366 4.80165C8.50636 4.80165 9.82858 5.21435 11.1318 5.69689C13.2159 6.46832 15.2762 7.31277 17.4159 7.92864C17.024 6.52795 16.2434 5.26689 15.1645 4.29147C14.0856 3.31604 12.7525 2.66615 11.3195 2.41702C9.88652 2.16789 8.41229 2.32972 7.06747 2.88377C5.72266 3.43782 4.56226 4.36144 3.72064 5.54769L3.81112 5.51117C4.87144 5.11593 5.95239 4.80006 7.09366 4.80165Z"
fill={fill}
/>
<Path
d="M12.7857 8.20486C11.3127 7.64771 9.86506 7.02073 8.29998 6.74772C7.3768 6.57473 6.42717 6.60289 5.51586 6.83026C4.51182 7.09926 3.53344 7.45619 2.59205 7.89692C2.04692 9.82814 2.27462 11.8957 3.22698 13.662C3.43491 13.5461 3.63649 13.416 3.8349 13.2826C4.68252 12.716 5.4857 12.0858 6.37459 11.5937C7.29998 11.0858 8.27935 10.8858 9.31268 11.1382C10.4873 11.4239 11.5349 12.0128 12.5889 12.581C13.8587 13.2699 15.173 13.8382 16.6238 13.9144C17.3268 12.7297 17.698 11.3777 17.6984 10.0001C17.6984 9.95406 17.6984 9.90803 17.6984 9.862C17.0222 9.68422 16.3508 9.49058 15.6905 9.26042C14.7169 8.92073 13.7487 8.56888 12.7857 8.20486Z"
fill={fill}
/>
</G>
</Svg>
);
}
30 changes: 30 additions & 0 deletions src/components/svgs/SvgStatsFire.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {useDooboo} from 'dooboo-ui';
import {G, Path, Svg} from 'react-native-svg';

type Props = {
color?: string;
};

export default function SvgStatsFire({color}: Props) {
const {theme} = useDooboo();
const fill = color || theme.text.basic;

return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<G opacity="1.0">
<Path
d="M4.97939 4.71436L16.2572 13.2001L10.0778 18.1651L3.89844 13.2001L4.97939 4.71436Z"
fill={fill}
/>
<Path
d="M9.16665 1.34912L11.019 4.24277L9.16665 5.73007L7.31586 4.24277L9.16665 1.34912Z"
fill={fill}
/>
<Path
d="M15.1746 3.25073L10.6953 6.91264L16.2699 11.1079L15.1746 3.25073Z"
fill={fill}
/>
</G>
</Svg>
);
}
30 changes: 30 additions & 0 deletions src/components/svgs/SvgStatsGold.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {useDooboo} from 'dooboo-ui';
import {G, Path, Svg} from 'react-native-svg';

type Props = {
color?: string;
};

export default function SvgStatsGold({color}: Props) {
const {theme} = useDooboo();
const fill = color || theme.text.basic;

return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<G opacity="1.0">
<Path
d="M3.65558 9.78738L9.89526 1.69214L16.1334 9.78738L9.89526 17.8826L3.65558 9.78738Z"
fill={fill}
/>
<Path
d="M14.4698 14.5777L16.2445 12.2761L18.0175 14.5777L16.2445 16.8793L14.4698 14.5777Z"
fill={fill}
/>
<Path
d="M2.89685 4.94596L4.18098 3.2793L5.4651 4.94596L4.18098 6.61263L2.89685 4.94596Z"
fill={fill}
/>
</G>
</Svg>
);
}
34 changes: 34 additions & 0 deletions src/components/svgs/SvgStatsPerson.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {useDooboo} from 'dooboo-ui';
import {G, Path, Svg} from 'react-native-svg';

type Props = {
color?: string;
};

export default function SvgStatsPerson({color}: Props) {
const {theme} = useDooboo();
const fill = color || theme.text.basic;

return (
<Svg width="20" height="20" viewBox="0 0 20 20" fill="none">
<G opacity="1.0">
<Path
d="M17.2222 12.0904L10.238 16.446V7.73486L17.2222 12.0904Z"
fill={fill}
/>
<Path
d="M2.61902 14.9096L8.47299 11.2588V18.5604L2.61902 14.9096Z"
fill={fill}
/>
<Path
d="M12.565 6.86981C13.8704 6.86981 14.9285 5.81164 14.9285 4.50631C14.9285 3.20099 13.8704 2.14282 12.565 2.14282C11.2597 2.14282 10.2015 3.20099 10.2015 4.50631C10.2015 5.81164 11.2597 6.86981 12.565 6.86981Z"
fill={fill}
/>
<Path
d="M6.44129 10.3967C7.56339 10.3967 8.47304 9.4871 8.47304 8.365C8.47304 7.2429 7.56339 6.33325 6.44129 6.33325C5.31919 6.33325 4.40955 7.2429 4.40955 8.365C4.40955 9.4871 5.31919 10.3967 6.44129 10.3967Z"
fill={fill}
/>
</G>
</Svg>
);
}
Loading

0 comments on commit 25e90f5

Please sign in to comment.