Skip to content

Commit ffd2a09

Browse files
committed
Feat(QR): Add qr for mobile login
1 parent c225258 commit ffd2a09

2 files changed

Lines changed: 177 additions & 69 deletions

File tree

src/components/Navbar.tsx

Lines changed: 171 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2,88 +2,194 @@ import { useSession } from "next-auth/react";
22
import Image from "next/image";
33
import React from "react";
44
import { useDrawer } from "@/lib/hooks/useDrawer";
5-
import {signOut} from "next-auth/react";import { getLoginUrl } from "@/lib/util/getLoginUrl";
5+
import { signOut } from "next-auth/react";
6+
import { getLoginUrl } from "@/lib/util/getLoginUrl";
67
import { router } from "@/core/trpc";
78
import { getConsoleUrl } from "@/lib/util/getCallbackUrl";
89
import { useRouter } from "next/router";
9-
;
10+
import { useHost } from "@/lib/hooks/useHost";
11+
import { useTenant } from "@/lib/hooks/useTenant";
12+
import { useModal } from "@/lib/hooks/useModel";
13+
import { useQRCode } from "next-qrcode";
1014

1115
export function Navbar() {
12-
const { data, toggle } = useDrawer();
13-
const { show: sideBarShowing } = data ?? {};
14-
const session = useSession();
15-
const router = useRouter();
16-
return (
17-
<div className="navbar bg-base-100 border-b-2 border-gray-100">
18-
<div className="flex-none">
16+
const { data, toggle } = useDrawer();
17+
const { show: sideBarShowing } = data ?? {};
18+
const session = useSession();
19+
const router = useRouter();
1920

20-
{/* <button onClick={(e)=>{
21+
const host = useHost();
22+
const { tenant } = useTenant();
23+
const [showModal, hideModal] = useModal();
24+
const { Canvas } = useQRCode();
25+
26+
return (
27+
<div className="navbar bg-base-100 border-b-2 border-gray-100">
28+
<div className="flex-none">
29+
{/* <button onClick={(e)=>{
2130
updateDrawer({drawerIsOpen:!sideBarShowing})
2231
}} className="btn btn-square btn-ghost">
2332
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="inline-block w-5 h-5 stroke-current"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"></path></svg>
2433
</button> */}
2534

35+
<label className="btn btn-circle swap swap-rotate lg:hidden">
36+
<input
37+
checked={sideBarShowing}
38+
type="checkbox"
39+
className="hidden"
40+
onChange={(e) => {
41+
if (e.target.checked !== sideBarShowing) {
42+
e.target.checked ? toggle(false) : toggle(true);
43+
}
44+
}}
45+
/>
2646

27-
<label className="btn btn-circle swap swap-rotate lg:hidden">
28-
<input checked={sideBarShowing} type="checkbox" className="hidden" onChange={(e) => {
29-
30-
if (e.target.checked !== sideBarShowing) {
31-
e.target.checked ? toggle(false) : toggle(true);
32-
}
33-
34-
}} />
35-
36-
<svg className="swap-off fill-current" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><path d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" /></svg>
37-
38-
<svg className="swap-on fill-current" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 512 512"><polygon points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49" /></svg>
39-
40-
</label>
47+
<svg
48+
className="swap-off fill-current"
49+
xmlns="http://www.w3.org/2000/svg"
50+
width="32"
51+
height="32"
52+
viewBox="0 0 512 512"
53+
>
54+
<path d="M64,384H448V341.33H64Zm0-106.67H448V234.67H64ZM64,128v42.67H448V128Z" />
55+
</svg>
4156

42-
</div>
43-
<div className="flex-1">
44-
<a className="btn btn-ghost normal-case text-lg">
45-
<Image
46-
47-
src="/logo-yavin2.png"
48-
width={40}
49-
height={40}
50-
alt="logo" /> <span className="mx-2">Shop care</span>
51-
</a>
52-
</div>
53-
<div className="flex-none">
54-
{/* <button className="btn btn-square btn-ghost">
57+
<svg
58+
className="swap-on fill-current"
59+
xmlns="http://www.w3.org/2000/svg"
60+
width="32"
61+
height="32"
62+
viewBox="0 0 512 512"
63+
>
64+
<polygon points="400 145.49 366.51 112 256 222.51 145.49 112 112 145.49 222.51 256 112 366.51 145.49 400 256 289.49 366.51 400 400 366.51 289.49 256 400 145.49" />
65+
</svg>
66+
</label>
67+
</div>
68+
<div className="flex-1">
69+
<a className="btn btn-ghost normal-case text-lg">
70+
<Image src="/logo-yavin2.png" width={40} height={40} alt="logo" />{" "}
71+
<span className="mx-2">Shop care</span>
72+
</a>
73+
</div>
74+
<div className="flex-none">
75+
{/* <button className="btn btn-square btn-ghost">
5576
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="inline-block w-5 h-5 stroke-current"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z"></path></svg>
5677
</button> */}
57-
<div className="dropdown dropdown-end">
58-
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
59-
<div className="w-10 rounded-full">
60-
{session.status == "authenticated" && <Image
61-
src={ session.data.user.image ??"/logo-yavin2.png"}
62-
width={40}
63-
height={40}
64-
alt={session.data.user.name ?? "User avatar"} />}
78+
<div className="dropdown dropdown-end">
79+
<label tabIndex={0} className="btn btn-ghost btn-circle avatar">
80+
<div className="w-10 rounded-full">
81+
{session.status == "authenticated" && (
82+
<Image
83+
src={session.data.user.image ?? "/logo-yavin2.png"}
84+
width={40}
85+
height={40}
86+
alt={session.data.user.name ?? "User avatar"}
87+
/>
88+
)}
89+
</div>
90+
</label>
91+
<ul
92+
tabIndex={0}
93+
className="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box w-52"
94+
>
95+
<li
96+
onClick={(e) => {
97+
router.push("/settings/system");
98+
}}
99+
>
100+
<a className="justify-between">
101+
Settings
102+
<span className="badge">New</span>
103+
</a>
104+
</li>
105+
<li
106+
onClick={(e) => {
107+
router.push(getConsoleUrl());
108+
}}
109+
>
110+
<a>Console</a>
111+
</li>
112+
{tenant&& <li
113+
onClick={(e) => {
114+
let cookie = document.cookie
115+
.split(";")
116+
.map((c) => c.trim())
117+
.find((c) => c.startsWith("next-auth.session-token"));
65118

119+
let { members, ...info } = tenant;
66120

67-
</div>
68-
</label>
69-
<ul tabIndex={0} className="mt-3 p-2 shadow menu menu-compact dropdown-content bg-base-100 rounded-box w-52">
70-
<li onClick={(e)=>{
71-
router.push("/settings/system")
72-
}}>
73-
<a className="justify-between">
74-
Settings
75-
<span className="badge">New</span>
121+
let qr = {
122+
token: cookie,
123+
host,
124+
tenant: info,
125+
};
126+
console.log(qr);
127+
showModal({
128+
// position:ModalPosition.
129+
content: ({
130+
show,
131+
hide,
132+
ModalContainer,
133+
ModalContent,
134+
ModalAction,
135+
}) => {
136+
return (
137+
<ModalContainer>
138+
<ModalContent>
139+
<h4 className="my-2 text text-lg">Scan QR with pos mobile app</h4>
140+
<div className="flex row">
141+
<Canvas
142+
text={JSON.stringify(qr)}
143+
options={{
144+
errorCorrectionLevel: "M",
145+
margin: 3,
146+
147+
scale: 4,
148+
width: 200,
149+
color: {
150+
dark: "#010599FF",
151+
light: "#FFBF60FF",
152+
},
153+
}}
154+
/>
155+
<div className="col ml-2 justify-between">
156+
<div>{tenant.name}</div>
157+
<div>{tenant.description}</div>
158+
<Image width={50} height={50} alt="logo" src={((JSON.parse(tenant.logo??"") as string[])??[""]).at(0)??""}/>
159+
</div>
160+
</div>
161+
<ModalAction>
162+
<a
163+
className="btn"
164+
onClick={() => {
165+
hide();
166+
}}
167+
>
168+
Dismiss
76169
</a>
77-
</li>
78-
<li onClick={(e)=>{
79-
router.push(getConsoleUrl())
80-
}}><a>Console</a></li>
81-
<li onClick={(e)=>signOut({
82-
callbackUrl:getLoginUrl()
83-
})}><a >Logout</a></li>
84-
</ul>
85-
</div>
86-
</div>
170+
</ModalAction>
171+
</ModalContent>
172+
</ModalContainer>
173+
);
174+
},
175+
});
176+
}}
177+
>
178+
<a>Mobile pos</a>
179+
</li>
180+
}
181+
<li
182+
onClick={(e) =>
183+
signOut({
184+
callbackUrl: getLoginUrl(),
185+
})
186+
}
187+
>
188+
<a>Logout</a>
189+
</li>
190+
</ul>
87191
</div>
88-
);
192+
</div>
193+
</div>
194+
);
89195
}

