diff --git a/components/layout/index.tsx b/components/layout/index.tsx
index c3c3095..4545004 100644
--- a/components/layout/index.tsx
+++ b/components/layout/index.tsx
@@ -1,4 +1,4 @@
-import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
+import { FADE_IN_ANIMATION_SETTINGS, READ_PILOT_TOKEN } from "@/lib/constants";
import { AnimatePresence, motion } from "framer-motion";
import { useSession } from "next-auth/react";
import Image from "next/image";
@@ -6,8 +6,10 @@ import Link from "next/link";
import { ReactNode } from "react";
import useScroll from "@/lib/hooks/use-scroll";
import Meta from "./meta";
-import { useSignInModal } from "./sign-in-modal";
import UserDropdown from "./user-dropdown";
+import { useGoogleLogin } from "@react-oauth/google";
+import { usePilotStore } from "@/lib/store";
+import { googleLogin } from "service.ts/request";
export default function Layout({
meta,
@@ -20,9 +22,21 @@ export default function Layout({
};
children: ReactNode;
}) {
- const { data: session, status } = useSession();
- const { SignInModal, setShowSignInModal } = useSignInModal();
const scrolled = useScroll(50);
+ const { authToken, setAuthToken } = usePilotStore((state) => state);
+ const login = useGoogleLogin({
+ onSuccess: async (tokenResponse) => {
+ try {
+ const res = await googleLogin({
+ access_token: tokenResponse.access_token,
+ });
+ localStorage.setItem(READ_PILOT_TOKEN, res.data.access);
+ setAuthToken(res.data.access);
+ } catch (error) {
+ console.error(error);
+ }
+ },
+ });
return (
<>
@@ -46,17 +60,26 @@ export default function Layout({
>
Read Pilot
-
+
- {!session && status !== "loading" ? (
-
+ Subscribe
+
+ {!authToken ? (
+ {
+ login();
+ }}
>
- Subscribe
-
+ Sign in
+
) : (
)}
diff --git a/components/layout/user-dropdown.tsx b/components/layout/user-dropdown.tsx
index b7bc4a2..f4a969e 100644
--- a/components/layout/user-dropdown.tsx
+++ b/components/layout/user-dropdown.tsx
@@ -1,17 +1,16 @@
import { useState } from "react";
-import { signOut, useSession } from "next-auth/react";
-import { LayoutDashboard, LogOut } from "lucide-react";
+import { LogOut } from "lucide-react";
import Popover from "@/components/shared/popover";
import Image from "next/image";
import { motion } from "framer-motion";
-import { FADE_IN_ANIMATION_SETTINGS } from "@/lib/constants";
+import { FADE_IN_ANIMATION_SETTINGS, READ_PILOT_TOKEN } from "@/lib/constants";
+import { usePilotStore } from "@/lib/store";
export default function UserDropdown() {
- const { data: session } = useSession();
- const { email, image } = session?.user || {};
+ const { userInfo, setAuthToken } = usePilotStore((state) => state);
const [openPopover, setOpenPopover] = useState(false);
- if (!email) return null;
+ if (!userInfo) return null;
return (
- {/*
-
- Dashboard
- */}
-
+ */}
diff --git a/lib/constants.ts b/lib/constants.ts
index 38abc24..971c152 100644
--- a/lib/constants.ts
+++ b/lib/constants.ts
@@ -16,3 +16,8 @@ export const FADE_UP_ANIMATION_VARIANTS = {
export const DEPLOY_URL =
"https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fsteven-tey%2Fprecedent&project-name=precedent&repository-name=precedent&demo-title=Precedent&demo-description=An%20opinionated%20collection%20of%20components%2C%20hooks%2C%20and%20utilities%20for%20your%20Next%20project.&demo-url=https%3A%2F%2Fprecedent.dev&demo-image=https%3A%2F%2Fprecedent.dev%2Fapi%2Fog&env=DATABASE_URL,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,NEXTAUTH_SECRET&envDescription=How%20to%20get%20these%20env%20variables%3A&envLink=https%3A%2F%2Fgithub.com%2Fsteven-tey%2Fprecedent%2Fblob%2Fmain%2F.env.example";
+
+export const READ_PILOT_TOKEN =
+ process.env.NODE_ENV === "development"
+ ? "READ_PILOT_LOCAL_AUTH"
+ : "READ_PILOT_PROD_AUTH";
diff --git a/lib/interface.ts b/lib/interface.ts
new file mode 100644
index 0000000..4f22b1e
--- /dev/null
+++ b/lib/interface.ts
@@ -0,0 +1,5 @@
+export interface UserInfo {
+ avatar: string;
+ email: string;
+ id: string;
+}
diff --git a/lib/store/index.ts b/lib/store/index.ts
new file mode 100644
index 0000000..b9fb32e
--- /dev/null
+++ b/lib/store/index.ts
@@ -0,0 +1,37 @@
+import { getUserInfo } from "service.ts/request";
+import { create } from "zustand";
+import { UserInfo } from "../interface";
+
+interface PilotStoreInterface {
+ userInfo?: UserInfo;
+ authToken?: string;
+
+ setUserInfo: (userInfo: UserInfo) => void;
+ setAuthToken: (token?: string) => void;
+ fetchUserInfo: () => Promise;
+}
+
+export const usePilotStore = create()((set, get) => ({
+ setUserInfo: (userInfo) => {
+ set({
+ userInfo: userInfo,
+ });
+ },
+ setAuthToken: (token) => {
+ set({
+ authToken: token,
+ });
+ },
+ fetchUserInfo: async () => {
+ const { authToken } = get();
+ if (!authToken) {
+ return;
+ }
+ try {
+ const res = await getUserInfo({});
+ set({
+ userInfo: res.data,
+ });
+ } catch (error) {}
+ },
+}));
diff --git a/package-lock.json b/package-lock.json
index feab81e..7254e27 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,11 +13,13 @@
"@prisma/client": "^4.8.1",
"@radix-ui/react-popover": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.2",
+ "@react-oauth/google": "^0.7.0",
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
"@vercel/analytics": "^0.1.6",
"@vercel/og": "^0.0.26",
+ "axios": "^1.3.2",
"classnames": "^2.3.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.1",
@@ -32,7 +34,8 @@
"react-markdown": "^8.0.4",
"react-wrap-balancer": "^0.3.0",
"typescript": "4.9.4",
- "use-debounce": "^9.0.3"
+ "use-debounce": "^9.0.3",
+ "zustand": "^4.3.2"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.3",
@@ -836,6 +839,15 @@
"@babel/runtime": "^7.13.10"
}
},
+ "node_modules/@react-oauth/google": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.7.0.tgz",
+ "integrity": "sha512-KLLYlLYYpXf1zmcrsJPAxImvoq2b0Rs0Pi/6GYfdwjmTh66Pf6jkZ4fpO10tuJuUPWvEeqloPEC/i4BySgbYVQ==",
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
"node_modules/@resvg/resvg-wasm": {
"version": "2.0.0-alpha.4",
"resolved": "https://registry.npmjs.org/@resvg/resvg-wasm/-/resvg-wasm-2.0.0-alpha.4.tgz",
@@ -1314,6 +1326,11 @@
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
},
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
"node_modules/autoprefixer": {
"version": "10.4.13",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
@@ -1366,6 +1383,16 @@
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz",
+ "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==",
+ "dependencies": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -1611,6 +1638,17 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/comma-separated-tokens": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
@@ -1833,6 +1871,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -2618,6 +2664,25 @@
"react-dom": ">=16.3.0"
}
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -2626,6 +2691,19 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -4066,6 +4144,25 @@
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
@@ -4762,6 +4859,11 @@
"url": "https://github.com/sponsors/wooorm"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/punycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
@@ -5827,6 +5929,14 @@
}
}
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -6052,6 +6162,29 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.3.0.tgz",
"integrity": "sha512-rD3L4jyMlO1m+RWU60lNwZQK5zmzglCV5fI1gTRikmpv3YzmNIZQbjyfE6cMNb9Xaly/C1SwemYGbsiOekMvnQ=="
+ },
+ "node_modules/zustand": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.2.tgz",
+ "integrity": "sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==",
+ "dependencies": {
+ "use-sync-external-store": "1.2.0"
+ },
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "immer": ">=9.0",
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
}
},
"dependencies": {
@@ -6596,6 +6729,12 @@
"@babel/runtime": "^7.13.10"
}
},
+ "@react-oauth/google": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.7.0.tgz",
+ "integrity": "sha512-KLLYlLYYpXf1zmcrsJPAxImvoq2b0Rs0Pi/6GYfdwjmTh66Pf6jkZ4fpO10tuJuUPWvEeqloPEC/i4BySgbYVQ==",
+ "requires": {}
+ },
"@resvg/resvg-wasm": {
"version": "2.0.0-alpha.4",
"resolved": "https://registry.npmjs.org/@resvg/resvg-wasm/-/resvg-wasm-2.0.0-alpha.4.tgz",
@@ -6940,6 +7079,11 @@
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag=="
},
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
"autoprefixer": {
"version": "10.4.13",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
@@ -6964,6 +7108,16 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz",
"integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg=="
},
+ "axios": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz",
+ "integrity": "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==",
+ "requires": {
+ "follow-redirects": "^1.15.0",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"axobject-query": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz",
@@ -7132,6 +7286,14 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
"comma-separated-tokens": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
@@ -7293,6 +7455,11 @@
"integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
"dev": true
},
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+ },
"dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -7895,6 +8062,11 @@
"tabbable": "^6.0.1"
}
},
+ "follow-redirects": {
+ "version": "1.15.2",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
+ "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ },
"for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -7903,6 +8075,16 @@
"is-callable": "^1.1.3"
}
},
+ "form-data": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
+ "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ }
+ },
"fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -8806,6 +8988,19 @@
"picomatch": "^2.3.1"
}
},
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
"mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
@@ -9237,6 +9432,11 @@
"resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz",
"integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg=="
},
+ "proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"punycode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz",
@@ -9943,6 +10143,12 @@
"tslib": "^2.0.0"
}
},
+ "use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "requires": {}
+ },
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -10103,6 +10309,14 @@
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.3.0.tgz",
"integrity": "sha512-rD3L4jyMlO1m+RWU60lNwZQK5zmzglCV5fI1gTRikmpv3YzmNIZQbjyfE6cMNb9Xaly/C1SwemYGbsiOekMvnQ=="
+ },
+ "zustand": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.2.tgz",
+ "integrity": "sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==",
+ "requires": {
+ "use-sync-external-store": "1.2.0"
+ }
}
}
}
diff --git a/package.json b/package.json
index 081a490..890e6ff 100644
--- a/package.json
+++ b/package.json
@@ -18,11 +18,13 @@
"@prisma/client": "^4.8.1",
"@radix-ui/react-popover": "^1.0.2",
"@radix-ui/react-tooltip": "^1.0.2",
+ "@react-oauth/google": "^0.7.0",
"@types/node": "18.11.18",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
"@vercel/analytics": "^0.1.6",
"@vercel/og": "^0.0.26",
+ "axios": "^1.3.2",
"classnames": "^2.3.2",
"eslint": "8.31.0",
"eslint-config-next": "13.1.1",
@@ -37,7 +39,8 @@
"react-markdown": "^8.0.4",
"react-wrap-balancer": "^0.3.0",
"typescript": "4.9.4",
- "use-debounce": "^9.0.3"
+ "use-debounce": "^9.0.3",
+ "zustand": "^4.3.2"
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.3",
diff --git a/pages/index.tsx b/pages/index.tsx
index e2363e7..758654f 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -2,11 +2,16 @@ import Card from "@/components/home/card";
import Layout from "@/components/layout";
import Balancer from "react-wrap-balancer";
import { motion } from "framer-motion";
-import { FADE_DOWN_ANIMATION_VARIANTS } from "@/lib/constants";
+import {
+ FADE_DOWN_ANIMATION_VARIANTS,
+ READ_PILOT_TOKEN,
+} from "@/lib/constants";
import { Github, LoadingDots, Twitter } from "@/components/shared/icons";
-import { useState } from "react";
+import { useEffect, useState } from "react";
import LinkIcon from "@/components/shared/icons/link";
import CountingNumbers from "@/components/shared/counting-numbers";
+import { usePilotStore } from "@/lib/store";
+import { GoogleOAuthProvider } from "@react-oauth/google";
export default function Home() {
const [url, setUrl] = useState("");
@@ -14,6 +19,10 @@ export default function Home() {
const [loading, setLoading] = useState(false);
const [results, setResults] = useState([]);
+ const { setAuthToken, authToken, fetchUserInfo } = usePilotStore(
+ (state) => state,
+ );
+
const generateCards = async (e: any) => {
e.preventDefault();
@@ -51,138 +60,173 @@ export default function Home() {
setLoading(false);
};
+ useEffect(() => {
+ const token = localStorage.getItem(READ_PILOT_TOKEN);
+ if (token && token !== null) {
+ setAuthToken(token);
+ }
+ }, []);
+
+ useEffect(() => {
+ if (authToken) {
+ fetchUserInfo();
+ }
+ }, [authToken]);
+
return (
-
-
-
+
+
+
-
-
-
- Introducing Read Pilot
-
-
-
-
- Star on GitHub
-
-
+
+
+
+ Introducing Read Pilot
+
+
+
+
+ Star on GitHub
+
+
-
-
- Read Online Articles With
-
-
- Intelligence
-
-
-
-
-
- Read Pilot analyzes online articles and generate Q&A cards for
- you.
-
-
+
+
+ Read Online Articles With
+
+
+ Intelligence
+
+
+
+
+
+ Read Pilot analyzes online articles and generate Q&A cards for
+ you.
+
+
-
-
- Trusted by{" "}
- {" "}
- users,{" "}
- {" "}
- links have been analyzed.
-
-
+
+
+ Trusted by{" "}
+ {" "}
+ users,{" "}
+ {" "}
+ links have been analyzed.
+
+
-
-
-
- {
- setUrl((e.target as HTMLInputElement).value);
- }}
- required
- className="block w-full rounded-2xl border border-gray-200 bg-white p-2 pl-12 text-lg text-gray-600 shadow-md focus:border-black focus:outline-none focus:ring-0"
- />
-
-
+
+
+
+ {
+ setUrl((e.target as HTMLInputElement).value);
+ }}
+ required
+ className="block w-full rounded-2xl border border-gray-200 bg-white p-2 pl-12 text-lg text-gray-600 shadow-md focus:border-black focus:outline-none focus:ring-0"
+ />
+
+
-
- {!loading && (
-
- )}
- {loading && (
-
+ )}
+ {loading && (
+
+ )}
+
+ ) : (
+
- Analyzing
-
-
+
+ Sign in to start
+
+
)}
-
- {showGeneratedCards && (
-
- {results.map(({ q, a }) => (
-
- ))}
-
- )}
-
-
+ {showGeneratedCards && (
+
+ {results.map(({ q, a }) => (
+
+ ))}
+
+ )}
+
+
+
);
}
diff --git a/service.ts/request.ts b/service.ts/request.ts
new file mode 100644
index 0000000..f47fc06
--- /dev/null
+++ b/service.ts/request.ts
@@ -0,0 +1,47 @@
+import { READ_PILOT_TOKEN } from "@/lib/constants";
+import axios, { AxiosError } from "axios";
+
+export const instance = axios.create({
+ baseURL:
+ process.env.NODE_ENV === "development"
+ ? "http://127.0.0.1:8000/"
+ : "https://api.pipe3.xyz/",
+
+ timeout: 5000,
+});
+
+instance.interceptors.request.use((req) => {
+ if (req.url !== "/api/v1/readpilot/google/login") {
+ !req.headers && (req.headers = {} as any);
+ req.headers.Authorization =
+ `Bearer ${localStorage.getItem(READ_PILOT_TOKEN)}` || "";
+ }
+ return req;
+});
+
+instance.interceptors.response.use(
+ (response) => {
+ return response;
+ },
+ (error: AxiosError) => {
+ if (error && error.response) {
+ const status = error.response.status;
+ if (status === 401) {
+ localStorage.removeItem(READ_PILOT_TOKEN);
+ window.location.reload();
+ } else {
+ }
+ }
+ return Promise.reject(error);
+ },
+);
+
+// ================================== User ================================
+
+// Get User Info
+export const getUserInfo = (params: any) =>
+ instance.get("/api/v1/readpilot/google/info", { params });
+
+// Google Login
+export const googleLogin = (params: any) =>
+ instance.post("/api/v1/readpilot/google/login", params);
diff --git a/yarn.lock b/yarn.lock
index fcc0719..f3298b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -427,6 +427,11 @@
dependencies:
"@babel/runtime" "^7.13.10"
+"@react-oauth/google@^0.7.0":
+ "integrity" "sha512-KLLYlLYYpXf1zmcrsJPAxImvoq2b0Rs0Pi/6GYfdwjmTh66Pf6jkZ4fpO10tuJuUPWvEeqloPEC/i4BySgbYVQ=="
+ "resolved" "https://registry.npmjs.org/@react-oauth/google/-/google-0.7.0.tgz"
+ "version" "0.7.0"
+
"@resvg/resvg-wasm@2.0.0-alpha.4":
"integrity" "sha512-pWIG9a/x1ky8gXKRhPH1OPKpHFoMN1ISLbJ+O+gPXQHIAKhNd5I28RlWf7q576hAOQA9JZTlo3p/M2uyLzJmmw=="
"resolved" "https://registry.npmjs.org/@resvg/resvg-wasm/-/resvg-wasm-2.0.0-alpha.4.tgz"
@@ -734,6 +739,11 @@
"resolved" "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz"
"version" "0.0.7"
+"asynckit@^0.4.0":
+ "integrity" "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ "resolved" "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz"
+ "version" "0.4.0"
+
"autoprefixer@^10.4.13":
"integrity" "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg=="
"resolved" "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz"
@@ -756,6 +766,15 @@
"resolved" "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz"
"version" "4.6.2"
+"axios@^1.3.2":
+ "integrity" "sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw=="
+ "resolved" "https://registry.npmjs.org/axios/-/axios-1.3.2.tgz"
+ "version" "1.3.2"
+ dependencies:
+ "follow-redirects" "^1.15.0"
+ "form-data" "^4.0.0"
+ "proxy-from-env" "^1.1.0"
+
"axobject-query@^3.1.1":
"integrity" "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg=="
"resolved" "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz"
@@ -890,6 +909,13 @@
"resolved" "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
"version" "1.1.4"
+"combined-stream@^1.0.8":
+ "integrity" "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="
+ "resolved" "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz"
+ "version" "1.0.8"
+ dependencies:
+ "delayed-stream" "~1.0.0"
+
"comma-separated-tokens@^2.0.0":
"integrity" "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="
"resolved" "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz"
@@ -1047,6 +1073,11 @@
"resolved" "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz"
"version" "1.0.1"
+"delayed-stream@~1.0.0":
+ "integrity" "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
+ "resolved" "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
+ "version" "1.0.0"
+
"dequal@^2.0.0":
"integrity" "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="
"resolved" "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz"
@@ -1524,6 +1555,11 @@
dependencies:
"tabbable" "^6.0.1"
+"follow-redirects@^1.15.0":
+ "integrity" "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
+ "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz"
+ "version" "1.15.2"
+
"for-each@^0.3.3":
"integrity" "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw=="
"resolved" "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz"
@@ -1531,6 +1567,15 @@
dependencies:
"is-callable" "^1.1.3"
+"form-data@^4.0.0":
+ "integrity" "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww=="
+ "resolved" "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz"
+ "version" "4.0.0"
+ dependencies:
+ "asynckit" "^0.4.0"
+ "combined-stream" "^1.0.8"
+ "mime-types" "^2.1.12"
+
"fraction.js@^4.2.0":
"integrity" "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA=="
"resolved" "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz"
@@ -2386,6 +2431,18 @@
"braces" "^3.0.2"
"picomatch" "^2.3.1"
+"mime-db@1.52.0":
+ "integrity" "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
+ "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
+ "version" "1.52.0"
+
+"mime-types@^2.1.12":
+ "integrity" "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="
+ "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
+ "version" "2.1.35"
+ dependencies:
+ "mime-db" "1.52.0"
+
"mini-svg-data-uri@^1.2.3":
"integrity" "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg=="
"resolved" "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz"
@@ -2790,6 +2847,11 @@
"resolved" "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz"
"version" "6.2.0"
+"proxy-from-env@^1.1.0":
+ "integrity" "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ "resolved" "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz"
+ "version" "1.1.0"
+
"punycode@^2.1.0":
"integrity" "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw=="
"resolved" "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz"
@@ -2877,7 +2939,7 @@
"resolved" "https://registry.npmjs.org/react-wrap-balancer/-/react-wrap-balancer-0.3.0.tgz"
"version" "0.3.0"
-"react@^16.5.1 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8||^17||^18", "react@^16.9.0 || ^17.0.0 || ^18.0.0", "react@^17.0.2 || ^18", "react@^18.0.0", "react@^18.2.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>=16", "react@>=16.3.0", "react@>=16.8.0", "react@18.2.0":
+"react@^16.5.1 || ^17.0.0 || ^18.0.0", "react@^16.8 || ^17.0 || ^18.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8||^17||^18", "react@^16.9.0 || ^17.0.0 || ^18.0.0", "react@^17.0.2 || ^18", "react@^18.0.0", "react@^18.2.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>=16", "react@>=16.3.0", "react@>=16.8", "react@>=16.8.0", "react@18.2.0":
"integrity" "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="
"resolved" "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
"version" "18.2.0"
@@ -3431,6 +3493,11 @@
"detect-node-es" "^1.1.0"
"tslib" "^2.0.0"
+"use-sync-external-store@1.2.0":
+ "integrity" "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
+ "resolved" "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz"
+ "version" "1.2.0"
+
"util-deprecate@^1.0.2":
"integrity" "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
"resolved" "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"
@@ -3575,3 +3642,10 @@
"integrity" "sha512-rD3L4jyMlO1m+RWU60lNwZQK5zmzglCV5fI1gTRikmpv3YzmNIZQbjyfE6cMNb9Xaly/C1SwemYGbsiOekMvnQ=="
"resolved" "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.3.0.tgz"
"version" "0.3.0"
+
+"zustand@^4.3.2":
+ "integrity" "sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw=="
+ "resolved" "https://registry.npmjs.org/zustand/-/zustand-4.3.2.tgz"
+ "version" "4.3.2"
+ dependencies:
+ "use-sync-external-store" "1.2.0"