feat(dimentorin): wire appointment payment flow to payments API
- PaymentStep: selectable VA/QRIS method, rate from mentor.mentoring_rate (fallback 50000), onMethodChange - AppointmentModal: book session -> create payment -> route to VA/QRIS step with real payment data; then success - QrisPaymentStep/VAPaymentStep: show real total + external_ref (VA number/QR ref) + expiry - service lib: TPayment/TCreatePaymentRequest types + postCreatePayment/getMyPayments/getPaymentById/postConfirmPayment + hooks - build verified, payments flow bundled
This commit is contained in:
+34
-7
@@ -10,7 +10,12 @@ import { QrisPaymentStep } from "./steps/qris-payement"
|
|||||||
import { VAPaymentStep } from "./steps/va-payment"
|
import { VAPaymentStep } from "./steps/va-payment"
|
||||||
import { SuccessStep } from "./steps/success"
|
import { SuccessStep } from "./steps/success"
|
||||||
import { PaymentStep } from "./steps/payment"
|
import { PaymentStep } from "./steps/payment"
|
||||||
import { TBookSessionRequest, usePostBookSession } from "@imphnen-frontend-service/service"
|
import {
|
||||||
|
TBookSessionRequest,
|
||||||
|
TPayment,
|
||||||
|
usePostBookSession,
|
||||||
|
usePostCreatePayment,
|
||||||
|
} from "@imphnen-frontend-service/service"
|
||||||
|
|
||||||
const STEPS = ['topic', 'schedule', 'profile', 'payment', 'qr-payment', 'va-payment', 'success'] as const
|
const STEPS = ['topic', 'schedule', 'profile', 'payment', 'qr-payment', 'va-payment', 'success'] as const
|
||||||
type Step = typeof STEPS[number]
|
type Step = typeof STEPS[number]
|
||||||
@@ -19,15 +24,24 @@ type Props = {
|
|||||||
open: boolean
|
open: boolean
|
||||||
setOpen: (open: boolean) => void
|
setOpen: (open: boolean) => void
|
||||||
mentorId?: string
|
mentorId?: string
|
||||||
mentor?: { fullname?: string | null; current_role?: string; current_company?: string }
|
mentor?: {
|
||||||
|
fullname?: string | null
|
||||||
|
current_role?: string
|
||||||
|
current_company?: string
|
||||||
|
mentoring_rate?: number
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AppointmentModal: FC<Props> = ({ open, setOpen, mentorId, mentor }) => {
|
export const AppointmentModal: FC<Props> = ({ open, setOpen, mentorId, mentor }) => {
|
||||||
const [step, setStep] = useState<Step>('topic')
|
const [step, setStep] = useState<Step>('topic')
|
||||||
const [selectedTopics, setSelectedTopics] = useState<number[]>([])
|
const [selectedTopics, setSelectedTopics] = useState<number[]>([])
|
||||||
const [booking, setBooking] = useState<TBookSessionRequest | null>(null)
|
const [booking, setBooking] = useState<TBookSessionRequest | null>(null)
|
||||||
|
const [payment, setPayment] = useState<TPayment | null>(null)
|
||||||
|
const [paymentMethod, setPaymentMethod] = useState<'va' | 'qris'>('va')
|
||||||
const [error, setError] = useState("")
|
const [error, setError] = useState("")
|
||||||
|
const [sessionId, setSessionId] = useState("")
|
||||||
const bookMutation = usePostBookSession(mentorId ?? "")
|
const bookMutation = usePostBookSession(mentorId ?? "")
|
||||||
|
const paymentMutation = usePostCreatePayment(sessionId)
|
||||||
|
|
||||||
const handleStep = async (action: 'next' | 'prev') => {
|
const handleStep = async (action: 'next' | 'prev') => {
|
||||||
setError("")
|
setError("")
|
||||||
@@ -37,8 +51,19 @@ export const AppointmentModal: FC<Props> = ({ open, setOpen, mentorId, mentor })
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await bookMutation.mutateAsync({ ...booking, topic: booking.topic || `Mentoring #${selectedTopics[0] ?? 1}` })
|
// 1. Book the session -> get session id
|
||||||
setStep('success')
|
const booked = await bookMutation.mutateAsync({ ...booking, topic: booking.topic || `Mentoring #${selectedTopics[0] ?? 1}` })
|
||||||
|
const sid = (booked as unknown as { data?: { id?: string } })?.data?.id ?? ""
|
||||||
|
if (!sid) {
|
||||||
|
setError("Gagal membuat sesi mentoring. Coba lagi.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setSessionId(sid)
|
||||||
|
// 2. Create payment for the session with the chosen method
|
||||||
|
const pm = await paymentMutation.mutateAsync({ method: paymentMethod })
|
||||||
|
setPayment(pm)
|
||||||
|
// 3. Route to the method-specific payment screen
|
||||||
|
setStep(paymentMethod === 'qris' ? 'qr-payment' : 'va-payment')
|
||||||
} catch {
|
} catch {
|
||||||
setError("Gagal membuat sesi mentoring. Coba lagi.")
|
setError("Gagal membuat sesi mentoring. Coba lagi.")
|
||||||
}
|
}
|
||||||
@@ -46,6 +71,8 @@ export const AppointmentModal: FC<Props> = ({ open, setOpen, mentorId, mentor })
|
|||||||
}
|
}
|
||||||
if (action === 'next' && step === 'success') {
|
if (action === 'next' && step === 'success') {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
} else if (action === 'next' && (step === 'qr-payment' || step === 'va-payment')) {
|
||||||
|
setStep('success')
|
||||||
} else if (action === 'next') {
|
} else if (action === 'next') {
|
||||||
setStep(STEPS[STEPS.indexOf(step) + 1])
|
setStep(STEPS[STEPS.indexOf(step) + 1])
|
||||||
} else if (action === 'prev' && step !== 'topic') {
|
} else if (action === 'prev' && step !== 'topic') {
|
||||||
@@ -135,9 +162,9 @@ export const AppointmentModal: FC<Props> = ({ open, setOpen, mentorId, mentor })
|
|||||||
{step === 'topic' && <TopicStep selectedTopics={selectedTopics} setSelectedTopics={setSelectedTopics} />}
|
{step === 'topic' && <TopicStep selectedTopics={selectedTopics} setSelectedTopics={setSelectedTopics} />}
|
||||||
{step === 'schedule' && <ScheduleStep onChange={(data) => setBooking(data)} />}
|
{step === 'schedule' && <ScheduleStep onChange={(data) => setBooking(data)} />}
|
||||||
{step === 'profile' && <ProfileStep />}
|
{step === 'profile' && <ProfileStep />}
|
||||||
{step === 'payment' && <PaymentStep selectedTopics={selectedTopics} mentor={mentor} booking={booking} />}
|
{step === 'payment' && <PaymentStep selectedTopics={selectedTopics} mentor={mentor} booking={booking} onMethodChange={setPaymentMethod} />}
|
||||||
{step === 'qr-payment' && <QrisPaymentStep />}
|
{step === 'qr-payment' && <QrisPaymentStep payment={payment} />}
|
||||||
{step === 'va-payment' && <VAPaymentStep />}
|
{step === 'va-payment' && <VAPaymentStep payment={payment} />}
|
||||||
{step === 'success' && <SuccessStep />}
|
{step === 'success' && <SuccessStep />}
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
|
|
||||||
|
|||||||
+28
-12
@@ -1,18 +1,32 @@
|
|||||||
import { For, Show } from "@imphnen-frontend-service/utils"
|
import { For, Show } from "@imphnen-frontend-service/utils"
|
||||||
import { FC } from "react"
|
import { FC, useState } from "react"
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
import { TOPICS } from "../../../sections/topics"
|
import { TOPICS } from "../../../sections/topics"
|
||||||
import { TBookSessionRequest } from "@imphnen-frontend-service/service"
|
import { TBookSessionRequest } from "@imphnen-frontend-service/service"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selectedTopics: number[]
|
selectedTopics: number[]
|
||||||
mentor?: { fullname?: string | null; current_role?: string; current_company?: string } | null
|
mentor?: {
|
||||||
|
fullname?: string | null;
|
||||||
|
current_role?: string;
|
||||||
|
current_company?: string;
|
||||||
|
mentoring_rate?: number;
|
||||||
|
} | null
|
||||||
booking?: TBookSessionRequest | null
|
booking?: TBookSessionRequest | null
|
||||||
|
onMethodChange: (method: 'va' | 'qris') => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PaymentStep: FC<Props> = ({ selectedTopics, mentor, booking }) => {
|
const BANK_OPTIONS = ['BCA', 'BRI', 'BNI', 'MANDIRI']
|
||||||
const rate = 50000
|
|
||||||
|
export const PaymentStep: FC<Props> = ({ selectedTopics, mentor, booking, onMethodChange }) => {
|
||||||
|
const rate = mentor?.mentoring_rate ?? 50000
|
||||||
const serviceFee = 2000
|
const serviceFee = 2000
|
||||||
|
const [method, setMethod] = useState<'va' | 'qris'>('va')
|
||||||
|
|
||||||
|
const handleMethod = (next: 'va' | 'qris') => {
|
||||||
|
setMethod(next)
|
||||||
|
onMethodChange(next)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -76,15 +90,16 @@ export const PaymentStep: FC<Props> = ({ selectedTopics, mentor, booking }) => {
|
|||||||
<p className="text-[8px] text-neutral-400 mb-2 md:text-[10px]">
|
<p className="text-[8px] text-neutral-400 mb-2 md:text-[10px]">
|
||||||
Virtual Account
|
Virtual Account
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-3 gap-2 md:grid-cols-4">
|
<div className="grid grid-cols-4 gap-2">
|
||||||
<For data={['BCA', 'BRI', 'BNI', 'MANDIRI', 'BCA-Virtual', 'BNI-Virtual', 'MANDIRI-Virtual']}>
|
<For data={BANK_OPTIONS}>
|
||||||
{(bank, index) => (
|
{(bank, index) => (
|
||||||
<div
|
<div
|
||||||
key={index}
|
key={index}
|
||||||
className="p-1 bg-white rounded-xs border border-primary-50 flex items-center gap-x-1"
|
className="p-1 bg-white rounded-xs border border-primary-50 flex items-center gap-x-1 cursor-pointer"
|
||||||
|
onClick={() => handleMethod('va')}
|
||||||
>
|
>
|
||||||
<input type="radio" name="payment" id={bank} className="size-2" />
|
<input type="radio" name="payment" id={`va-${bank}`} checked={method === 'va'} readOnly className="size-2" />
|
||||||
<label htmlFor={bank} className="block">
|
<label htmlFor={`va-${bank}`} className="block">
|
||||||
<img src="/image/payment/bca.webp" alt={bank} className="object-scale-down" />
|
<img src="/image/payment/bca.webp" alt={bank} className="object-scale-down" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,11 +111,12 @@ export const PaymentStep: FC<Props> = ({ selectedTopics, mentor, booking }) => {
|
|||||||
<p className="text-[8px] text-neutral-400 mb-2 md:text-[10px]">
|
<p className="text-[8px] text-neutral-400 mb-2 md:text-[10px]">
|
||||||
QRIS
|
QRIS
|
||||||
</p>
|
</p>
|
||||||
<div className="grid grid-cols-3 gap-2 md:grid-cols-4">
|
<div className="grid grid-cols-4 gap-2">
|
||||||
<div
|
<div
|
||||||
className="p-1 bg-white rounded-xs border border-primary-50 flex items-center gap-x-1"
|
className="p-1 bg-white rounded-xs border border-primary-50 flex items-center gap-x-1 cursor-pointer"
|
||||||
|
onClick={() => handleMethod('qris')}
|
||||||
>
|
>
|
||||||
<input type="radio" name="payment" id="QRIS" className="size-2" />
|
<input type="radio" name="payment" id="QRIS" checked={method === 'qris'} readOnly className="size-2" />
|
||||||
<label htmlFor="QRIS" className="block">
|
<label htmlFor="QRIS" className="block">
|
||||||
<img src="/image/payment/qris.webp" alt="QRIS" className="object-scale-down" />
|
<img src="/image/payment/qris.webp" alt="QRIS" className="object-scale-down" />
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
+20
-4
@@ -1,5 +1,7 @@
|
|||||||
import { For } from "@imphnen-frontend-service/utils"
|
import { For, Show } from "@imphnen-frontend-service/utils"
|
||||||
|
import { FC } from "react"
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
|
import { TPayment } from "@imphnen-frontend-service/service"
|
||||||
|
|
||||||
const PAYMENT_STEP = [
|
const PAYMENT_STEP = [
|
||||||
'Buka aplikasi e-wallet atau m-banking kamu',
|
'Buka aplikasi e-wallet atau m-banking kamu',
|
||||||
@@ -8,7 +10,11 @@ const PAYMENT_STEP = [
|
|||||||
'Konfimasi pembayaran, dan proses selesai.'
|
'Konfimasi pembayaran, dan proses selesai.'
|
||||||
]
|
]
|
||||||
|
|
||||||
export const QrisPaymentStep = () => {
|
type Props = {
|
||||||
|
payment?: TPayment | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const QrisPaymentStep: FC<Props> = ({ payment }) => {
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="bg-white px-6 py-5 rounded-md md:flex md:justify-between md:gap-8"
|
className="bg-white px-6 py-5 rounded-md md:flex md:justify-between md:gap-8"
|
||||||
@@ -38,7 +44,14 @@ export const QrisPaymentStep = () => {
|
|||||||
<p className="text-[10px] text-neutral-400 mb-1.5 font-medium md:text-xs">
|
<p className="text-[10px] text-neutral-400 mb-1.5 font-medium md:text-xs">
|
||||||
Biaya yang harus dibayarkan
|
Biaya yang harus dibayarkan
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs font-semibold text-neutral-700 md:text-[15px]">Rp. 52.000</p>
|
<p className="text-xs font-semibold text-neutral-700 md:text-[15px]">
|
||||||
|
Rp. {(payment?.total ?? 52000).toLocaleString("id-ID")}
|
||||||
|
</p>
|
||||||
|
<Show condition={!!payment?.external_ref}>
|
||||||
|
<p className="text-[10px] text-neutral-400 mt-1 font-medium">
|
||||||
|
Ref: {payment?.external_ref}
|
||||||
|
</p>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -49,7 +62,10 @@ export const QrisPaymentStep = () => {
|
|||||||
<div className="bg-primary-50 p-2.5 rounded-lg size-[120px] mx-auto md:size-[142px] md:me-0">
|
<div className="bg-primary-50 p-2.5 rounded-lg size-[120px] mx-auto md:size-[142px] md:me-0">
|
||||||
<img src="/image/sample-qrcode.webp" alt="QR Code" className="w-full" />
|
<img src="/image/sample-qrcode.webp" alt="QR Code" className="w-full" />
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-[8px] text-neutral-500 text-center mt-2 md:text-[10px]">
|
||||||
|
Berlaku hingga {payment ? new Date(payment.expires_at).toLocaleString("id-ID") : "-"}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+26
-6
@@ -1,5 +1,7 @@
|
|||||||
import { For } from "@imphnen-frontend-service/utils"
|
import { For, Show } from "@imphnen-frontend-service/utils"
|
||||||
|
import { FC } from "react"
|
||||||
import { motion } from "framer-motion"
|
import { motion } from "framer-motion"
|
||||||
|
import { TPayment } from "@imphnen-frontend-service/service"
|
||||||
|
|
||||||
const PAYMENT_STEP = [
|
const PAYMENT_STEP = [
|
||||||
'Buka aplikasi e-wallet atau m-banking kamu',
|
'Buka aplikasi e-wallet atau m-banking kamu',
|
||||||
@@ -8,7 +10,11 @@ const PAYMENT_STEP = [
|
|||||||
'Konfimasi pembayaran, dan proses selesai.'
|
'Konfimasi pembayaran, dan proses selesai.'
|
||||||
]
|
]
|
||||||
|
|
||||||
export const VAPaymentStep = () => {
|
type Props = {
|
||||||
|
payment?: TPayment | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const VAPaymentStep: FC<Props> = ({ payment }) => {
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
className="bg-white px-6 py-5 rounded-md md:flex md:items-center md:gap-11"
|
className="bg-white px-6 py-5 rounded-md md:flex md:items-center md:gap-11"
|
||||||
@@ -24,7 +30,7 @@ export const VAPaymentStep = () => {
|
|||||||
<p className="text-[10px] text-neutral-400 mb-1.5">
|
<p className="text-[10px] text-neutral-400 mb-1.5">
|
||||||
Cara melakukan pembayaran
|
Cara melakukan pembayaran
|
||||||
</p>
|
</p>
|
||||||
<ul className="list-decimal pl-2.5">
|
<ul className="list-decimal pl-2.5 mb-4 md:mb-7">
|
||||||
<For data={PAYMENT_STEP}>
|
<For data={PAYMENT_STEP}>
|
||||||
{(step, index) => (
|
{(step, index) => (
|
||||||
<li key={index} className="text-[10px] text-neutral-400 leading-tight font-medium">
|
<li key={index} className="text-[10px] text-neutral-400 leading-tight font-medium">
|
||||||
@@ -33,6 +39,15 @@ export const VAPaymentStep = () => {
|
|||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div className="text-center md:text-start">
|
||||||
|
<p className="text-[10px] text-neutral-400 mb-1.5 font-medium md:text-xs">
|
||||||
|
Biaya yang harus dibayarkan
|
||||||
|
</p>
|
||||||
|
<p className="text-xs font-semibold text-neutral-700 md:text-[15px]">
|
||||||
|
Rp. {(payment?.total ?? 52000).toLocaleString("id-ID")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center md:text-start">
|
<div className="text-center md:text-start">
|
||||||
@@ -44,12 +59,17 @@ export const VAPaymentStep = () => {
|
|||||||
Kode Virtual Account
|
Kode Virtual Account
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs font-semibold text-neutral-700 mb-1.5 md:text-[15px]">
|
<p className="text-xs font-semibold text-neutral-700 mb-1.5 md:text-[15px]">
|
||||||
8091239861969812
|
{payment?.external_ref || "8091239861969812"}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-[8px] text-neutral-400 md:text-[10px]">
|
<p className="text-[8px] text-neutral-400 md:text-[10px]">
|
||||||
A/N Unknown
|
A/N IMPHNEN
|
||||||
</p>
|
</p>
|
||||||
|
<Show condition={!!payment?.expires_at}>
|
||||||
|
<p className="text-[8px] text-neutral-500 mt-2 md:text-[10px]">
|
||||||
|
Berlaku hingga {new Date(payment!.expires_at).toLocaleString("id-ID")}
|
||||||
|
</p>
|
||||||
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -3,14 +3,16 @@ import {
|
|||||||
TArticleDetail,
|
TArticleDetail,
|
||||||
TArticleListItem,
|
TArticleListItem,
|
||||||
TArticleListParams,
|
TArticleListParams,
|
||||||
|
TBookSessionRequest,
|
||||||
|
TCreatePaymentRequest,
|
||||||
TMentorAvailability,
|
TMentorAvailability,
|
||||||
TMentorDetail,
|
TMentorDetail,
|
||||||
TMentorListParams,
|
TMentorListParams,
|
||||||
TMentorRegisterRequest,
|
TMentorRegisterRequest,
|
||||||
TMentorStats,
|
TMentorStats,
|
||||||
|
TPayment,
|
||||||
TSessionFeedbackRequest,
|
TSessionFeedbackRequest,
|
||||||
TSessionListResponse,
|
TSessionListResponse,
|
||||||
TBookSessionRequest,
|
|
||||||
} from '../../types/dimentorin';
|
} from '../../types/dimentorin';
|
||||||
import { TResponseMessage } from '../../types/common';
|
import { TResponseMessage } from '../../types/common';
|
||||||
|
|
||||||
@@ -154,3 +156,41 @@ export const postRegisterMentor = async (
|
|||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const postCreatePayment = async (
|
||||||
|
sessionId: string,
|
||||||
|
payload: TCreatePaymentRequest
|
||||||
|
): Promise<TPayment> => {
|
||||||
|
const { data } = await api({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/dimentorin/payments/sessions/${sessionId}/create`,
|
||||||
|
data: payload,
|
||||||
|
});
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMyPayments = async (): Promise<TPayment[]> => {
|
||||||
|
const { data } = await api({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/dimentorin/payments/me',
|
||||||
|
});
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getPaymentById = async (id: string): Promise<TPayment> => {
|
||||||
|
const { data } = await api({
|
||||||
|
method: 'GET',
|
||||||
|
url: `/dimentorin/payments/${id}`,
|
||||||
|
});
|
||||||
|
return data.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const postConfirmPayment = async (
|
||||||
|
id: string
|
||||||
|
): Promise<TResponseMessage> => {
|
||||||
|
const { data } = await api({
|
||||||
|
method: 'POST',
|
||||||
|
url: `/dimentorin/payments/${id}/confirm`,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|||||||
@@ -11,8 +11,12 @@ import {
|
|||||||
getMentorSessions,
|
getMentorSessions,
|
||||||
getMentorStats,
|
getMentorStats,
|
||||||
getMentors,
|
getMentors,
|
||||||
|
getMyPayments,
|
||||||
getMySessions,
|
getMySessions,
|
||||||
|
getPaymentById,
|
||||||
postBookSession,
|
postBookSession,
|
||||||
|
postConfirmPayment,
|
||||||
|
postCreatePayment,
|
||||||
postRegisterMentor,
|
postRegisterMentor,
|
||||||
postSessionFeedback,
|
postSessionFeedback,
|
||||||
} from '../../api/dimentorin';
|
} from '../../api/dimentorin';
|
||||||
@@ -21,11 +25,13 @@ import {
|
|||||||
TArticleListItem,
|
TArticleListItem,
|
||||||
TArticleListParams,
|
TArticleListParams,
|
||||||
TBookSessionRequest,
|
TBookSessionRequest,
|
||||||
|
TCreatePaymentRequest,
|
||||||
TMentorAvailability,
|
TMentorAvailability,
|
||||||
TMentorDetail,
|
TMentorDetail,
|
||||||
TMentorListParams,
|
TMentorListParams,
|
||||||
TMentorRegisterRequest,
|
TMentorRegisterRequest,
|
||||||
TMentorStats,
|
TMentorStats,
|
||||||
|
TPayment,
|
||||||
TSessionFeedbackRequest,
|
TSessionFeedbackRequest,
|
||||||
TSessionListResponse,
|
TSessionListResponse,
|
||||||
} from '../../types/dimentorin';
|
} from '../../types/dimentorin';
|
||||||
@@ -134,6 +140,41 @@ export const usePostRegisterMentor = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const usePostCreatePayment = (sessionId: string) => {
|
||||||
|
return useMutation({
|
||||||
|
mutationKey: ['post-create-payment', sessionId],
|
||||||
|
mutationFn: async (payload: TCreatePaymentRequest) =>
|
||||||
|
await postCreatePayment(sessionId, payload),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetMyPayments = (): UseQueryResult<
|
||||||
|
TPayment[],
|
||||||
|
TResponseError
|
||||||
|
> => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['get-my-payments'],
|
||||||
|
queryFn: async () => await getMyPayments(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useGetPaymentById = (
|
||||||
|
id: string
|
||||||
|
): UseQueryResult<TPayment, TResponseError> => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ['get-payment-by-id', id],
|
||||||
|
queryFn: async () => await getPaymentById(id),
|
||||||
|
enabled: !!id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const usePostConfirmPayment = () => {
|
||||||
|
return useMutation({
|
||||||
|
mutationKey: ['post-confirm-payment'],
|
||||||
|
mutationFn: async (id: string) => await postConfirmPayment(id),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetArticles = (
|
export const useGetArticles = (
|
||||||
params?: TArticleListParams
|
params?: TArticleListParams
|
||||||
): UseQueryResult<TArticleListItem[], TResponseError> => {
|
): UseQueryResult<TArticleListItem[], TResponseError> => {
|
||||||
|
|||||||
@@ -162,3 +162,22 @@ export type TMentorRegisterRequest = {
|
|||||||
mentoring_rate_amount: number;
|
mentoring_rate_amount: number;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TPayment = {
|
||||||
|
id: string;
|
||||||
|
session_id: string;
|
||||||
|
mentor_id: string;
|
||||||
|
amount: number;
|
||||||
|
service_fee: number;
|
||||||
|
total: number;
|
||||||
|
method: string;
|
||||||
|
provider: string;
|
||||||
|
status: string;
|
||||||
|
external_ref?: string | null;
|
||||||
|
expires_at: string;
|
||||||
|
created_at: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TCreatePaymentRequest = {
|
||||||
|
method: string; // 'va' | 'qris' | 'manual'
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user