src/core/authentication/auth.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ import { Prisma } from "@prisma/client";
1212

1313
const useSecureCookies = process.env.NODE_ENV === 'production';
1414

15-
const cookieBuilder = (name:string)=>({
15+
const cookieBuilder = (name:string,httpOnly:boolean=true)=>({
1616
name:`${useSecureCookies?'__Secure-':''}next-auth.${name}`,
1717
options:{
18-
httpOnly:true,
18+
httpOnly,
1919
sameSite: 'Lax',
2020
path:'/',
2121
domain: `.${(new URL(process.env.NEXTAUTH_URL!)).hostname}`,
@@ -72,7 +72,7 @@ export const authOptions: NextAuthOptions = {
7272
id: profile.sub,
7373
name: profile.name,
7474
email: profile.email,
75-
image: profile.picture
75+
image: profile.picture,
7676
};
7777
},
7878
},
@@ -88,7 +88,8 @@ export const authOptions: NextAuthOptions = {
8888
debug:true,
8989
useSecureCookies:useSecureCookies,
9090
cookies:{
91-
sessionToken:cookieBuilder("session-token"),
91+
//TODO change this to httponly cookie after we find a better way to read the cookie from js
92+
sessionToken:cookieBuilder("session-token",false),
9293
csrfToken:cookieBuilder('csrf-token'),
9394
state:cookieBuilder('state'),
9495
nonce:cookieBuilder("nonce"),
@@ -126,6 +127,7 @@ export const authOptions: NextAuthOptions = {
126127
session: ({ session, user,token }) => ({
127128
...session,
128129
token,
130+
129131
user: {
130132
...session.user,
131133
id: user.id,

0 commit comments

Comments
 (0)