Skip to content

Commit

Permalink
fix unauthenticated user to add to cart
Browse files Browse the repository at this point in the history
  • Loading branch information
fachrihawari committed Oct 2, 2024
1 parent 5a3231e commit ab0fa37
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 62 deletions.
4 changes: 2 additions & 2 deletions src/app/(main)/cart/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import CartNotLoggedIn from './components/CartNotLoggedIn';
import CartEmpty from './components/CartEmpty';
import CartItems from './components/CartItems';
import { getCart } from '@/lib/actions/cart';
import { isLoggedIn } from '@/lib/utils/auth';
import { isLoggedIn } from '@/lib/actions/users';
import CartSummary from './components/CartSummary';

export default async function CartPage() {
const cart = await getCart();

let content;

if (!isLoggedIn()) {
if (!await isLoggedIn()) {
content = <CartNotLoggedIn />
} else if (cart.items.length === 0) {
content = <CartEmpty />
Expand Down
4 changes: 2 additions & 2 deletions src/app/(main)/orders/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { getOrders } from "@/lib/actions/orders";
import OrdersEmpty from './components/OrdersEmpty';
import OrdersList from './components/OrdersList';
import { isLoggedIn } from '@/lib/utils/auth';
import { isLoggedIn } from '@/lib/actions/users';
import OrdersNotLoggedIn from './components/OrdersNotLoggedIn';

export default async function OrdersPage() {
const orders = await getOrders();

let content;

if (!isLoggedIn()) {
if (!await isLoggedIn()) {
content = <OrdersNotLoggedIn />
} else if (orders.length === 0) {
content = <OrdersEmpty />
Expand Down
2 changes: 1 addition & 1 deletion src/app/(main)/payment/[token]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { useMidtrans } from "@/lib/hooks/useMidtrans"
import { setQueryParams } from "@/lib/utils/url"
import { useEffect } from "react"
import { useRouter } from "next/navigation"

type PaymentPageProps = {
params: {
token: string
}
}

export default function PaymentPage({ params }: PaymentPageProps) {
const { token } = params
const router = useRouter()
Expand Down
12 changes: 11 additions & 1 deletion src/components/AddToCartButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { useEffect, useState } from 'react';
import { FiShoppingCart, FiPlus, FiMinus } from "react-icons/fi";
import { addToCart, getCart, removeFromCart, updateCartItemQuantity } from "@/lib/actions/cart";
import type { Product } from "@/lib/db/product_collection";
import { isLoggedIn } from '@/lib/actions/users';
import { swal } from '@/lib/utils/swal';

interface AddToCartButtonProps {
product: Product;
Expand Down Expand Up @@ -32,6 +34,14 @@ export default function AddToCartButton({ product, size = 'small' }: AddToCartBu
}, [product._id]);

const handleAddToCart = async () => {
if (!await isLoggedIn()) {
return swal({
title: 'Unauthenticated',
type: 'error',
message: 'You must be login to add product to the cart'
})
}

setIsLoading(true);
if (isInCart) {
await updateCartItemQuantity(product._id.toString(), quantity + 1);
Expand Down Expand Up @@ -119,4 +129,4 @@ export default function AddToCartButton({ product, size = 'small' }: AddToCartBu
{isLoading ? 'Adding...' : 'Add to Cart'}
</button>
);
}
}
4 changes: 2 additions & 2 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { buildSearchParams, setQueryParams } from '@/lib/utils/url';
import TokoPakEdiLogo from './TokoPakEdiLogo';
import { logout } from '@/lib/actions/users';
import { getCart } from '@/lib/actions/cart';
import { isLoggedIn } from '@/lib/utils/auth';
import { isLoggedIn } from '@/lib/actions/users';

async function Navbar() {
const searchParams = buildSearchParams(headers().get('x-current-url')) // HACK: get current url from headers
Expand Down Expand Up @@ -71,7 +71,7 @@ async function Navbar() {
</Link>
<div className="flex items-center space-x-2">
{
isLoggedIn() ? (
await isLoggedIn() ? (
<form action={logout}>
<button type='submit' className="bg-white text-red-500 border border-red-500 hover:bg-red-500 hover:text-white px-3 py-1 rounded-md">
Logout
Expand Down
52 changes: 6 additions & 46 deletions src/components/SweetAlert.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,20 @@
'use client'

import { swal, SwalOption } from "@/lib/utils/swal"
import { usePathname, useRouter, useSearchParams } from "next/navigation"
import { useEffect } from "react"
import Swal from "sweetalert2"

function SweetAlert() {
const searchParams = useSearchParams()
const pathname = usePathname()
const router = useRouter()
const message = searchParams.get('message')
const title = searchParams.get('title')
const type = searchParams.get('type') as 'success' | 'error' | 'info' | null

const colorClasses = {
success: 'bg-green-500 hover:bg-green-600',
error: 'bg-red-500 hover:bg-red-600',
info: 'bg-blue-500 hover:bg-blue-600'
}
const message = searchParams.get('message') as string
const title = searchParams.get('title') as string
const type = searchParams.get('type') as SwalOption['type']

useEffect(() => {
if (message && type) {
const isError = type === 'error'
const messageArray = message.split(',')

const titleHtml = isError && messageArray.length > 1
? `<p class="mb-2 text-gray-700">Please correct the following ${message.includes(',') ? 'errors' : 'error'}:</p>` : ''
const messageHtml = messageArray.length > 1 ?
`<ul class="list-disc list-inside space-y-1">
${messageArray.map((msg) => `<li>${msg.trim()}</li>`).join('')}
</ul>` : `<p class="text-center">${messageArray[0]}</p>`

Swal.fire({
icon: type,
title: title || type.charAt(0).toUpperCase() + type.slice(1),
html: `
<div class="text-left">
${titleHtml}
${messageHtml}
</div >
`,
customClass: {
popup: 'rounded-lg shadow-xl border border-gray-200',
title: `text-2xl font-bold mb-4`,
htmlContainer: 'text-base',
confirmButton: `${colorClasses[type]} text-white font-semibold py-2 px-4 rounded`
},
buttonsStyling: false,
showConfirmButton: true,
confirmButtonText: isError ? 'Try Again' : 'OK',
showCloseButton: false,
timer: 8000,
timerProgressBar: true
})

router.replace(pathname)
}
swal({ type, title, message })
router.replace(pathname)
}, [message, title, type, router, pathname])

return null
Expand Down
10 changes: 8 additions & 2 deletions src/lib/actions/cart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import { cookies } from "next/headers";
import { Cart } from "@/lib/db/cart_collection";
import { isLoggedIn } from "@/lib/utils/auth";
import { isLoggedIn } from "@/lib/actions/users";
import { ObjectId } from "mongodb";
import { revalidateTag } from "next/cache";

const NEXT_PUBLIC_URL = process.env.NEXT_PUBLIC_URL;

export async function getCart(): Promise<Cart> {
if (!isLoggedIn()) {
if (!await isLoggedIn()) {
return { items: [], _id: new ObjectId(), userId: new ObjectId() }
}
const res = await fetch(`${NEXT_PUBLIC_URL}/api/cart`, {
Expand All @@ -29,6 +29,8 @@ export async function getCart(): Promise<Cart> {
}

export async function addToCart(productId: string, quantity: number) {
if (!await isLoggedIn()) return

await fetch(`${NEXT_PUBLIC_URL}/api/cart/${productId}`, {
method: 'POST',
body: JSON.stringify({ quantity }),
Expand All @@ -41,6 +43,8 @@ export async function addToCart(productId: string, quantity: number) {
}

export async function updateCartItemQuantity(productId: string, quantity: number) {
if (!await isLoggedIn()) return

await fetch(`${NEXT_PUBLIC_URL}/api/cart/${productId}`, {
method: 'PUT',
body: JSON.stringify({ quantity }),
Expand All @@ -53,6 +57,8 @@ export async function updateCartItemQuantity(productId: string, quantity: number
}

export async function removeFromCart(productId: string) {
if (!await isLoggedIn()) return

await fetch(`${NEXT_PUBLIC_URL}/api/cart/${productId}`, {
method: 'DELETE',
headers: {
Expand Down
8 changes: 8 additions & 0 deletions src/lib/actions/orders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { redirect } from "next/navigation";
import { revalidateTag } from "next/cache";
import { setQueryParams } from "@/lib/utils/url";
import { Order } from "@/lib/db/order_collection";
import { isLoggedIn } from "./users";

const NEXT_PUBLIC_URL = process.env.NEXT_PUBLIC_URL

export const createOrder = async () => {
if (!await isLoggedIn()) return

const res = await fetch(`${NEXT_PUBLIC_URL}/api/orders`, {
method: 'POST',
headers: {
Expand All @@ -28,9 +31,14 @@ export const createOrder = async () => {
}

export const getOrders = async (): Promise<Order[]> => {
if (!await isLoggedIn()) return []

const res = await fetch(`${NEXT_PUBLIC_URL}/api/orders`, {
headers: {
Cookie: cookies().toString()
},
next: {
tags: ['orders']
}
});

Expand Down
9 changes: 8 additions & 1 deletion src/lib/actions/users.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use server';

import { redirect } from "next/navigation";
import { setQueryParams } from "../utils/url";
import { cookies } from "next/headers";
import { revalidateTag } from "next/cache";
import { setQueryParams } from "@/lib/utils/url";

export const register = async (formData: FormData) => {
const res = await fetch(process.env.NEXT_PUBLIC_URL + "/api/auth/register", {
Expand Down Expand Up @@ -64,5 +65,11 @@ export const login = async (formData: FormData) => {

export const logout = async () => {
cookies().delete('token');
revalidateTag('cart')
revalidateTag('orders')
redirect('/');
};

export const isLoggedIn = async () => {
return cookies().has('token')
}
5 changes: 0 additions & 5 deletions src/lib/utils/auth.ts

This file was deleted.

49 changes: 49 additions & 0 deletions src/lib/utils/swal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import Swal from "sweetalert2"

const colorClasses = {
success: 'bg-green-500 hover:bg-green-600',
error: 'bg-red-500 hover:bg-red-600',
info: 'bg-blue-500 hover:bg-blue-600'
}

export type SwalOption = {
message: string
type: 'success' | 'error' | 'info'
title?: string
}
export function swal({ type, title, message }: SwalOption) {
if (message && type) {
const isError = type === 'error'
const messageArray = message.split(',')

const titleHtml = isError && messageArray.length > 1
? `<p class="mb-2 text-gray-700">Please correct the following ${message.includes(',') ? 'errors' : 'error'}:</p>` : ''
const messageHtml = messageArray.length > 1 ?
`<ul class="list-disc list-inside space-y-1">
${messageArray.map((msg) => `<li>${msg.trim()}</li>`).join('')}
</ul>` : `<p class="text-center">${messageArray[0]}</p>`

Swal.fire({
icon: type,
title: title || type.charAt(0).toUpperCase() + type.slice(1),
html: `
<div class="text-left">
${titleHtml}
${messageHtml}
</div >
`,
customClass: {
popup: 'rounded-lg shadow-xl border border-gray-200',
title: `text-2xl font-bold mb-4`,
htmlContainer: 'text-base',
confirmButton: `${colorClasses[type]} text-white font-semibold py-2 px-4 rounded`
},
buttonsStyling: false,
showConfirmButton: true,
confirmButtonText: isError ? 'Try Again' : 'OK',
showCloseButton: false,
timer: 8000,
timerProgressBar: true
})
}
}

0 comments on commit ab0fa37

Please sign in to comment.