Başlıklar ve Seed

This commit is contained in:
Sedat ÖZTÜRK 2025-08-14 10:10:56 +03:00
parent ce886ee5e1
commit 880329d3ae
37 changed files with 842 additions and 535 deletions

View file

@ -505,6 +505,12 @@
"en": "Abp Settings",
"tr": "Abp Ayarları"
},
{
"resourceName": "Platform",
"key": "App.ChangeLog",
"en": "Change Log",
"tr": "Versiyon Günlüğü"
},
{
"resourceName": "Platform",
"key": "App.BlogManagement",
@ -6343,6 +6349,24 @@
"tr": "Ürünler",
"en": "Products"
},
{
"resourceName": "Platform",
"key": "Public.nav.checkout",
"tr": "Organizasyon Seçimi",
"en": "Select Organization"
},
{
"resourceName": "Platform",
"key": "Public.nav.payment",
"tr": "Ödeme",
"en": "Payment"
},
{
"resourceName": "Platform",
"key": "Public.nav.success",
"tr": "Sipariş Durumu",
"en": "Success"
},
{
"resourceName": "Platform",
"key": "Public.nav.basket",

View file

@ -82,11 +82,12 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.172lu27b4eg"
"revision": "0.6nc9e67jtoo"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
allowlist: [/^\/$/]
allowlist: [/^\/$/],
denylist: [/^\/api\//]
}));
}));

View file

@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Kurs Platform" />
<title>Kurs Platform</title>
<meta name="description" content="Sözsoft" />
<title>Sözsoft</title>
</head>
<body>
<div id="root"></div>

View file

