Skip to content

Commit

Permalink
Refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaewoook committed Aug 9, 2022
1 parent ddfab2c commit f25a68d
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 50 deletions.
73 changes: 40 additions & 33 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable jsx-a11y/accessible-emoji */
import React from "react";
/**
* External modules
*/
import React, { useCallback, useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import "antd/dist/antd.css";
import "./App.css";
import {
Button,
Input,
Expand All @@ -17,10 +19,15 @@ import {
LoadingOutlined,
ReloadOutlined,
} from "@ant-design/icons";

/**
* Internal modules
*/
import "./App.css";
import { AddressData, AddressManager } from "./AddressManager";
import { AddressList } from "./components/AddressList";
import { getRuntime } from "./utils";
import { SettingsManager, Settings } from "./SettingsManager";
import { getRuntime } from "./utils";

const Header = styled.div`
position: fixed;
Expand Down Expand Up @@ -92,7 +99,7 @@ const ListEnd = styled.div`
}
`;

const Spinner: React.FC = () => (
const Spinner = () => (
<Spin style={{ width: "100%", marginTop: "15px", marginBottom: "30px" }} indicator={<LoadingOutlined style={{ fontSize: 24 }} />} />
);

Expand All @@ -103,25 +110,25 @@ interface Props {

export const App = (props: Props) => {
const { settings, address } = props;
const [searchValue, setSearchValue] = React.useState("");
const [showLoading, setShowLoading] = React.useState(false);
const [isEnd, setIsEnd] = React.useState(false);
const [showEngAddr, setShowEngAddr] = React.useState(true);
const [showRoadAddr, setShowRoadAddr] = React.useState(true);
const [showLegacyAddr, setShowLegacyAddr] = React.useState(true);
const [addressData, setAddressData] = React.useState<AddressData[]>([]);
const [updatingSettings, setUpdatingSettings] = React.useState(false);
const [searchValue, setSearchValue] = useState("");
const [loading, setLoading] = useState(false);
const [isEnd, setIsEnd] = useState(false);
const [showEngAddr, setShowEngAddr] = useState(true);
const [showRoadAddr, setShowRoadAddr] = useState(true);
const [showLegacyAddr, setShowLegacyAddr] = useState(true);
const [addressData, setAddressData] = useState<AddressData[]>([]);
const [updatingSettings, setUpdatingSettings] = useState(false);

const handleSearchValueChange = React.useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const handleSearchValueChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
setSearchValue(e.target.value);
}, [setSearchValue]);

const handleSearchClick = React.useCallback(() => {
const handleSearchClick = useCallback(() => {
if (address.previousSearchKey?.keyword === searchValue) {
return;
}

setShowLoading(true);
setLoading(true);
setAddressData([]);

window.ga("send", "event", "address", "search", searchValue);
Expand All @@ -135,17 +142,17 @@ export const App = (props: Props) => {
}).catch((err) => {
console.error(err);
}).finally(() => {
setShowLoading(false);
setLoading(false);
});
}, [address, searchValue, setAddressData, setShowLoading]);
}, [address, searchValue]);

const handleResetClick = React.useCallback(() => {
const handleResetClick = useCallback(() => {
setSearchValue("");
handleSearchClick();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [setSearchValue]);
}, []);

const handleSearchOptionClick = React.useCallback((type: "eng" | "road" | "legacy") => async () => {
const handleSearchOptionClick = useCallback((type: "eng" | "road" | "legacy") => async () => {
if (updatingSettings) {
return;
}
Expand Down Expand Up @@ -178,10 +185,10 @@ export const App = (props: Props) => {
} finally {
setUpdatingSettings(false);
}
}, [settings, showEngAddr, showRoadAddr, showLegacyAddr, updatingSettings, setShowEngAddr, setShowRoadAddr, setShowLegacyAddr, setUpdatingSettings]);
}, [settings, showEngAddr, showRoadAddr, showLegacyAddr, updatingSettings]);

const loadNextAddress = React.useCallback(() => {
if (showLoading) {
const loadNextAddress = useCallback(() => {
if (loading) {
return;
}
if (address.previousSearchKey?.end) {
Expand All @@ -190,7 +197,7 @@ export const App = (props: Props) => {
return;
}

setShowLoading(true);
setLoading(true);
const nextPage = (Number.parseInt(address.previousSearchKey?.currentPage!) + 1).toString();

window.ga("send", "event", "address", "search", "์ถ”๊ฐ€ ๋ฐ์ดํ„ฐ ๋กœ๋“œ", Number.parseInt(nextPage));
Expand All @@ -202,11 +209,11 @@ export const App = (props: Props) => {
}).catch((err) => {
console.error(err);
}).finally(() => {
setShowLoading(false);
setLoading(false);
});
}, [address, showLoading, setShowLoading]);
}, [address, loading]);

const Options = React.useMemo(() => [
const Options = useMemo(() => [
<Button key={1} type="link" disabled={updatingSettings} onClick={handleSearchOptionClick("eng")}
icon={showEngAddr ? <CheckCircleFilled /> : <CheckCircleOutlined />}>
์˜๋ฌธ์ฃผ์†Œ
Expand All @@ -221,7 +228,7 @@ export const App = (props: Props) => {
</Button>,
], [showEngAddr, showRoadAddr, showLegacyAddr, updatingSettings, handleSearchOptionClick]);

const handleScrollEvent = React.useCallback(() => {
const handleScrollEvent = useCallback(() => {
const list = document.getElementsByClassName("address-list");
const bottom = list[0]?.getBoundingClientRect().bottom ?? 0;
if (bottom > 0 && bottom <= window.innerHeight) {
Expand All @@ -230,11 +237,11 @@ export const App = (props: Props) => {
}
}, [loadNextAddress]);

React.useEffect(() => {
useEffect(() => {
if (getRuntime() === "extension") {
settings?.once("ready", () => {
console.log("Settings loaded", settings);
const searchResult = settings?.settings?.searchResult;
const searchResult = settings.settings?.searchResult;
setShowEngAddr(searchResult?.showEng ?? false);
setShowRoadAddr(searchResult?.showRoad ?? true);
setShowLegacyAddr(searchResult?.showLegacy ?? true);
Expand All @@ -247,7 +254,7 @@ export const App = (props: Props) => {
}
}, [settings]);

React.useEffect(() => {
useEffect(() => {
document.addEventListener("scroll", handleScrollEvent);
return () => {
document.removeEventListener("scroll", handleScrollEvent);
Expand All @@ -263,7 +270,7 @@ export const App = (props: Props) => {
enterButton allowClear
placeholder="๊ฒ€์ƒ‰ํ•  ์ฃผ์†Œ ์ž…๋ ฅ"
value={searchValue}
loading={showLoading}
loading={loading}
onChange={handleSearchValueChange}
onSearch={handleSearchClick} />
</SearchWrapper>
Expand All @@ -275,7 +282,7 @@ export const App = (props: Props) => {
showEngAddr={showEngAddr}
showRoadAddr={showRoadAddr}
showLegacyAddr={showLegacyAddr} />
{showLoading ? (
{loading ? (
<Spinner />
) : isEnd ? (
<ListEnd>
Expand Down
11 changes: 10 additions & 1 deletion src/components/AddressList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
/* eslint-disable jsx-a11y/accessible-emoji */
/**
* External modules
*/
import React from "react";
import styled from "styled-components";
import { Collapse, Typography } from "antd";

/**
* Internal modules
*/
import "./AddressList.css";
import { AddressData } from "../../AddressManager";
import { ClickToCopyText } from "../ClickToCopyText";
import { FeedbackPopover } from "../FeedbackPopover";
import "./AddressList.css";

interface Props {
data: AddressData[];
Expand All @@ -27,13 +34,15 @@ const EmptyText = styled(Typography.Paragraph)`

export const AddressList = (props: Props) => {
const { data, showEngAddr, showRoadAddr, showLegacyAddr } = props;

if (!data || !data.length) {
return <EmptyText type="secondary">
๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.<br />
<span>(๊ฒ€์ƒ‰์–ด ์˜ˆ์‹œ: ๊ฐ•๋‚จ๋Œ€๋กœ, ์ž์–‘๋™, ์ดˆ์„ฑ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅ)</span><br />
<FeedbackPopover />
</EmptyText>;
}

return (
<Collapse className="address-list" bordered={false} defaultActiveKey={[0]}>
{data.map((row, i) => (
Expand Down
22 changes: 15 additions & 7 deletions src/components/ClickToCopyText/index.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
import React from "react";
/**
* External modules
*/
import React, { useCallback, useState } from "react";
import {
Button,
Tooltip,
} from "antd";
import copy from "copy-to-clipboard";

/**
* Internal modules
*/
import "./ClickToCopyText.css";

interface ClickToCopyTextProps {
children: string;
analytics?: "์šฐํŽธ๋ฒˆํ˜ธ" | "๋„๋กœ๋ช…์ฃผ์†Œ" | "์ง€๋ฒˆ์ฃผ์†Œ" | "์˜๋ฌธ์ฃผ์†Œ";
}

export const ClickToCopyText: React.FC<ClickToCopyTextProps> = ({ children, analytics }: ClickToCopyTextProps) => {
const [copied, setCopied] = React.useState(false);
export const ClickToCopyText = (props: ClickToCopyTextProps) => {
const { children, analytics } = props;
const [copied, setCopied] = useState(false);

const handleCopyClick = React.useCallback(() => {
const handleCopyClick = useCallback(() => {
setCopied(true);
copy(children);
window.ga("send", "event", "address", "copy", `${analytics} ๋ณต์‚ฌ`);
}, [setCopied, analytics, children]);
}, [analytics, children]);

const handleVisibleChange = React.useCallback((visible: boolean) => {
const handleVisibleChange = useCallback((visible: boolean) => {
if (!visible) {
setTimeout(() => setCopied(false), 100);
}
}, [setCopied]);
}, []);
return (
<Tooltip title={!copied ? "ํด๋ฆญํ•ด์„œ ๋ณต์‚ฌํ•˜๊ธฐ" : "๋ณต์‚ฌ์™„๋ฃŒ!"} onVisibleChange={handleVisibleChange}>
<Button className="text-click-to-copy" type="link" onClick={handleCopyClick}>{children}</Button>
Expand Down
20 changes: 12 additions & 8 deletions src/components/FeedbackPopover.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* eslint-disable jsx-a11y/accessible-emoji */
import React from "react";
/**
* External modules
*/
import React, { useCallback, useState } from "react";
import styled from "styled-components";
import { Button, Input, Popover, Typography } from "antd";
import axios from "axios";
Expand Down Expand Up @@ -31,12 +34,12 @@ const PopoverContentStyle = {
};

const FeedbackForm = () => {
const [message, setMessage] = React.useState("");
const [sending, setSending] = React.useState(false);
const [sent, setSent] = React.useState(false);
const [message, setMessage] = useState("");
const [sending, setSending] = useState(false);
const [sent, setSent] = useState(false);

const handleSendClick = React.useCallback(async () => {
if (sent) {
const handleSendClick = useCallback(async () => {
if (sent || !message) {
return;
}
setSending(true);
Expand All @@ -48,14 +51,15 @@ const FeedbackForm = () => {
} finally {
setSending(false);
}
}, [message, sent, setSent, setSending]);
}, [message, sent]);

return <FeedbackSenderWrapper>
<Input.TextArea disabled={sent || sending}
value={message}
rows={3}
placeholder="์ด๊ณณ์— ํ”ผ๋“œ๋ฐฑ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.&#10;์ž‘์„ฑํ•ด์ฃผ์‹  ์†Œ์ค‘ํ•œ ํ”ผ๋“œ๋ฐฑ์ด ๋” ์ข‹์€ ์ฃผ์†Œ๊ฒ€์ƒ‰์„ ๋งŒ๋“ค์–ด์š”!"
onChange={(ev) => setMessage(ev.target.value)} />
<Button disabled={sent || sending} type="primary" onClick={handleSendClick}>
<Button disabled={sent || sending || !message} type="primary" onClick={handleSendClick}>
{!sent ? "๋ณด๋‚ด๊ธฐ ๐ŸŽ‰" : "ํ”ผ๋“œ๋ฐฑ ์ „๋‹ฌ ์™„๋ฃŒ! ๐Ÿ’›"}
</Button>
</FeedbackSenderWrapper>;
Expand Down
9 changes: 8 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
/**
* External modules
*/
import React from "react";
import * as Sentry from "@sentry/react";
import { render } from "react-dom";

/**
* Internal modules
*/
import { App } from "./App";
import { getRuntime, isProduction } from "./utils";
import { AddressManager } from "./AddressManager";
import { SettingsManager, Settings, DEFAULT_SETTINGS } from "./SettingsManager";
import { getRuntime, isProduction } from "./utils";

// inject NODE_ENV variable into window object
window.__ENV__ = {
Expand Down

0 comments on commit f25a68d

Please sign in to comment.