sina_sajjadi
3 weeks ago
12 changed files with 304 additions and 253 deletions
-
1public/locales/en/common.json
-
133src/components/auth/registration-form.tsx
-
1src/components/shop/shop-form.tsx
-
6src/components/ui/logo.tsx
-
3src/data/client/api-endpoints.ts
-
62src/data/subscription.ts
-
38src/data/user.ts
-
5src/pages/shop/create.tsx
-
4src/pages/subscriptions/active-section.tsx
-
69src/pages/subscriptions/modal.tsx
-
230src/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 = () => { |
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 = () => { |
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 = () => { |
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