Compare commits
1 Commits
develop
...
feature/ME
| Author | SHA1 | Date | |
|---|---|---|---|
| ab0834149d |
22
.env
22
.env
@@ -53,5 +53,23 @@ NEXT_PUBLIC_DEFAULT_LOCALE=et
|
|||||||
NEXT_PUBLIC_TEAM_NAVIGATION_STYLE=custom
|
NEXT_PUBLIC_TEAM_NAVIGATION_STYLE=custom
|
||||||
NEXT_PUBLIC_USER_NAVIGATION_STYLE=custom
|
NEXT_PUBLIC_USER_NAVIGATION_STYLE=custom
|
||||||
|
|
||||||
# MEDUSA
|
#### MEDUSA
|
||||||
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=
|
#NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_0ec86252438b38ce18d5601f7877e4395d7e0a6afa8687dfea8d37af33015633
|
||||||
|
#MEDUSA_BACKEND_URL=http://5.181.51.38:9000
|
||||||
|
NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_e23a820689a07d55aa0a0ad187268559f5d6288ecb0768ff4520516285bdef84
|
||||||
|
MEDUSA_BACKEND_URL=http://localhost:9000
|
||||||
|
# NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_068d930c33fea53608a410d84a51935f6ce2ccec5bef8e0ecf75eaee602ac486
|
||||||
|
# MEDUSA_BACKEND_URL=https://backoffice-test.medreport.ee:443
|
||||||
|
|
||||||
|
#### MONTONIO
|
||||||
|
NEXT_PUBLIC_MONTONIO_ACCESS_KEY=7da5d7fa-3383-4997-9435-46aa818f4ead
|
||||||
|
MONTONIO_SECRET_KEY=rNZkzwxOiH93mzkdV53AvhSsbGidrgO2Kl5lE/IT7cvo
|
||||||
|
MONTONIO_API_URL=https://sandbox-stargate.montonio.com
|
||||||
|
|
||||||
|
#### SUPABASE
|
||||||
|
# NEXT_PUBLIC_SUPABASE_URL=https://oqsdacktkhmbylmzstjq.supabase.co
|
||||||
|
# NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9xc2RhY2t0a2htYnlsbXpzdGpxIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDY1MjgxMjMsImV4cCI6MjA2MjEwNDEyM30.LdHCTWxijFmhXdnT9KVuLRAVbtSwY7OO-oLtpd8GmO0
|
||||||
|
# SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9xc2RhY2t0a2htYnlsbXpzdGpxIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc0NjUyODEyMywiZXhwIjoyMDYyMTA0MTIzfQ.KVcnkZ21Pd0XkJho23dZqFHawVTLQqfvF7l2RxsELLk
|
||||||
|
NEXT_PUBLIC_SUPABASE_URL=http://5.181.51.38:54321
|
||||||
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
|
||||||
|
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# These values are only used when running the app in development mode.
|
# These values are only used when running the app in development mode.
|
||||||
|
|
||||||
# SUPABASE
|
# SUPABASE
|
||||||
NEXT_PUBLIC_SUPABASE_URL=http://127.0.0.1:54321
|
NEXT_PUBLIC_SUPABASE_URL=http://5.181.51.38:54321
|
||||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6ImFub24iLCJleHAiOjE5ODM4MTI5OTZ9.CRXP1A7WOeoJeXxjNni43kdQwgnWNReilDMblYTn_I0
|
||||||
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
|
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZS1kZW1vIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImV4cCI6MTk4MzgxMjk5Nn0.EGIM96RAZx35lJzdJsyH-qQwv8Hdp7fsn3W0YpN81IU
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ export const POST = enhanceRouteHandler(
|
|||||||
const body = await request.json();
|
const body = await request.json();
|
||||||
const namespace = 'montonio.verify-token';
|
const namespace = 'montonio.verify-token';
|
||||||
|
|
||||||
|
const activeCartId = request.cookies.get('_medusa_cart_id')?.value;
|
||||||
|
console.info('cart id', activeCartId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { token } = BodySchema.parse(body);
|
const { token } = BodySchema.parse(body);
|
||||||
|
|
||||||
@@ -58,6 +61,12 @@ export const POST = enhanceRouteHandler(
|
|||||||
algorithms: ['HS256'],
|
algorithms: ['HS256'],
|
||||||
}) as MontonioOrderToken;
|
}) as MontonioOrderToken;
|
||||||
|
|
||||||
|
const [, cartId] = decoded.merchantReferenceDisplay.split(':');
|
||||||
|
console.info('active cart id parsed', {cartId, activeCartId, decoded:decoded.merchantReferenceDisplay});
|
||||||
|
if (cartId !== activeCartId) {
|
||||||
|
throw new Error('Invalid cart id');
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
{
|
{
|
||||||
name: namespace,
|
name: namespace,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function CartItems({ cart, items, productColumnLabelKey }: {
|
|||||||
return (
|
return (
|
||||||
<Table className="rounded-lg border border-separate">
|
<Table className="rounded-lg border border-separate">
|
||||||
<TableHeader className="text-ui-fg-subtle txt-medium-plus">
|
<TableHeader className="text-ui-fg-subtle txt-medium-plus">
|
||||||
<TableRow className="">
|
<TableRow>
|
||||||
<TableHead className="px-6">
|
<TableHead className="px-6">
|
||||||
<Trans i18nKey={productColumnLabelKey} />
|
<Trans i18nKey={productColumnLabelKey} />
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Button } from '@kit/ui/button';
|
|||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
import { placeOrder } from "@lib/data/cart"
|
import { placeOrder } from "@lib/data/cart"
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Loading from '@/app/home/loading';
|
import GlobalLoader from '../../loading';
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
LOADING = 'LOADING',
|
LOADING = 'LOADING',
|
||||||
@@ -18,12 +18,17 @@ enum Status {
|
|||||||
export function MontonioCheckoutCallback() {
|
export function MontonioCheckoutCallback() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [status, setStatus] = useState<Status>(Status.LOADING);
|
const [status, setStatus] = useState<Status>(Status.LOADING);
|
||||||
|
const [isFinalized, setIsFinalized] = useState(false);
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (isFinalized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const token = searchParams.get('order-token');
|
const token = searchParams.get('order-token');
|
||||||
if (!token) {
|
if (!token) {
|
||||||
router.push('/home/cart');
|
//router.push('/home/cart');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +43,7 @@ export function MontonioCheckoutCallback() {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({ token }),
|
body: JSON.stringify({ token }),
|
||||||
});
|
});
|
||||||
|
setIsFinalized(true);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const body = await response.json();
|
const body = await response.json();
|
||||||
@@ -54,7 +60,7 @@ export function MontonioCheckoutCallback() {
|
|||||||
router.push('/home/cart');
|
router.push('/home/cart');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setStatus(Status.ERROR);
|
throw new Error('Payment failed or pending');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Error verifying token", e);
|
console.error("Error verifying token", e);
|
||||||
@@ -63,7 +69,7 @@ export function MontonioCheckoutCallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void verifyToken();
|
void verifyToken();
|
||||||
}, [searchParams]);
|
}, [searchParams, isFinalized]);
|
||||||
|
|
||||||
if (status === Status.ERROR) {
|
if (status === Status.ERROR) {
|
||||||
return (
|
return (
|
||||||
@@ -91,5 +97,5 @@ export function MontonioCheckoutCallback() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (<Loading />);
|
return <GlobalLoader />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export default function CartTotals({ order }: {
|
|||||||
</div>
|
</div>
|
||||||
<div className="h-px w-full border-b border-gray-200 my-4" />
|
<div className="h-px w-full border-b border-gray-200 my-4" />
|
||||||
<div className="flex items-center justify-between text-ui-fg-base mb-2 txt-medium ">
|
<div className="flex items-center justify-between text-ui-fg-base mb-2 txt-medium ">
|
||||||
<span><Trans i18nKey="cart:orderConfirmed.total" /></span>
|
<span className="font-bold"><Trans i18nKey="cart:orderConfirmed.total" /></span>
|
||||||
<span
|
<span
|
||||||
className="txt-xlarge-plus"
|
className="txt-xlarge-plus"
|
||||||
data-testid="cart-total"
|
data-testid="cart-total"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
import { PageBody, PageHeader } from '@kit/ui/page';
|
import { PageBody, PageHeader } from '@kit/ui/page';
|
||||||
import { StoreOrder } from "@medusajs/types"
|
import { StoreOrder } from "@medusajs/types"
|
||||||
|
import Divider from "@modules/common/components/divider"
|
||||||
|
|
||||||
import CartTotals from "./cart-totals"
|
import CartTotals from "./cart-totals"
|
||||||
import OrderDetails from "./order-details"
|
import OrderDetails from "./order-details"
|
||||||
@@ -14,8 +15,10 @@ export default async function OrderCompleted({
|
|||||||
return (
|
return (
|
||||||
<PageBody>
|
<PageBody>
|
||||||
<PageHeader title={<Trans i18nKey="cart:orderConfirmed.title" />} />
|
<PageHeader title={<Trans i18nKey="cart:orderConfirmed.title" />} />
|
||||||
|
<Divider />
|
||||||
<div className="grid grid-cols-1 small:grid-cols-[1fr_360px] gap-x-40 lg:px-4 gap-y-6">
|
<div className="grid grid-cols-1 small:grid-cols-[1fr_360px] gap-x-40 lg:px-4 gap-y-6">
|
||||||
<OrderDetails order={order} />
|
<OrderDetails order={order} />
|
||||||
|
<Divider />
|
||||||
<OrderItems order={order} />
|
<OrderItems order={order} />
|
||||||
<CartTotals order={order} />
|
<CartTotals order={order} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,13 +11,13 @@ export default function OrderItem({ item, currencyCode }: {
|
|||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<TableRow className="w-full" data-testid="product-row">
|
<TableRow className="w-full" data-testid="product-row">
|
||||||
{/* <TableCell className="!pl-0 p-4 w-24">
|
{/* <TableCell className="px-6 w-24">
|
||||||
<div className="flex w-16">
|
<div className="flex w-16">
|
||||||
<Thumbnail thumbnail={item.thumbnail} size="square" />
|
<Thumbnail thumbnail={item.thumbnail} size="square" />
|
||||||
</div>
|
</div>
|
||||||
</TableCell> */}
|
</TableCell> */}
|
||||||
|
|
||||||
<TableCell className="text-left">
|
<TableCell className="text-left px-6">
|
||||||
<span
|
<span
|
||||||
className="txt-medium-plus text-ui-fg-base"
|
className="txt-medium-plus text-ui-fg-base"
|
||||||
data-testid="product-name"
|
data-testid="product-name"
|
||||||
@@ -27,8 +27,8 @@ export default function OrderItem({ item, currencyCode }: {
|
|||||||
<LineItemOptions variant={item.variant} data-testid="product-variant" />
|
<LineItemOptions variant={item.variant} data-testid="product-variant" />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell className="!pr-0">
|
<TableCell className="px-6">
|
||||||
<span className="!pr-0 flex flex-col items-end h-full justify-center">
|
<span className="flex flex-col items-end h-full justify-center">
|
||||||
<span className="flex gap-x-1 ">
|
<span className="flex gap-x-1 ">
|
||||||
<span className="text-ui-fg-muted">
|
<span className="text-ui-fg-muted">
|
||||||
{item.quantity}x{" "}
|
{item.quantity}x{" "}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import repeat from "@lib/util/repeat"
|
|||||||
import { StoreOrder } from "@medusajs/types"
|
import { StoreOrder } from "@medusajs/types"
|
||||||
import { Table, TableBody } from "@kit/ui/table"
|
import { Table, TableBody } from "@kit/ui/table"
|
||||||
|
|
||||||
import Divider from "@modules/common/components/divider"
|
|
||||||
import SkeletonLineItem from "@modules/skeletons/components/skeleton-line-item"
|
import SkeletonLineItem from "@modules/skeletons/components/skeleton-line-item"
|
||||||
import OrderItem from "./order-item"
|
import OrderItem from "./order-item"
|
||||||
import { Heading } from "@kit/ui/heading"
|
import { Heading } from "@kit/ui/heading"
|
||||||
@@ -19,8 +18,7 @@ export default function OrderItems({ order }: {
|
|||||||
<Trans i18nKey="cart:orderConfirmed.summary" />
|
<Trans i18nKey="cart:orderConfirmed.summary" />
|
||||||
</Heading>
|
</Heading>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Divider className="!mb-0" />
|
<Table className="rounded-lg border border-separate">
|
||||||
<Table>
|
|
||||||
<TableBody data-testid="products-table">
|
<TableBody data-testid="products-table">
|
||||||
{items?.length
|
{items?.length
|
||||||
? items
|
? items
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ export async function register() {
|
|||||||
* @param err
|
* @param err
|
||||||
*/
|
*/
|
||||||
export const onRequestError: Instrumentation.onRequestError = async (err) => {
|
export const onRequestError: Instrumentation.onRequestError = async (err) => {
|
||||||
const { getServerMonitoringService } = await import('@kit/monitoring/server');
|
// const { getServerMonitoringService } = await import('@kit/monitoring/server');
|
||||||
|
|
||||||
const service = await getServerMonitoringService();
|
// const service = await getServerMonitoringService();
|
||||||
|
|
||||||
await service.ready();
|
// await service.ready();
|
||||||
await service.captureException(err as Error);
|
// await service.captureException(err as Error);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export async function handleNavigateToPayment({ language }: { language: string }
|
|||||||
currency: cart.currency_code.toUpperCase(),
|
currency: cart.currency_code.toUpperCase(),
|
||||||
description: `Order from Medreport`,
|
description: `Order from Medreport`,
|
||||||
locale: language,
|
locale: language,
|
||||||
merchantReference: `${account.id}:${Date.now()}`,
|
merchantReference: `${account.id}:${cart.id}:${Date.now()}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { error } = await supabase
|
const { error } = await supabase
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export class MontonioWebhookHandlerService
|
|||||||
}, `Received Montonio webhook event`);
|
}, `Received Montonio webhook event`);
|
||||||
|
|
||||||
if (event.paymentStatus === 'PAID') {
|
if (event.paymentStatus === 'PAID') {
|
||||||
const accountId = event.merchantReferenceDisplay.split(':')[0];
|
const [accountId] = event.merchantReferenceDisplay.split(':');
|
||||||
if (!accountId) {
|
if (!accountId) {
|
||||||
throw new Error('Invalid merchant reference');
|
throw new Error('Invalid merchant reference');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
"orderConfirmed": {
|
"orderConfirmed": {
|
||||||
"title": "Tellimus on edukalt esitatud",
|
"title": "Tellimus on edukalt esitatud",
|
||||||
"summary": "Summa",
|
"summary": "Teenused",
|
||||||
"subtotal": "Vahesumma",
|
"subtotal": "Vahesumma",
|
||||||
"taxes": "Maksud",
|
"taxes": "Maksud",
|
||||||
"giftCard": "Kinkekaart",
|
"giftCard": "Kinkekaart",
|
||||||
|
|||||||
Reference in New Issue
Block a user