@ -90,7 +90,7 @@ const Simple = ({ children, content, ...rest }: SimpleProps) => {
return (
<div className="h-full">
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-10">
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-6">
<div className="flex justify-between items-center mb-4">
{!hasSubdomain() && (
<a

View file

@ -4,7 +4,7 @@ import { useStoreState } from '@/store'
const HeaderLogo = () => {
const mode = useStoreState((state) => state.theme.mode)
return <Logo mode={mode} className="hidden md:block" />
return <Logo mode={mode} className="hidden md:block" imgClass="w-9/12" />
}
export default HeaderLogo

View file

@ -73,7 +73,10 @@ export const useMenuData = () => {
try {
// Flatten the hierarchy for API
const flatten = (items: MenuItem[], parentCode: string | null = null): MenuItem[] => {
const flatten = (
items: MenuItem[],
parentCode: string | undefined = undefined,
): MenuItem[] => {
const result: MenuItem[] = []
items.forEach((item, index) => {
const flatItem = {

View file

@ -3,6 +3,7 @@ import DoubleSidedImage from '@/components/shared/DoubleSidedImage'
import { Button } from '@/components/ui'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
import { MdArrowBack } from 'react-icons/md'
import { useNavigate } from 'react-router-dom'
@ -15,6 +16,11 @@ const AccessDenied = () => {
return (
<Container className="h-full">
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Access Denied')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="h-full flex flex-col items-center justify-center p-28">
<DoubleSidedImage
src="/img/others/img-2.png"
@ -29,7 +35,9 @@ const AccessDenied = () => {
size="xs"
className="mt-2"
variant="default"
onClick={() => navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)}
onClick={() =>
navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)
}
>
<MdArrowBack />
</Button>

View file

@ -5,13 +5,11 @@ const Dashboard = () => {
const { translate } = useLocalization()
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Home')}
title={translate('::' + 'Dashboard')}
defaultTitle="Kurs Platform"
></Helmet>
</>
)
}

View file

@ -1,5 +1,6 @@
import { ROUTES_ENUM } from '@/routes/route.constant'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
import { useNavigate } from 'react-router-dom'
const NotFoundPage = () => {
@ -11,6 +12,11 @@ const NotFoundPage = () => {
return (
<div className="p-28">
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Not Found')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="flex items-center justify-center font-inter">
<div className="text-[8rem] sm:text-[10rem] md:text-[12rem] font-bold bg-gradient-to-br from-primary to-secondary bg-clip-text animate-pulse">
404
@ -21,7 +27,9 @@ const NotFoundPage = () => {
</p>
<div className="flex items-center justify-center font-inter">
<button
onClick={() => navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)}
onClick={() =>
navigate(isAdminPath ? ROUTES_ENUM.protected.dashboard : ROUTES_ENUM.public.home)
}
className="px-6 py-3 bg-primary rounded-xl shadow hover:bg-secondary transition"
>
{translate('::Public.notFound.button')}

View file

@ -14,6 +14,7 @@ import merge from 'lodash/merge'
import { useEffect, useState } from 'react'
import Log from './components/Log'
import LogFilter from './components/LogFilter'
import { Helmet } from 'react-helmet'
const itemsPerPage = 10
@ -80,6 +81,12 @@ const ActivityLog = () => {
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Identity.ActivityLogs')}
defaultTitle="Kurs Platform"
></Helmet>
<AdaptableCard>
<div className="grid lg:grid-cols-5 gap-8">
<div className="col-span-4">

View file

@ -263,6 +263,12 @@ function ChartEdit() {
return chartValues && roleList && userList && permissionOptions ? (
<div>
<Helmet
titleTemplate="%s | Kurs Platform"
title={chartCode}
defaultTitle="Kurs Platform"
></Helmet>
<Formik
initialValues={{ ...chartValues }}
validationSchema={chartValidationSchema}
@ -284,12 +290,6 @@ function ChartEdit() {
{({ touched, errors, resetForm, isSubmitting, values }) => (
<Form>
<FormContainer size="sm">
<Helmet
titleTemplate="%s | Kurs Platform"
title={chartCode}
defaultTitle="Kurs Platform"
></Helmet>
<div className="lg:flex items-center justify-between mb-4 gap-3">
<div className="mb-4 lg:mb-0">
<h4>

View file

@ -132,7 +132,7 @@ const Wizard = () => {
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Wizard')}
title={translate('::' + 'App.Listforms.Wizard')}
defaultTitle="Kurs Platform"
></Helmet>

View file

@ -3,6 +3,7 @@ import Container from '@/components/shared/Container'
import Tabs from '@/components/ui/Tabs'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Suspense, lazy, useState } from 'react'
import { Helmet } from 'react-helmet'
import { useLocation, useNavigate } from 'react-router-dom'
type AccountSetting = {
@ -66,6 +67,11 @@ const Profile = () => {
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Identity.Profile')}
defaultTitle="Kurs Platform"
></Helmet>
<AdaptableCard>
<Tabs value={currentTab} onChange={(val) => onTabChange(val)}>
<TabList>

View file

@ -7,6 +7,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
import { getAi } from '@/services/ai.service'
import { AiDto } from '@/proxy/ai/models'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
// Types
type ChatType = 'chat' | 'query' | 'analyze'
@ -264,6 +265,12 @@ const Assistant = () => {
// Render
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Identity.Ai')}
defaultTitle="Kurs Platform"
></Helmet>
<LoadAiPostsFromLocalStorage />
<div className="h-[calc(100vh-140px)] flex flex-col">
<div className="flex-1 overflow-y-auto p-4 space-y-4">

View file

@ -11,6 +11,7 @@ import { useLocalization } from '@/utils/hooks/useLocalization'
import useTimeOutMessage from '@/utils/hooks/useTimeOutMessage'
import { Field, Form, Formik } from 'formik'
import { useState } from 'react'
import { Helmet } from 'react-helmet'
import * as Yup from 'yup'
type ExtendLoginFormSchema = {
@ -53,15 +54,27 @@ const ExtendLogin = () => {
return emailSent ? (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('AbpAccount::' + 'Abp.Account.ExtendLogin')}
defaultTitle="Kurs Platform"
></Helmet>
<div>
<h3 className="mb-1">{translate('::Abp.Account.ExtendLogin.Title')}</h3>
<p>{translate('::Abp.Account.ExtendLogin.Description')}</p>
<div className="mt-4 text-center">
<span>{translate('::Abp.Account.Backto')} </span>
<ActionLink to={signInUrl}>{translate('::Abp.Account.SignIn')}</ActionLink>
</div>{' '}
</div>
</>
) : (
<div>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Account.ExtendLogin')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="mb-6">
<h3 className="mb-1">{translate('::Abp.Account.ExtendLogin')}</h3>
</div>

View file

@ -13,6 +13,7 @@ import type { AxiosError } from 'axios'
import { Field, Form, Formik } from 'formik'
import { motion } from 'framer-motion'
import { useState } from 'react'
import { Helmet } from 'react-helmet'
import * as Yup from 'yup'
type ForgotPasswordFormSchema = {
@ -56,6 +57,12 @@ const ForgotPassword = () => {
}
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Account.ForgotPassword')}
defaultTitle="Kurs Platform"
></Helmet>
<motion.div
initial={{ opacity: 0, x: 100 }}
animate={{ opacity: 1, x: 0 }}
@ -124,6 +131,7 @@ const ForgotPassword = () => {
)}
</Formik>
</motion.div>
</>
)
}

View file

@ -21,6 +21,7 @@ import { useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import * as Yup from 'yup'
import { getSubdomain } from '@/utils/subdomain'
import { Helmet } from 'react-helmet'
type SignInFormSchema = {
userName: string
@ -195,6 +196,12 @@ const Login = () => {
: undefined
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('AbpAccount::' + 'Login')}
defaultTitle="Kurs Platform"
></Helmet>
<motion.div
initial={{ opacity: 0, x: 100 }}
animate={{ opacity: 1, x: 0 }}
@ -323,6 +330,7 @@ const Login = () => {
</Formik>
</div>
</motion.div>
</>
)
}

View file

@ -12,6 +12,7 @@ import { Field, Form, Formik } from 'formik'
import { useState } from 'react'
import * as Yup from 'yup'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
type SignUpFormSchema = {
password: string
@ -60,7 +61,13 @@ const Register = () => {
return (
<>
<div className="mb-8">
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('AbpAccount::' + 'Register')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="mb-4">
<h3 className="mb-1">{translate('::Abp.Account.Register.Title')}</h3>
<p>{translate('::Abp.Account.Register.Message')}</p>
</div>

View file

@ -10,6 +10,7 @@ import useTimeOutMessage from '@/utils/hooks/useTimeOutMessage'
import type { AxiosError } from 'axios'
import { Field, Form, Formik } from 'formik'
import { useState } from 'react'
import { Helmet } from 'react-helmet'
import { useNavigate, useSearchParams } from 'react-router-dom'
import * as Yup from 'yup'
@ -77,6 +78,11 @@ const ResetPassword = () => {
return (
<div>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('AbpAccount::' + 'ResetPassword')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="mb-6">
{resetComplete ? (
<>

View file

@ -7,6 +7,7 @@ import { ROUTES_ENUM } from '@/routes/route.constant'
import { store } from '@/store'
import Captcha from '@/components/shared/Captcha'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
type FormSchema = {
email: string
@ -34,6 +35,12 @@ const SendConfirmationCode = () => {
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Account.SendConfirmationCode')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="mb-8">
<h3 className="mb-1">{translate('::Abp.Account.SendConfirmationCode')}</h3>
<p>{translate('::Abp.Account.SendConfirmationCode.Message')}</p>
@ -85,7 +92,9 @@ const SendConfirmationCode = () => {
</Button>
<div className="mt-4 text-center">
<span>{translate('::Abp.Account.Backto')} </span>
<ActionLink to={ROUTES_ENUM.authenticated.login}>{translate('::Abp.Account.SignIn')}</ActionLink>
<ActionLink to={ROUTES_ENUM.authenticated.login}>
{translate('::Abp.Account.SignIn')}
</ActionLink>
</div>
</FormContainer>
</Form>

View file

@ -3,6 +3,7 @@ import { Alert, Button } from '@/components/ui'
import { useNavigate, useParams } from 'react-router-dom'
import useAccount from '@/utils/hooks/useAccount'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
const VerifyConfirmationCode = () => {
const { userId, token } = useParams()
@ -19,6 +20,12 @@ const VerifyConfirmationCode = () => {
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Abp.Account.VerifyConfirmationCode')}
defaultTitle="Kurs Platform"
></Helmet>
<div>
{message && (
<Alert showIcon className="mb-4" type="success">

View file

@ -2,14 +2,25 @@ import React from 'react'
import { EntityProvider } from '@/contexts/EntityContext'
import DeveloperLayout from '@/components/layouts/DeveloperLayout'
import Dashboard from '@/components/developerKit/Dashboard'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
const DashboardPage: React.FC = () => {
const { translate } = useLocalization()
return (
<>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.DeveloperKit')}
defaultTitle="Kurs Platform"
></Helmet>
<DeveloperLayout>
<EntityProvider>
<Dashboard />
</EntityProvider>
</DeveloperLayout>
</>
)
}

View file

@ -1,6 +1,8 @@
import AdaptableCard from '@/components/shared/AdaptableCard'
import Container from '@/components/shared/Container'
import { useLocalization } from '@/utils/hooks/useLocalization'
import type { ReactNode } from 'react'
import { Helmet } from 'react-helmet'
type Log = {
version: string
@ -17,33 +19,22 @@ const logData: Log[] = [
{
version: '1.0.3',
date: '04 Şubat 2025',
updateContent: [
'[Fix] GridBoxEditorComponent bug',
'[Fix] TagBoxEditorComponent bug',
],
updateContent: ['[Fix] GridBoxEditorComponent bug', '[Fix] TagBoxEditorComponent bug'],
},
{
version: '1.0.2',
date: '27 Ocak 2025',
updateContent: [
'[Add] jspdf kurulumu',
'[Add] exceljs kurulumu',
'[Add] file-saver kurulumu',
],
updateContent: ['[Add] jspdf kurulumu', '[Add] exceljs kurulumu', '[Add] file-saver kurulumu'],
},
{
version: '1.0.1',
date: '23 Ocak 2025',
updateContent: [
'[Fix] Bağımlılık güvenlik açığı',
],
updateContent: ['[Fix] Bağımlılık güvenlik açığı'],
},
{
version: '1.0.0',
date: '20 Ocak 2025',
updateContent: [
'[Update] İlk yeni sürüm',
],
updateContent: ['[Update] İlk yeni sürüm'],
},
]
@ -51,29 +42,28 @@ const Log = (props: LogProps) => {
return (
<div className={`py-4 ${props.border && 'border-bottom'}`}>
<div className="flex items-center">
<h5 className="font-weight-normal mb-0 mr-3">
{props.version}
</h5>
<h5 className="font-weight-normal mb-0 mr-3">{props.version}</h5>
<code>{props.date}</code>
</div>
<div className="api-container p-0 border-0 mt-3">
{props.children}
</div>
<div className="api-container p-0 border-0 mt-3">{props.children}</div>
</div>
)
}
const Changelog = () => {
const { translate } = useLocalization()
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.ChangeLog')}
defaultTitle="Kurs Platform"
></Helmet>
<AdaptableCard>
<h4>Platform Güncelleme Günlüğü</h4>
{logData.map((elm) => (
<Log
key={elm.version}
version={`v${elm.version}`}
date={elm.date}
>
<Log key={elm.version} version={`v${elm.version}`} date={elm.date}>
{elm.updateContent.length > 0 ? (
<ul>
{elm.updateContent.map((item, i) => (

View file

@ -4,8 +4,12 @@ import React, { useState, useEffect } from 'react'
import { useForumData } from './useForumData'
import { ForumView } from './forum/ForumView'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
export function Forum() {
const { translate } = useLocalization()
const { user, tenant } = useStoreState((state) => state.auth)
const {
categories,
@ -47,6 +51,12 @@ export function Forum() {
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.Forum')}
defaultTitle="Kurs Platform"
></Helmet>
{error && (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative">

View file

@ -2,6 +2,8 @@ import { useEffect } from 'react'
import { useForumData } from './useForumData'
import { AdminView } from './admin/AdminView'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
export function Management() {
const {
@ -31,6 +33,7 @@ export function Management() {
unmarkPostAsAcceptedAnswer,
clearError,
} = useForumData()
const { translate } = useLocalization()
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
@ -54,6 +57,12 @@ export function Management() {
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.ForumManagement')}
defaultTitle="Kurs Platform"
></Helmet>
{error && (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative">

View file

@ -4,11 +4,15 @@ import { MenuItem } from '@/@types/menu'
import { useMenuData } from '@/utils/hooks/useMenuData'
import { AlertCircle, Loader2, Menu, Save } from 'lucide-react'
import { Container } from '@/components/shared'
import { Helmet } from 'react-helmet'
import { useLocalization } from '@/utils/hooks/useLocalization'
export const MenuManager = () => {
const { menuItems, setMenuItems, loading, error, refetch, saveMenuData } = useMenuData()
const [isDesignMode, setIsDesignMode] = useState(true)
const [isSaving, setIsSaving] = useState(false)
const { translate } = useLocalization()
const [saveMessage, setSaveMessage] = useState<{
type: 'success' | 'error'
text: string
@ -78,6 +82,12 @@ export const MenuManager = () => {
return (
<Container>
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'App.Menus.Manager')}
defaultTitle="Kurs Platform"
></Helmet>
<div className="bg-white rounded px-4 sm:px-4 lg:px-6 py-6">
<div className="flex items-center justify-between mb-6 flex-wrap gap-4">
{/* Sol kısım: Başlık */}

View file

@ -2,6 +2,7 @@ import React from 'react'
import { Users, Award, Clock, Globe2 } from 'lucide-react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useCountUp } from '@/utils/hooks/useCountUp'
import { Helmet } from 'react-helmet'
const About: React.FC = () => {
const { translate } = useLocalization()
@ -12,6 +13,13 @@ const About: React.FC = () => {
const countriesCount = useCountUp({ end: 3, duration: 1500 })
return (
<>
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.about.title')}
defaultTitle="Sözsoft"
></Helmet>
<div className="min-h-screen bg-gray-50">
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
@ -103,6 +111,7 @@ const About: React.FC = () => {
</div>
</div>
</div>
</>
)
}

View file

@ -1,30 +1,31 @@
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { Calendar, Clock, User, Tag, Search } from "lucide-react";
import { format } from "date-fns";
import { tr } from "date-fns/locale";
import { BlogCategory, BlogPost } from "@/proxy/blog/blog";
import { blogService } from "@/services/blog.service";
import { useLocalization } from "@/utils/hooks/useLocalization";
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { Calendar, Clock, User, Tag, Search } from 'lucide-react'
import { format } from 'date-fns'
import { tr } from 'date-fns/locale'
import { BlogCategory, BlogPost } from '@/proxy/blog/blog'
import { blogService } from '@/services/blog.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
const Blog = () => {
const { translate } = useLocalization()
const [posts, setPosts] = useState<BlogPost[]>([]);
const [categories, setCategories] = useState<BlogCategory[]>([]);
const [loading, setLoading] = useState(true);
const [selectedCategory, setSelectedCategory] = useState<string>("");
const [searchQuery, setSearchQuery] = useState("");
const [currentPage, setCurrentPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [posts, setPosts] = useState<BlogPost[]>([])
const [categories, setCategories] = useState<BlogCategory[]>([])
const [loading, setLoading] = useState(true)
const [selectedCategory, setSelectedCategory] = useState<string>('')
const [searchQuery, setSearchQuery] = useState('')
const [currentPage, setCurrentPage] = useState(1)
const [totalPages, setTotalPages] = useState(1)
useEffect(() => {
loadBlogData();
}, [currentPage, selectedCategory]);
loadBlogData()
}, [currentPage, selectedCategory])
const loadBlogData = async () => {
try {
setLoading(true);
setLoading(true)
const [postsData, categoriesData] = await Promise.all([
blogService.getPosts({
page: currentPage,
@ -33,29 +34,29 @@ const Blog = () => {
search: searchQuery,
}),
blogService.getCategories(),
]);
])
setPosts(postsData.items.filter(a=> a.isPublished));
setTotalPages(postsData.totalPages);
setCategories(categoriesData.filter(a=> a.isActive));
setPosts(postsData.items.filter((a) => a.isPublished))
setTotalPages(postsData.totalPages)
setCategories(categoriesData.filter((a) => a.isActive))
} catch (error) {
console.error("Blog verileri yüklenemedi:", error);
setPosts([]);
console.error('Blog verileri yüklenemedi:', error)
setPosts([])
} finally {
setLoading(false);
setLoading(false)
}
}
};
const handleSearch = (e: React.FormEvent) => {
e.preventDefault();
setCurrentPage(1);
loadBlogData();
};
e.preventDefault()
setCurrentPage(1)
loadBlogData()
}
const handleCategoryChange = (categoryId: string) => {
setSelectedCategory(categoryId);
setCurrentPage(1);
};
setSelectedCategory(categoryId)
setCurrentPage(1)
}
if (loading && posts.length === 0) {
return (
@ -64,11 +65,16 @@ const Blog = () => {
<p className="mt-4 text-gray-600">Blog yazıları yükleniyor...</p>
</div>
</div>
);
)
}
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.blog.title')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div
@ -76,12 +82,14 @@ const Blog = () => {
style={{
backgroundImage:
'url("https://images.pexels.com/photos/3183164/pexels-photo-3183164.jpeg?auto=compress&cs=tinysrgb&w=1920")',
backgroundSize: "cover",
backgroundPosition: "center",
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
></div>
<div className="container mx-auto pt-20 relative">
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">{translate('::Public.blog.title')}</h1>
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">
{translate('::Public.blog.title')}
</h1>
<p className="text-xl max-w-3xl ml-4">{translate('::Public.blog.subtitle')}</p>
</div>
</div>
@ -107,11 +115,11 @@ const Blog = () => {
{/* Category Filter */}
<div className="flex gap-2 flex-wrap">
<button
onClick={() => handleCategoryChange("")}
onClick={() => handleCategoryChange('')}
className={`px-4 py-2 rounded-lg transition-colors ${
selectedCategory === ""
? "bg-blue-600 text-white"
: "bg-gray-200 text-gray-700 hover:bg-gray-300"
selectedCategory === ''
? 'bg-blue-600 text-white'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
Tümü
@ -122,8 +130,8 @@ const Blog = () => {
onClick={() => handleCategoryChange(category.id)}
className={`px-4 py-2 rounded-lg transition-colors ${
selectedCategory === category.id
? "bg-blue-600 text-white"
: "bg-gray-200 text-gray-700 hover:bg-gray-300"
? 'bg-blue-600 text-white'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
{translate('::Public.' + category.name)} ({category.postCount})
@ -138,24 +146,16 @@ const Blog = () => {
<div className="container mx-auto px-4 py-16">
{!Array.isArray(posts) || posts.length === 0 ? (
<div className="text-center py-12">
<p className="text-gray-600 text-lg">
Henüz blog yazısı bulunmuyor.
</p>
<p className="text-gray-600 text-lg">Henüz blog yazısı bulunmuyor.</p>
</div>
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{posts.map((post) => (
<Link
to={`/blog/${post.slug || post.id}`}
key={post.id}
className="block"
>
<Link to={`/blog/${post.slug || post.id}`} key={post.id} className="block">
<article className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow h-full flex flex-col">
<div className="aspect-w-16 aspect-h-9 relative">
<img
src={
post.coverImage
}
src={post.coverImage}
alt={post.title}
className="object-cover w-full h-48"
/>
@ -167,7 +167,9 @@ const Blog = () => {
<h2 className="text-xl font-bold text-gray-900 mb-3 hover:text-blue-600 transition-colors">
{translate('::Public.' + post.title)}
</h2>
<p className="text-gray-600 mb-4 flex-1">{translate('::Public.' + post.summary)}</p>
<p className="text-gray-600 mb-4 flex-1">
{translate('::Public.' + post.summary)}
</p>
{/* Tags */}
{post.tags.length > 0 && (
@ -191,11 +193,9 @@ const Blog = () => {
</div>
<div className="flex items-center">
<Calendar size={16} className="mr-1" />
{format(
new Date(post.publishedAt || post.creationTime),
"dd MMM yyyy",
{ locale: tr }
)}
{format(new Date(post.publishedAt || post.creationTime), 'dd MMM yyyy', {
locale: tr,
})}
</div>
</div>
</div>
@ -223,8 +223,8 @@ const Blog = () => {
onClick={() => setCurrentPage(i + 1)}
className={`px-4 py-2 rounded-lg ${
currentPage === i + 1
? "bg-blue-600 text-white"
: "border border-gray-300 hover:bg-gray-50"
? 'bg-blue-600 text-white'
: 'border border-gray-300 hover:bg-gray-50'
}`}
>
{i + 1}
@ -232,9 +232,7 @@ const Blog = () => {
))}
<button
onClick={() =>
setCurrentPage(Math.min(totalPages, currentPage + 1))
}
onClick={() => setCurrentPage(Math.min(totalPages, currentPage + 1))}
disabled={currentPage === totalPages}
className="px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
>
@ -267,7 +265,7 @@ const Blog = () => {
</div>
</div>
</div>
);
};
)
}
export default Blog;
export default Blog

View file

@ -7,6 +7,7 @@ import { blogService } from '@/services/blog.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { useStoreState } from '@/store/store'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { Helmet } from 'react-helmet'
interface PostData {
image?: string
@ -78,9 +79,17 @@ const BlogDetail: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.blog.title')}
defaultTitle="Sözsoft"
></Helmet>
<div className="relative bg-blue-900 text-white py-12"></div>
<div className="container mx-auto px-4">
<Link to={ROUTES_ENUM.public.blog} className="text-blue-600 hover:underline mt-4 mb-4 inline-block">
<Link
to={ROUTES_ENUM.public.blog}
className="text-blue-600 hover:underline mt-4 mb-4 inline-block"
>
&larr; {translate('::Public.blog.backToBlog')}
</Link>
{postData.image && (
@ -90,7 +99,9 @@ const BlogDetail: React.FC = () => {
className="w-full h-96 object-cover rounded-lg mb-8"
/>
)}
<h1 className="text-4xl font-bold text-gray-900 mb-6">{translate('::Public.' + blogPost.title)}</h1>
<h1 className="text-4xl font-bold text-gray-900 mb-6">
{translate('::Public.' + blogPost.title)}
</h1>
<div className="flex items-center text-sm text-gray-500 space-x-4 mb-8">
<div className="flex items-center">
<span>{postData.author?.name}</span>
@ -105,7 +116,10 @@ const BlogDetail: React.FC = () => {
<div
className="prose max-w-none text-gray-800"
dangerouslySetInnerHTML={{
__html: currentLang == 'tr' ? translate(blogPost.contentTr!!) : translate(blogPost.contentEn!!),
__html:
currentLang == 'tr'
? translate(blogPost.contentTr!!)
: translate(blogPost.contentEn!!),
}}
/>
</div>

View file

@ -8,12 +8,16 @@ import {
removeItemFromCart,
updateCartItemQuantity,
} from '@/utils/cartUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
import React, { useState, useEffect } from 'react'
import { Helmet } from 'react-helmet'
import { useNavigate } from 'react-router-dom'
const Checkout: React.FC = () => {
const navigate = useNavigate()
const [isCartOpen, setIsCartOpen] = useState(false)
const { translate } = useLocalization()
const [cartState, setCartState] = useState<CartState>(() => {
const savedCart = localStorage.getItem('cartState')
return savedCart ? JSON.parse(savedCart) : initialCartState
@ -55,6 +59,12 @@ const Checkout: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Public.nav.checkout')}
defaultTitle="Kurs Platform"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div

View file

@ -1,4 +1,4 @@
import React from "react";
import React from 'react'
import {
Mail,
Phone,
@ -8,14 +8,21 @@ import {
CalendarDays,
CalendarCheck,
MessageCircle,
} from "lucide-react";
import { useLocalization } from "@/utils/hooks/useLocalization";
} from 'lucide-react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { Helmet } from 'react-helmet'
const Contact: React.FC = () => {
const { translate } = useLocalization()
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.contact.title')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div
@ -23,12 +30,14 @@ const Contact: React.FC = () => {
style={{
backgroundImage:
'url("https://images.pexels.com/photos/3183171/pexels-photo-3183171.jpeg?auto=compress&cs=tinysrgb&w=1920")',
backgroundSize: "cover",
backgroundPosition: "center",
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
></div>
<div className="container mx-auto pt-20 relative">
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">{translate('::Public.contact.title')}</h1>
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">
{translate('::Public.contact.title')}
</h1>
<p className="text-xl max-w-3xl ml-4">{translate('::Public.contact.subtitle')}</p>
</div>
</div>
@ -46,9 +55,7 @@ const Contact: React.FC = () => {
<div className="flex items-start space-x-4">
<MapPin className="w-6 h-6 text-blue-600 flex-shrink-0 mt-1" />
<div>
<p className="text-gray-600">
{translate('::Public.contact.address.full')}
</p>
<p className="text-gray-600">{translate('::Public.contact.address.full')}</p>
</div>
</div>
<div className="flex items-start space-x-4">
@ -96,9 +103,7 @@ const Contact: React.FC = () => {
className="w-24 object-contain mt-1 flex-shrink-0"
/>
<div>
<h3 className="font-semibold text-gray-900">
Özlem Öztürk
</h3>
<h3 className="font-semibold text-gray-900">Özlem Öztürk</h3>
<p className="text-gray-600">
03663 / Enpara
<br />
@ -163,7 +168,7 @@ const Contact: React.FC = () => {
</div>
</div>
</div>
);
};
)
}
export default Contact;
export default Contact

View file

@ -17,46 +17,123 @@ import {
} from 'lucide-react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { Helmet } from 'react-helmet'
const Home: React.FC = () => {
const { translate } = useLocalization()
const features = [
{ icon: <Users className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.reliable'), description: translate('::Public.features.reliable.desc') },
{ icon: <Calendar className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.rapid'), description: translate('::Public.features.rapid.desc') },
{ icon: <BookOpen className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.expert'), description: translate('::Public.features.expert.desc') },
{ icon: <CreditCard className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.muhasebe'), description: translate('::Public.features.muhasebe.desc') },
{ icon: <MessageSquare className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.iletisim'), description: translate('::Public.features.iletisim.desc') },
{ icon: <Phone className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.mobil'), description: translate('::Public.features.mobil.desc') },
{ icon: <BarChart className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.scalable'), description: translate('::Public.features.scalable.desc') },
{ icon: <Shield className="w-12 h-12 text-blue-500" />, title: translate('::Public.features.guvenlik'), description: translate('::Public.features.guvenlik.desc') },
{
icon: <Users className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.reliable'),
description: translate('::Public.features.reliable.desc'),
},
{
icon: <Calendar className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.rapid'),
description: translate('::Public.features.rapid.desc'),
},
{
icon: <BookOpen className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.expert'),
description: translate('::Public.features.expert.desc'),
},
{
icon: <CreditCard className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.muhasebe'),
description: translate('::Public.features.muhasebe.desc'),
},
{
icon: <MessageSquare className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.iletisim'),
description: translate('::Public.features.iletisim.desc'),
},
{
icon: <Phone className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.mobil'),
description: translate('::Public.features.mobil.desc'),
},
{
icon: <BarChart className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.scalable'),
description: translate('::Public.features.scalable.desc'),
},
{
icon: <Shield className="w-12 h-12 text-blue-500" />,
title: translate('::Public.features.guvenlik'),
description: translate('::Public.features.guvenlik.desc'),
},
]
const solutions = [
{ icon: <Monitor className="w-16 h-16 text-white" />, title: translate('::Public.solutions.web.title'), description: translate('::Public.solutions.web.desc'), color: 'bg-blue-600' },
{ icon: <Smartphone className="w-16 h-16 text-white" />, title: translate('::Public.solutions.mobile.title'), description: translate('::Public.solutions.mobile.desc'), color: 'bg-purple-600' },
{ icon: <Server className="w-16 h-16 text-white" />, title: translate('::Public.solutions.custom.title'), description: translate('::Public.solutions.custom.desc'), color: 'bg-green-600' },
{ icon: <Database className="w-16 h-16 text-white" />, title: translate('::Public.solutions.database.title'), description: translate('::Public.solutions.database.desc'), color: 'bg-red-600' },
{
icon: <Monitor className="w-16 h-16 text-white" />,
title: translate('::Public.solutions.web.title'),
description: translate('::Public.solutions.web.desc'),
color: 'bg-blue-600',
},
{
icon: <Smartphone className="w-16 h-16 text-white" />,
title: translate('::Public.solutions.mobile.title'),
description: translate('::Public.solutions.mobile.desc'),
color: 'bg-purple-600',
},
{
icon: <Server className="w-16 h-16 text-white" />,
title: translate('::Public.solutions.custom.title'),
description: translate('::Public.solutions.custom.desc'),
color: 'bg-green-600',
},
{
icon: <Database className="w-16 h-16 text-white" />,
title: translate('::Public.solutions.database.title'),
description: translate('::Public.solutions.database.desc'),
color: 'bg-red-600',
},
]
return (
<div className="min-h-screen">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'App.Home')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero */}
<div className="relative min-h-screen">
<div className="absolute inset-0 bg-gradient-to-br from-blue-900 via-indigo-900 to-purple-900"></div>
<div className="absolute inset-0 opacity-20" style={{ backgroundImage: 'url("https://images.pexels.com/photos/3183150/pexels-photo-3183150.jpeg?auto=compress&cs=tinysrgb&w=1920")', backgroundSize: 'cover', backgroundPosition: 'center' }}></div>
<div
className="absolute inset-0 opacity-20"
style={{
backgroundImage:
'url("https://images.pexels.com/photos/3183150/pexels-photo-3183150.jpeg?auto=compress&cs=tinysrgb&w=1920")',
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
></div>
<div className="relative container mx-auto px-4 pt-32 pb-16">
<div className="max-w-4xl mx-auto text-center">
<h1 className="text-3xl md:text-5xl font-bold mb-6 text-white">{translate('::Public.hero.title')}</h1>
<p className="text-xl md:text-2xl text-gray-300 mb-12">{translate('::Public.hero.subtitle')}</p>
<h1 className="text-3xl md:text-5xl font-bold mb-6 text-white">
{translate('::Public.hero.title')}
</h1>
<p className="text-xl md:text-2xl text-gray-300 mb-12">
{translate('::Public.hero.subtitle')}
</p>
<div className="flex flex-col md:flex-row justify-center gap-6 mb-16">
<Link to={ROUTES_ENUM.public.contact} className="inline-flex items-center justify-center px-8 py-4 bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white rounded-lg font-semibold transition-all transform hover:scale-105">
{translate('::Public.hero.cta.consultation')} <ArrowRight className="ml-2" size={20} />
<Link
to={ROUTES_ENUM.public.contact}
className="inline-flex items-center justify-center px-8 py-4 bg-gradient-to-r from-blue-500 to-purple-500 hover:from-blue-600 hover:to-purple-600 text-white rounded-lg font-semibold transition-all transform hover:scale-105"
>
{translate('::Public.hero.cta.consultation')}{' '}
<ArrowRight className="ml-2" size={20} />
</Link>
<Link to={ROUTES_ENUM.public.products} className="inline-flex items-center justify-center px-8 py-4 bg-white/10 hover:bg-white/20 text-white rounded-lg font-semibold backdrop-blur-sm transition-all transform hover:scale-105">
<Link
to={ROUTES_ENUM.public.products}
className="inline-flex items-center justify-center px-8 py-4 bg-white/10 hover:bg-white/20 text-white rounded-lg font-semibold backdrop-blur-sm transition-all transform hover:scale-105"
>
{translate('::Public.hero.cta.discover')}
</Link>
</div>
@ -64,17 +141,23 @@ const Home: React.FC = () => {
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-4xl mx-auto">
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
<Calendar className="mx-auto mb-4 text-blue-400" size={40} />
<h3 className="text-xl font-semibold mb-3 text-white">{translate('::Public.hero.service1.title')}</h3>
<h3 className="text-xl font-semibold mb-3 text-white">
{translate('::Public.hero.service1.title')}
</h3>
<p className="text-gray-300">{translate('::Public.hero.service1.desc')}</p>
</div>
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
<Users className="mx-auto mb-4 text-purple-400" size={40} />
<h3 className="text-xl font-semibold mb-3 text-white">{translate('::Public.hero.service2.title')}</h3>
<h3 className="text-xl font-semibold mb-3 text-white">
{translate('::Public.hero.service2.title')}
</h3>
<p className="text-gray-300">{translate('::Public.hero.service2.desc')}</p>
</div>
<div className="bg-white/5 backdrop-blur-sm rounded-2xl p-8 text-center hover:scale-105 hover:bg-white/10 transition-all">
<Shield className="mx-auto mb-4 text-indigo-400" size={40} />
<h3 className="text-xl font-semibold mb-3 text-white">{translate('::Public.hero.service3.title')}</h3>
<h3 className="text-xl font-semibold mb-3 text-white">
{translate('::Public.hero.service3.title')}
</h3>
<p className="text-gray-300">{translate('::Public.hero.service3.desc')}</p>
</div>
</div>
@ -86,13 +169,20 @@ const Home: React.FC = () => {
<section className="py-20 bg-white">
<div className="container mx-auto px-4">
<div className="text-center mb-16">
<h2 className="text-4xl font-bold text-gray-900 mb-4">{translate('::Public.features.title')}</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">{translate('::Public.features.subtitle')}</p>
<h2 className="text-4xl font-bold text-gray-900 mb-4">
{translate('::Public.features.title')}
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
{translate('::Public.features.subtitle')}
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{features.map((feature, i) => (
<div key={i} className="p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow">
<div
key={i}
className="p-8 bg-white rounded-xl shadow-lg hover:shadow-xl transition-shadow"
>
<div className="mb-6">{feature.icon}</div>
<h3 className="text-xl font-semibold text-gray-900 mb-4">{feature.title}</h3>
<p className="text-gray-600">{feature.description}</p>
@ -106,13 +196,20 @@ const Home: React.FC = () => {
<section className="py-20 bg-gray-50">
<div className="container mx-auto px-4">
<div className="text-center mb-16">
<h2 className="text-4xl font-bold text-gray-900 mb-4">{translate('::Public.solutions.title')}</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">{translate('::Public.solutions.subtitle')}</p>
<h2 className="text-4xl font-bold text-gray-900 mb-4">
{translate('::Public.solutions.title')}
</h2>
<p className="text-xl text-gray-600 max-w-2xl mx-auto">
{translate('::Public.solutions.subtitle')}
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{solutions.map((s, i) => (
<div key={i} className="group relative overflow-hidden rounded-2xl transition-all hover:scale-105">
<div
key={i}
className="group relative overflow-hidden rounded-2xl transition-all hover:scale-105"
>
<div className={`${s.color} p-8 h-full`}>
<div className="mb-6">{s.icon}</div>
<h3 className="text-2xl font-semibold text-white mb-4">{s.title}</h3>
@ -127,9 +224,14 @@ const Home: React.FC = () => {
{/* Call to Action */}
<section className="bg-blue-600 py-16">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl font-bold text-white mb-4">{translate('::Public.common.getStarted')}</h2>
<h2 className="text-3xl font-bold text-white mb-4">
{translate('::Public.common.getStarted')}
</h2>
<p className="text-white text-lg mb-8">{translate('::Public.common.contact')}</p>
<Link to={ROUTES_ENUM.public.contact} className="bg-white text-blue-600 px-8 py-3 rounded-lg font-semibold hover:bg-blue-50 transition-colors">
<Link
to={ROUTES_ENUM.public.contact}
className="bg-white text-blue-600 px-8 py-3 rounded-lg font-semibold hover:bg-blue-50 transition-colors"
>
{translate('::Public.common.learnMore')}
</Link>
</div>

View file

@ -10,7 +10,9 @@ import {
removeItemFromCart,
updateCartItemQuantity,
} from '@/utils/cartUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
import React, { useState, useEffect } from 'react'
import { Helmet } from 'react-helmet'
import { useNavigate } from 'react-router-dom'
const Payment: React.FC = () => {
@ -18,6 +20,7 @@ const Payment: React.FC = () => {
const [tenant, setTenant] = useState<CustomTenantDto | null>(null)
const [isCartOpen, setIsCartOpen] = useState(false)
const [cartState, setCartState] = useState<CartState>(initialCartState)
const { translate } = useLocalization()
useEffect(() => {
const tenantData = localStorage.getItem('tenantData') // ✅ güncellendi
@ -109,6 +112,12 @@ const Payment: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.nav.payment')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div

View file

@ -11,12 +11,16 @@ import {
setCartGlobalPeriod,
updateCartItemQuantity,
} from '@/utils/cartUtils'
import { useLocalization } from '@/utils/hooks/useLocalization'
import React, { useState, useEffect } from 'react'
import { Helmet } from 'react-helmet'
import { useNavigate } from 'react-router-dom'
const Products: React.FC = () => {
const [searchQuery, setSearchQuery] = useState('')
const [isCartOpen, setIsCartOpen] = useState(false)
const { translate } = useLocalization()
const [cartState, setCartState] = useState<CartState>(() => {
// Load cart state from localStorage if available
const savedCart = localStorage.getItem('cartState')
@ -70,6 +74,12 @@ const Products: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.nav.products')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div

View file

@ -1,16 +1,9 @@
import React from "react";
import {
Code2,
Globe2,
Server,
Users,
Shield,
Settings,
CheckCircle,
} from "lucide-react";
import { Link } from "react-router-dom";
import { useLocalization } from "@/utils/hooks/useLocalization";
import { ROUTES_ENUM } from "@/routes/route.constant";
import React from 'react'
import { Code2, Globe2, Server, Users, Shield, Settings, CheckCircle } from 'lucide-react'
import { Link } from 'react-router-dom'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { ROUTES_ENUM } from '@/routes/route.constant'
import { Helmet } from 'react-helmet'
const Services: React.FC = () => {
const { translate } = useLocalization()
@ -88,7 +81,7 @@ const Services: React.FC = () => {
translate('::Public.services.consulting.features.training'),
],
},
];
]
const supportPlans = [
{
@ -127,10 +120,16 @@ const Services: React.FC = () => {
translate('::Public.services.support.sms.features.api'),
],
},
];
]
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.nav.services')}
defaultTitle="Sözsoft"
></Helmet>
{/* Hero Section */}
<div className="relative bg-blue-900 text-white py-12">
<div
@ -138,12 +137,14 @@ const Services: React.FC = () => {
style={{
backgroundImage:
'url("https://images.pexels.com/photos/3183173/pexels-photo-3183173.jpeg?auto=compress&cs=tinysrgb&w=1920")',
backgroundSize: "cover",
backgroundPosition: "center",
backgroundSize: 'cover',
backgroundPosition: 'center',
}}
></div>
<div className="container mx-auto pt-20 relative">
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">{translate('::Public.services.title')}</h1>
<h1 className="text-5xl font-bold ml-4 mt-3 mb-2 text-white">
{translate('::Public.services.title')}
</h1>
<p className="text-xl max-w-3xl ml-4">{translate('::Public.services.subtitle')}</p>
</div>
</div>
@ -158,16 +159,11 @@ const Services: React.FC = () => {
className="bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow"
>
<div className="mb-6">{service.icon}</div>
<h3 className="text-2xl font-bold text-gray-900 mb-4">
{service.title}
</h3>
<h3 className="text-2xl font-bold text-gray-900 mb-4">{service.title}</h3>
<p className="text-gray-600 mb-6">{service.description}</p>
<ul className="space-y-2">
{service.features.map((feature, fIndex) => (
<li
key={fIndex}
className="flex items-center text-gray-700"
>
<li key={fIndex} className="flex items-center text-gray-700">
<span className="w-2 h-2 bg-blue-600 rounded-full mr-2"></span>
{feature}
</li>
@ -187,18 +183,12 @@ const Services: React.FC = () => {
</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{supportPlans.map((plan, index) => (
<div
key={index}
className="bg-white rounded-xl shadow-lg p-8 border border-gray-200"
>
<div key={index} className="bg-white rounded-xl shadow-lg p-8 border border-gray-200">
<h3 className="text-xl font-bold mb-4">{plan.title}</h3>
<ul className="space-y-3 mb-8">
{plan.features.map((feature, fIndex) => (
<li
key={fIndex}
className="flex items-center space-x-2 text-gray-700"
>
<li key={fIndex} className="flex items-center space-x-2 text-gray-700">
<CheckCircle className="w-5 h-5 text-green-500 flex-shrink-0" />
<span>{feature}</span>
</li>
@ -219,7 +209,9 @@ const Services: React.FC = () => {
{/* Call to Action */}
<div className="bg-blue-900 text-white py-16">
<div className="container mx-auto px-4 text-center">
<h2 className="text-3xl font-bold mb-6 text-white">{translate('::Public.services.cta.title')}</h2>
<h2 className="text-3xl font-bold mb-6 text-white">
{translate('::Public.services.cta.title')}
</h2>
<p className="text-xl mb-8 max-w-2xl mx-auto">
{translate('::Public.services.cta.description')}
</p>
@ -232,7 +224,7 @@ const Services: React.FC = () => {
</div>
</div>
</div>
);
};
)
}
export default Services;
export default Services

View file

@ -1,10 +1,13 @@
import { OrderSuccess } from '@/components/orders/OrderSuccess'
import { useLocalization } from '@/utils/hooks/useLocalization'
import React, { useState, useEffect } from 'react'
import { Helmet } from 'react-helmet'
import { useNavigate } from 'react-router-dom'
const Success: React.FC = () => {
const navigate = useNavigate()
const [orderId, setOrderId] = useState<string>('')
const { translate } = useLocalization()
useEffect(() => {
// Get order ID from local storage
@ -28,6 +31,11 @@ const Success: React.FC = () => {
return (
<div className="min-h-screen bg-gray-50">
<Helmet
titleTemplate="%s | Sözsoft"
title={translate('::' + 'Public.nav.success')}
defaultTitle="Sözsoft"
></Helmet>
<div className="relative bg-blue-900 text-white py-12">
<div
className="absolute inset-0 opacity-20"

View file

@ -121,7 +121,7 @@ const Settings = () => {
<Container className="h-full">
<Helmet
titleTemplate="%s | Kurs Platform"
title={translate('::' + 'Settings')}
title={translate('::' + 'App.Settings')}
defaultTitle="Kurs Platform"
></Helmet>