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 // components dizisinin varlığını kontrol et
if (loading || !components || !Array.isArray(components)) { 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 // Belirtilen bileşeni bul

View file

@ -190,7 +190,14 @@ const DynamicRenderer: React.FC<DynamicRendererProps> = ({
} }
}, [componentName, externalDeps, components, getComponentByName]) }, [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 ( return (
<ErrorBoundary key={componentName}> <ErrorBoundary key={componentName}>

View file

@ -13,7 +13,7 @@ import {
FaPuzzlePiece, FaPuzzlePiece,
FaCheckCircle, FaCheckCircle,
FaTimesCircle, FaTimesCircle,
} from 'react-icons/fa'; } from 'react-icons/fa'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
@ -155,8 +155,10 @@ const ComponentManager: React.FC = () => {
{/* Components List */} {/* Components List */}
{loading ? ( {loading ? (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center min-h-screen bg-gray-50">
<div className="text-slate-600">Bileşenler yükleniyor...</div> <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> </div>
) : filteredComponents?.length > 0 ? ( ) : filteredComponents?.length > 0 ? (
<div className="grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6"> <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 React, { useState } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { ROUTES_ENUM } from '@/routes/route.constant'
interface TenantFormProps { interface TenantFormProps {
onSubmit: (tenant: CustomTenantDto) => void onSubmit: (tenant: CustomTenantDto) => void
@ -279,7 +280,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
</div> </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"> <div className="relative">
<FaUser className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaUser className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <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 className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <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"> <div className="relative">
<FaPhone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaPhone className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -310,7 +315,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
</div> </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"> <div className="relative">
<FaEnvelope className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaEnvelope className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -326,7 +333,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
<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"> <div className="relative">
<FaMapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" /> <FaMapPin className="absolute left-3 top-3 text-gray-400 w-5 h-5" />
<textarea <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 className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <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"> <div className="relative">
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -355,7 +366,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
</div> </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"> <div className="relative">
<FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaGlobe className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <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 className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <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"> <div className="relative">
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -386,7 +401,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
</div> </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"> <div className="relative">
<FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaMapPin className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <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 className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div> <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"> <div className="relative">
<FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaBuilding className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -417,7 +436,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
</div> </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"> <div className="relative">
<FaDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaDollarSign className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -433,7 +454,9 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
</div> </div>
<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"> <div className="relative">
<FaUserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" /> <FaUserPlus className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
<input <input
@ -451,7 +474,7 @@ export const TenantForm: React.FC<TenantFormProps> = ({ onSubmit }) => {
<div className="flex justify-between items-center mt-6"> <div className="flex justify-between items-center mt-6">
<button <button
type="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" 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" /> <FaArrowLeft className="w-4 h-4 mr-2" />

View file

@ -1,33 +1,27 @@
import { Product } from '@/proxy/order/models'; import { Product } from '@/proxy/order/models'
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react'
export const useOrders = () => { export const useOrders = () => {
const [products, setProducts] = useState<Product[]>([]); const [products, setProducts] = useState<Product[]>([])
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
fetchProducts(); fetchProducts()
}, []); }, [])
const fetchProducts = async () => { const fetchProducts = async () => {
try { try {
setLoading(true); setLoading(true)
setProducts(products)
// Using static data instead of API call setError(null)
// You can replace this with API call if needed:
// const response = await api.get('/products');
// const products: Product[] = response.data;
setProducts(products);
setError(null);
} catch (err) { } catch (err) {
console.error('Products fetch error:', err); console.error('Products fetch error:', err)
setError('Ürünler yüklenirken hata oluştu'); setError('Ürünler yüklenirken hata oluştu')
} finally { } 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 { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
@ -58,7 +58,7 @@ const FormEdit = (
} }
return ( return (
<> <Container>
{!isSubForm && ( {!isSubForm && (
<Helmet <Helmet
titleTemplate="%s | Kurs Platform" titleTemplate="%s | Kurs Platform"
@ -96,7 +96,7 @@ const FormEdit = (
/> />
<hr className="my-4" /> <hr className="my-4" />
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} /> <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 { useLocalization } from '@/utils/hooks/useLocalization'
import { DataType } from 'devextreme/common' import { DataType } from 'devextreme/common'
import { SimpleItem } from 'devextreme/ui/form' import { SimpleItem } from 'devextreme/ui/form'
@ -144,7 +144,7 @@ const FormNew = (
} }
return ( return (
<> <Container>
{!isSubForm && ( {!isSubForm && (
<Helmet <Helmet
titleTemplate="%s | Kurs Platform" titleTemplate="%s | Kurs Platform"
@ -181,7 +181,7 @@ const FormNew = (
formItems={formItems} formItems={formItems}
setFormData={setFormData} 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 { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
@ -53,7 +53,7 @@ const FormView = (
} }
return ( return (
<> <Container>
{!isSubForm && ( {!isSubForm && (
<Helmet <Helmet
titleTemplate="%s | Kurs Platform" titleTemplate="%s | Kurs Platform"
@ -91,7 +91,7 @@ const FormView = (
/> />
<hr className="my-4" /> <hr className="my-4" />
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} refreshData={fetchData} /> <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) => { const handleTenantSubmit = (tenantData: CustomTenantDto) => {
localStorage.setItem('tenantData', JSON.stringify(tenantData)) localStorage.setItem('tenantData', JSON.stringify(tenantData))
navigate('/payment') navigate(ROUTES_ENUM.public.payment)
} }
const handleBackToCatalog = () => { const handleBackToCatalog = () => {
navigate(ROUTES_ENUM.public.home) navigate(ROUTES_ENUM.public.home)
} }
const handleCheckout = () => { const handleCheckout = () => {
setIsCartOpen(false) setIsCartOpen(false)
navigate(ROUTES_ENUM.public.checkout) navigate(ROUTES_ENUM.public.checkout)

View file

@ -2,6 +2,7 @@ import { Cart } from '@/components/orders/Cart'
import { PaymentForm } from '@/components/orders/PaymentForm' import { PaymentForm } from '@/components/orders/PaymentForm'
import { CustomTenantDto } from '@/proxy/config/models' import { CustomTenantDto } from '@/proxy/config/models'
import { OrderDto } from '@/proxy/order/models' import { OrderDto } from '@/proxy/order/models'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { OrderService } from '@/services/order.service' import { OrderService } from '@/services/order.service'
import { import {
CartState, CartState,
@ -29,7 +30,7 @@ const Payment: React.FC = () => {
if (tenantData) { if (tenantData) {
setTenant(JSON.parse(tenantData)) setTenant(JSON.parse(tenantData))
} else { } else {
navigate('/checkout') navigate(ROUTES_ENUM.public.checkout)
} }
if (savedCartState) { if (savedCartState) {
@ -44,7 +45,7 @@ const Payment: React.FC = () => {
const handleCheckout = () => { const handleCheckout = () => {
setIsCartOpen(false) setIsCartOpen(false)
navigate('/checkout') navigate(ROUTES_ENUM.public.checkout)
} }
const handleUpdateQuantity = (id: string, quantity: number) => { const handleUpdateQuantity = (id: string, quantity: number) => {
@ -92,7 +93,7 @@ const Payment: React.FC = () => {
setCartState(clearCart()) setCartState(clearCart())
localStorage.removeItem('tenantData') // ✅ temizlik localStorage.removeItem('tenantData') // ✅ temizlik
localStorage.removeItem('cartState') // ✅ temizlik localStorage.removeItem('cartState') // ✅ temizlik
navigate('/success') navigate(ROUTES_ENUM.public.success)
} else { } else {
alert('Sipariş oluşturulurken hata oluştu: ' + result.error) alert('Sipariş oluşturulurken hata oluştu: ' + result.error)
} }
@ -103,11 +104,17 @@ const Payment: React.FC = () => {
} }
const handleBackToTenant = () => { const handleBackToTenant = () => {
navigate('/checkout') navigate(ROUTES_ENUM.public.checkout)
} }
if (!tenant) { 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 ( return (

View file

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

View file

@ -27,7 +27,13 @@ const Success: React.FC = () => {
} }
if (!orderId) { 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 ( return (