sina_sajjadi
3 weeks ago
12 changed files with 304 additions and 253 deletions
-
1public/locales/en/common.json
-
119src/components/auth/registration-form.tsx
-
1src/components/shop/shop-form.tsx
-
6src/components/ui/logo.tsx
-
3src/data/client/api-endpoints.ts
-
60src/data/subscription.ts
-
28src/data/user.ts
-
5src/pages/shop/create.tsx
-
4src/pages/subscriptions/active-section.tsx
-
69src/pages/subscriptions/modal.tsx
-
138src/pages/subscriptions/plans-section.tsx
-
5src/settings/site.settings.ts
@ -1,13 +1,61 @@ |
|||
import { useQuery } from "react-query"; |
|||
import { API_ENDPOINTS } from "./client/api-endpoints"; |
|||
import { HttpClient } from "./client/http-client"; |
|||
// hooks/subscriptionHooks.ts
|
|||
import { useQuery, useMutation, QueryKey, UseQueryOptions, UseMutationOptions } from 'react-query'; |
|||
import { API_ENDPOINTS } from './client/api-endpoints'; |
|||
import { HttpClient } from './client/http-client'; |
|||
|
|||
// Define types for your responses and request data
|
|||
interface Subscription { |
|||
id: number; |
|||
duration: string; |
|||
final_price: string; |
|||
discount_percentage: string; |
|||
// ... other subscription fields
|
|||
} |
|||
|
|||
interface PurchaseData { |
|||
subscription_id: number; |
|||
transaction_id: string; |
|||
} |
|||
|
|||
interface PurchaseResponse { |
|||
// Define the structure based on your API response
|
|||
success: boolean; |
|||
message: string; |
|||
// ... other fields
|
|||
} |
|||
|
|||
// Generic GET hook
|
|||
const useApiGet = <T>( |
|||
endpoint: string, |
|||
queryKey?: QueryKey, |
|||
options?: UseQueryOptions<T, Error> |
|||
) => { |
|||
return useQuery<T, Error>( |
|||
queryKey || [endpoint], |
|||
() => HttpClient.get<T>(endpoint), |
|||
options |
|||
); |
|||
}; |
|||
|
|||
// Specific GET hooks
|
|||
export const useGetActiveSubscription = () => { |
|||
return useQuery([API_ENDPOINTS.GET_ACTIVE_SUBSCRIPTION], () => HttpClient.get(API_ENDPOINTS.GET_ACTIVE_SUBSCRIPTION)); |
|||
return useApiGet<Subscription>(API_ENDPOINTS.GET_ACTIVE_SUBSCRIPTION); |
|||
}; |
|||
|
|||
export const useGetAllSubscriptions = () => { |
|||
return useQuery([API_ENDPOINTS.GET_ALL_SUBSCRIPTIONS], () => HttpClient.get(API_ENDPOINTS.GET_ALL_SUBSCRIPTIONS)); |
|||
return useApiGet<Subscription[]>(API_ENDPOINTS.GET_ALL_SUBSCRIPTIONS); |
|||
}; |
|||
|
|||
export const useGetSubscriptionsHistory = () => { |
|||
return useQuery([API_ENDPOINTS.GET_SUBSCRIPTIONS_HISTORY], () => HttpClient.get(API_ENDPOINTS.GET_SUBSCRIPTIONS_HISTORY)); |
|||
return useApiGet<Subscription[]>(API_ENDPOINTS.GET_SUBSCRIPTIONS_HISTORY); |
|||
}; |
|||
|
|||
// Purchase Subscription using useMutation
|
|||
export const usePurchaseSubscription = ( |
|||
options?: UseMutationOptions<PurchaseResponse, Error, PurchaseData> |
|||
) => { |
|||
return useMutation<PurchaseResponse, Error, PurchaseData>( |
|||
(data: PurchaseData) => HttpClient.post<PurchaseResponse>(API_ENDPOINTS.PURCHASE_SUBSCRIPTION, data), |
|||
options |
|||
); |
|||
}; |
@ -1,69 +0,0 @@ |
|||
// components/ui/Modal.tsx
|
|||
|
|||
import React, { useEffect } from 'react'; |
|||
import { FaTimes } from 'react-icons/fa'; |
|||
|
|||
interface ModalProps { |
|||
display: boolean; |
|||
setDisplay: (display: boolean) => void; |
|||
children: React.ReactNode; |
|||
} |
|||
|
|||
const Modal: React.FC<ModalProps> = ({ display, setDisplay, children }) => { |
|||
// Close the modal when the Escape key is pressed
|
|||
useEffect(() => { |
|||
const handleEscape = (event: KeyboardEvent) => { |
|||
if (event.key === 'Escape') { |
|||
setDisplay(false); |
|||
} |
|||
}; |
|||
if (display) { |
|||
document.addEventListener('keydown', handleEscape); |
|||
} else { |
|||
document.removeEventListener('keydown', handleEscape); |
|||
} |
|||
return () => { |
|||
document.removeEventListener('keydown', handleEscape); |
|||
}; |
|||
}, [display, setDisplay]); |
|||
|
|||
// Prevent scrolling when modal is open
|
|||
useEffect(() => { |
|||
if (display) { |
|||
document.body.style.overflow = 'hidden'; |
|||
} else { |
|||
document.body.style.overflow = 'auto'; |
|||
} |
|||
return () => { |
|||
document.body.style.overflow = 'auto'; |
|||
}; |
|||
}, [display]); |
|||
|
|||
if (!display) return null; |
|||
|
|||
return ( |
|||
<div |
|||
className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50" |
|||
onClick={() => setDisplay(false)} // Close when clicking on the backdrop
|
|||
> |
|||
<div |
|||
className="bg-white rounded-lg shadow-lg w-full max-w-lg p-6 relative" |
|||
onClick={(e) => e.stopPropagation()} // Prevent closing when clicking inside the modal
|
|||
> |
|||
{/* Close Button */} |
|||
<button |
|||
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700" |
|||
onClick={() => setDisplay(false)} |
|||
aria-label="Close Modal" |
|||
> |
|||
<FaTimes size={20} /> |
|||
</button> |
|||
|
|||
{/* Modal Content */} |
|||
<div>{children}</div> |
|||
</div> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default Modal; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue