Public sayfalardaki Loading

This commit is contained in:
Sedat ÖZTÜRK 2025-08-21 15:26:25 +03:00
parent aa1b17935d
commit 53e0420116
12 changed files with 102 additions and 58 deletions

View file

@ -16,7 +16,13 @@ const ComponentPreview: React.FC<ComponentPreviewProps> = ({ componentName, clas
// components dizisinin varlığını kontrol et
if (loading || !components || !Array.isArray(components)) {
return <div className="text-sm text-gray-500">Bileşenler yükleniyor...</div>
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<div className="w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto"></div>
</div>
</div>
)
}
// Belirtilen bileşeni bul

View file

@ -80,7 +80,7 @@ const DynamicRenderer: React.FC<DynamicRendererProps> = ({
const Timeline = React.lazy(() => import('../ui/Timeline'))
const Tooltip = React.lazy(() => import('../ui/Tooltip'))
const Upload = React.lazy(() => import('../ui/Upload'))
const [Component, setComponent] = useState<React.ComponentType<any> | null>(null)
const { getComponentByName, components } = useComponents()
@ -190,7 +190,14 @@ const DynamicRenderer: React.FC<DynamicRendererProps> = ({
}
}, [componentName, externalDeps, components, getComponentByName])
if (!Component) return <div>Yükleniyor...</div>
if (!Component)
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<div className="w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto"></div>
</div>
</div>
)
return (
<ErrorBoundary key={componentName}>

View file

@ -13,7 +13,7 @@ import {
FaPuzzlePiece,
FaCheckCircle,
FaTimesCircle,
} from 'react-icons/fa';
} from 'react-icons/fa'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { useLocalization } from '@/utils/hooks/useLocalization'
@ -155,8 +155,10 @@ const ComponentManager: React.FC = () => {
{/* Components List */}
{loading ? (
<div className="flex items-center justify-center py-12">
<div className="text-slate-600">Bileşenler yükleniyor...</div>
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<div className="w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto"></div>
</div>
</div>
) : filteredComponents?.length > 0 ? (
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6">

View file

@ -18,6 +18,7 @@ import {
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ROUTES_ENUM } from '@/routes/route.constant'
interface TenantFormProps {
onSubmit: (tenant: CustomTenantDto) => void
@ -279,7 +280,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.founder')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.founder')}
</label>
<div className="relative">
<FaUser className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -296,7 +299,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.phone')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.phone')}
</label>
<div className="relative">
<FaPhone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -310,7 +315,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.email')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.email')}
</label>
<div className="relative">
<FaEnvelope className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -326,7 +333,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.address')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.address')}
</label>
<div className="relative">
<FaMapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" />
<textarea
@ -342,7 +351,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.country')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.country')}
</label>
<div className="relative">
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -355,7 +366,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.city')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.city')}
</label>
<div className="relative">
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -372,7 +385,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.district')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.district')}
</label>
<div className="relative">
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -386,7 +401,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.postalCode')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.postalCode')}
</label>
<div className="relative">
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -403,7 +420,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.taxOffice')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.taxOffice')}
</label>
<div className="relative">
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -417,7 +436,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.taxNumber')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.taxNumber')}
</label>
<div className="relative">
<FaDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -433,7 +454,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div>
<div>
<label className="text-sm font-medium text-gray-700">{translate('::Public.products.tenantForm.reference')}</label>
<label className="text-sm font-medium text-gray-700">
{translate('::Public.products.tenantForm.reference')}
</label>
<div className="relative">
<FaUserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
@ -451,7 +474,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="flex justify-between items-center mt-6">
<button
type="button"
onClick={() => navigate('/products')}
onClick={() => navigate(ROUTES_ENUM.public.products)}
className="flex items-center px-6 py-3 border border-gray-300 text-gray-700 rounded-lg"
>
<FaArrowLeft className="w-4 h-4 mr-2" />

View file

@ -1,33 +1,27 @@
import { Product } from '@/proxy/order/models';
import { useState, useEffect } from 'react';
import { Product } from '@/proxy/order/models'
import { useState, useEffect } from 'react'
export const useOrders = () => {
const [products, setProducts] = useState<Product[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [products, setProducts] = useState<Product[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
fetchProducts();
}, []);
fetchProducts()
}, [])
const fetchProducts = async () => {
try {
setLoading(true);
// Using static data instead of API call
// You can replace this with API call if needed:
// const response = await api.get('/products');
// const products: Product[] = response.data;
setProducts(products);
setError(null);
setLoading(true)
setProducts(products)
setError(null)
} catch (err) {
console.error('Products fetch error:', err);
setError('Ürünler yüklenirken hata oluştu');
console.error('Products fetch error:', err)
setError('Ürünler yüklenirken hata oluştu')
} finally {
setLoading(false);
setLoading(false)
}
};
}
return { products, loading, error, refetch: fetchProducts };
};
return { products, loading, error, refetch: fetchProducts }
}

View file

@ -1,4 +1,4 @@
import { Loading } from '@/components/shared'
import { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
import { useParams } from 'react-router-dom'
@ -58,7 +58,7 @@ const FormEdit = (
}
return (
<>
<Container>
{!isSubForm && (
<Helmet
titleTemplate="%s | Kurs Platform"
@ -96,7 +96,7 @@ const FormEdit = (
/>
<hr className="my-4" />
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} />
</>
</Container>
)
}

View file

@ -1,4 +1,4 @@
import { Loading } from '@/components/shared'
import { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { DataType } from 'devextreme/common'
import { SimpleItem } from 'devextreme/ui/form'
@ -144,7 +144,7 @@ const FormNew = (
}
return (
<>
<Container>
{!isSubForm && (
<Helmet
titleTemplate="%s | Kurs Platform"
@ -181,7 +181,7 @@ const FormNew = (
formItems={formItems}
setFormData={setFormData}
/>
</>
</Container>
)
}

View file

@ -1,4 +1,4 @@
import { Loading } from '@/components/shared'
import { Container, Loading } from '@/components/shared'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
import { useParams } from 'react-router-dom'
@ -53,7 +53,7 @@ const FormView = (
}
return (
<>
<Container>
{!isSubForm && (
<Helmet
titleTemplate="%s | Kurs Platform"
@ -91,7 +91,7 @@ const FormView = (
/>
<hr className="my-4" />
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} refreshData={fetchData} />
</>
</Container>
)
}

View file

@ -30,14 +30,13 @@ const Checkout: React.FC = () => {
const handleTenantSubmit = (tenantData: CustomTenantDto) => {
localStorage.setItem('tenantData', JSON.stringify(tenantData))
navigate('/payment')
navigate(ROUTES_ENUM.public.payment)
}
const handleBackToCatalog = () => {
navigate(ROUTES_ENUM.public.home)
}
const handleCheckout = () => {
setIsCartOpen(false)
navigate(ROUTES_ENUM.public.checkout)

View file

@ -2,6 +2,7 @@ import { Cart } from '@/components/orders/Cart'
import { PaymentForm } from '@/components/orders/PaymentForm'
import { CustomTenantDto } from '@/proxy/config/models'
import { OrderDto } from '@/proxy/order/models'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { OrderService } from '@/services/order.service'
import {
CartState,
@ -29,7 +30,7 @@ const Payment: React.FC = () => {
if (tenantData) {
setTenant(JSON.parse(tenantData))
} else {
navigate('/checkout')
navigate(ROUTES_ENUM.public.checkout)
}
if (savedCartState) {
@ -44,7 +45,7 @@ const Payment: React.FC = () => {
const handleCheckout = () => {
setIsCartOpen(false)
navigate('/checkout')
navigate(ROUTES_ENUM.public.checkout)
}
const handleUpdateQuantity = (id: string, quantity: number) => {
@ -92,7 +93,7 @@ const Payment: React.FC = () => {
setCartState(clearCart())
localStorage.removeItem('tenantData') // ✅ temizlik
localStorage.removeItem('cartState') // ✅ temizlik
navigate('/success')
navigate(ROUTES_ENUM.public.success)
} else {
alert('Sipariş oluşturulurken hata oluştu: ' + result.error)
}
@ -103,11 +104,17 @@ const Payment: React.FC = () => {
}
const handleBackToTenant = () => {
navigate('/checkout')
navigate(ROUTES_ENUM.public.checkout)
}
if (!tenant) {
return <div>Yükleniyor...</div>
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<div className="w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto"></div>
</div>
</div>
)
}
return (

View file

@ -50,7 +50,7 @@ const Products: React.FC = () => {
const handleCheckout = () => {
setIsCartOpen(false)
navigate('/checkout')
navigate(ROUTES_ENUM.public.checkout)
}
const handleUpdateQuantity = (id: string, quantity: number) => {

View file

@ -27,7 +27,13 @@ const Success: React.FC = () => {
}
if (!orderId) {
return <div>Yükleniyor...</div>
return (
<div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-center">
<div className="w-12 h-12 border-4 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto"></div>
</div>
</div>
)
}
return (