diff --git a/package.json b/package.json index 3a101aa..2cb24c5 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,13 @@ "@headlessui/react": "^1.3.0", "@supabase/supabase-js": "^1.18.0", "@supabase/ui": "0.27.3", + "moji": "^0.5.1", "next": "11.0.1", "react": "17.0.2", "react-dom": "17.0.2" }, "devDependencies": { + "@types/moji": "^0.5.0", "@types/react": "17.0.11", "autoprefixer": "^10.2.6", "eslint": "7.29.0", diff --git a/src/pages/api/hello.ts b/src/pages/api/hello.ts deleted file mode 100644 index f8bcc7e..0000000 --- a/src/pages/api/hello.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler( - req: NextApiRequest, - res: NextApiResponse -) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/src/pages/api/rakuten.ts b/src/pages/api/rakuten.ts new file mode 100644 index 0000000..ad3a45a --- /dev/null +++ b/src/pages/api/rakuten.ts @@ -0,0 +1,107 @@ +import moji from "moji"; +import type { NextApiRequest, NextApiResponse } from "next"; + +const compare = (a: bookData, b: bookData) => { + if (a.title < b.title) { + return -1; + } else { + return 1; + } +}; + +type rakutenItem = { + Item: bookItem; +}; + +type bookItem = { + title: string; + author: string; + publisherName: string; + largeImageUrl: string; + isbn: string; +}; + +export type bookData = { + title: string; + author: string; + publisherName: string; + imageUrl: string; + isbn: string; +}; + +const convertToUtf8 = (text: string) => { + return unescape(encodeURIComponent(text)); +}; + +const extractData = (item: rakutenItem) => { + let titleString = item.Item.title; + titleString = moji(titleString).convert("ZE", "HE").toString(); + titleString = moji(titleString).convert("ZS", "HS").toString(); + let authorString = item.Item.author; + authorString = moji(authorString).convert("ZE", "HE").toString(); + authorString = moji(authorString).convert("ZS", "HS").reject("HS").toString(); + const data: bookData = { + title: titleString, + author: authorString, + publisherName: item.Item.publisherName, + imageUrl: item.Item.largeImageUrl, + isbn: item.Item.isbn, + }; + return data; +}; + +const Rakuten = async (req: NextApiRequest, res: NextApiResponse) => { + let url = + "https://app.rakuten.co.jp/services/api/BooksBook/Search/20170404?applicationId=" + + process.env.RAKUTEN_APP_ID + + "&booksGenreId=001001"; + + let { title } = req.query; + if (title) { + title = title.toString(); + url += "&title=" + convertToUtf8(title); + } + + let { author } = req.query; + if (author) { + author = author.toString(); + url += "&author=" + convertToUtf8(author); + } + + if (title || author) { + let bookList: bookData[] = []; + let count = -1; + const response = await fetch(url); + const data = await response.json(); + if (data) { + data.Items.map((item: rakutenItem) => { + bookList = [...bookList, extractData(item)]; + }); + count = data.count; + + for (let i = 1; i < data.pageCount; i++) { + await new Promise((resolve) => setTimeout(resolve, 300)); + const response = await fetch(url + "&page=" + (i + 1)); + const data = await response.json(); + if (data) { + data.Items.map((item: rakutenItem) => { + bookList = [...bookList, extractData(item)]; + }); + } + } + } + + if (count != bookList.length) { + res.status(500).json({ massege: "Error: Rakuten Book API." }); + } else { + bookList.sort(compare); + res.status(200).json({ data: bookList, size: count }); + } + } else { + res + .status(500) + .json({ massege: "Error: Please set title or author to query." }); + } +}; + +export default Rakuten; diff --git a/src/styles/Home.module.css b/src/styles/Home.module.css deleted file mode 100644 index 35454bb..0000000 --- a/src/styles/Home.module.css +++ /dev/null @@ -1,121 +0,0 @@ -.container { - min-height: 100vh; - padding: 0 0.5rem; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - height: 100vh; -} - -.main { - padding: 5rem 0; - flex: 1; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.footer { - width: 100%; - height: 100px; - border-top: 1px solid #eaeaea; - display: flex; - justify-content: center; - align-items: center; -} - -.footer a { - display: flex; - justify-content: center; - align-items: center; - flex-grow: 1; -} - -.title a { - color: #0070f3; - text-decoration: none; -} - -.title a:hover, -.title a:focus, -.title a:active { - text-decoration: underline; -} - -.title { - margin: 0; - line-height: 1.15; - font-size: 4rem; -} - -.title, -.description { - text-align: center; -} - -.description { - line-height: 1.5; - font-size: 1.5rem; -} - -.code { - background: #fafafa; - border-radius: 5px; - padding: 0.75rem; - font-size: 1.1rem; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, - Bitstream Vera Sans Mono, Courier New, monospace; -} - -.grid { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - max-width: 800px; - margin-top: 3rem; -} - -.card { - margin: 1rem; - padding: 1.5rem; - text-align: left; - color: inherit; - text-decoration: none; - border: 1px solid #eaeaea; - border-radius: 10px; - transition: color 0.15s ease, border-color 0.15s ease; - width: 45%; -} - -.card:hover, -.card:focus, -.card:active { - color: #0070f3; - border-color: #0070f3; -} - -.card h2 { - margin: 0 0 1rem 0; - font-size: 1.5rem; -} - -.card p { - margin: 0; - font-size: 1.25rem; - line-height: 1.5; -} - -.logo { - height: 1em; - margin-left: 0.5rem; -} - -@media (max-width: 600px) { - .grid { - width: 100%; - flex-direction: column; - } -} diff --git a/src/styles/globals.css b/src/styles/globals.css deleted file mode 100644 index e5e2dcc..0000000 --- a/src/styles/globals.css +++ /dev/null @@ -1,16 +0,0 @@ -html, -body { - padding: 0; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, - Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; -} - -a { - color: inherit; - text-decoration: none; -} - -* { - box-sizing: border-box; -} diff --git a/yarn.lock b/yarn.lock index 0a9b770..2a9cc37 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,6 +223,11 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= +"@types/moji@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@types/moji/-/moji-0.5.0.tgz#4b68f789702baeb9aa5482ea68191ca4080c8b2b" + integrity sha512-oZhMgrG0iv5u1yICABzV4NrlpGOE7hNapc3atIMiQ1ebWOTkay/x1eMYbQPXjCxxk14Td3cqy7S+kvmGdE7NGA== + "@types/node@*": version "15.12.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.5.tgz#9a78318a45d75c9523d2396131bd3cca54b2d185" @@ -2232,6 +2237,13 @@ modern-normalize@^1.1.0: resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.1.0.tgz#da8e80140d9221426bd4f725c6e11283d34f90b7" integrity sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA== +moji@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/moji/-/moji-0.5.1.tgz#088eecd1c22c8f31a240adcf9c95e54f33eb54fb" + integrity sha1-CI7s0cIsjzGiQK3PnJXlTzPrVPs= + dependencies: + object-assign "^3.0.0" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -2403,6 +2415,11 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I= + object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"