Compare commits

...

25 Commits

Author SHA1 Message Date
nabijonovdavronbek619@gmail.com
ee34ef0905 for gitea 2026-04-13 19:04:15 +05:00
Davronbek Nabijonov
46552fdd55 Merge pull request #21 from DavronNabijonv/new_changes
new sitemap.xml file
2026-04-13 18:57:56 +05:00
nabijonovdavronbek619@gmail.com
fa9df55856 new sitemap.xml file 2026-04-13 18:54:40 +05:00
Davronbek Nabijonov
2f8fc09027 Merge pull request #20 from DavronNabijonv/new_changes
New changes
2026-04-10 17:07:30 +05:00
nabijonovdavronbek619@gmail.com
18724e135b fix 2026-04-10 17:05:51 +05:00
nabijonovdavronbek619@gmail.com
a6a221faf5 fix 2026-04-10 17:02:52 +05:00
nabijonovdavronbek619@gmail.com
be582a6474 authButton fixed 2026-04-10 16:59:51 +05:00
nabijonovdavronbek619@gmail.com
b4fd590eda fix base_api error 2026-04-10 16:53:29 +05:00
nabijonovdavronbek619@gmail.com
553db7194a payment link chnage to new link 2026-04-09 20:04:24 +05:00
nabijonovdavronbek619@gmail.com
aba0d25cbd last fix 2026-04-09 12:48:23 +05:00
Davronbek Nabijonov
9a62c214a5 Merge pull request #15 from DavronNabijonv/dev
Dev
2026-04-03 21:48:16 +05:00
Davronbek Nabijonov
83d75ad499 Merge pull request #14 from DavronNabijonv/dev
vercel error fixed
2026-04-03 20:59:41 +05:00
Davronbek Nabijonov
10fcded48f Merge pull request #13 from DavronNabijonv/dev
Dev
2026-04-03 20:51:49 +05:00
Davronbek Nabijonov
ff8e003ef5 Merge pull request #12 from DavronNabijonv/dev
detail page text translation added
2026-04-03 14:40:35 +05:00
Davronbek Nabijonov
4a755d5d03 Merge pull request #11 from DavronNabijonv/dev
change baseUrl variable
2026-04-02 22:58:32 +05:00
Davronbek Nabijonov
6e485484fb Merge pull request #10 from DavronNabijonv/dev
sertificate downloaded added
2026-04-02 21:30:09 +05:00
Davronbek Nabijonov
3af699c468 Merge pull request #9 from DavronNabijonv/dev
fix
2026-04-02 21:11:39 +05:00
Davronbek Nabijonov
d3a868da68 Merge pull request #8 from DavronNabijonv/dev
Dev
2026-04-02 21:01:41 +05:00
Davronbek Nabijonov
0c3b5f50ad Merge pull request #7 from DavronNabijonv/dev
detail page
2026-04-02 13:54:33 +05:00
Davronbek Nabijonov
60c3ddf43c Merge pull request #6 from DavronNabijonv/dev
Dev
2026-04-02 11:42:22 +05:00
Davronbek Nabijonov
69abdd6562 Merge pull request #5 from DavronNabijonv/dev
Dev
2026-04-02 11:06:09 +05:00
Davronbek Nabijonov
1efb97e4c9 Merge pull request #4 from DavronNabijonv/dev
Dev
2026-04-01 12:14:01 +05:00
Davronbek Nabijonov
e8c4bd7bd1 Merge pull request #3 from DavronNabijonv/dev
added multi language features
2026-03-31 19:55:26 +05:00
Davronbek Nabijonov
00cbac1292 Merge pull request #2 from DavronNabijonv/dev
Dev
2026-03-31 17:42:35 +05:00
Davronbek Nabijonov
016094fa34 Merge pull request #1 from DavronNabijonv/dev
Payment modal added
2026-03-31 12:14:29 +05:00
23 changed files with 604 additions and 208 deletions

View File

@@ -7,4 +7,5 @@ Disallow: /_next/
Disallow: /admin/
# Sitemap location
Sitemap: https://antiplagiat.uz/sitemap.xml
Sitemap: https://antiplagiat.uz/sitemap.xml
# enjoy

106
public/llms.txt Normal file
View File

@@ -0,0 +1,106 @@
# AntiPlagiat.uz — AI uchun sayt ma'lumotlari (llms.txt)
# Standart: https://llmstxt.org
# Yangilangan: 2026-04-12
# ═══════════════════════════════════════════════════════════
# SAYT HAQIDA / ABOUT THE SITE
# ═══════════════════════════════════════════════════════════
> AntiPlagiat.uz — O'zbekistonning akademik plagiat tekshiruvi platformasi.
> Dissertatsiya, kurs ishi va ilmiy maqolalarni onlayn tekshiring.
> Natija daqiqalar ichida tayyor bo'ladi. Rasmiy sertifikat beriladi.
**Sayt nomi:** AntiPlagiat.uz
**Egalik qiluvchi:** Pedagok.uz
**Manzil:** https://anti-plagiat.uz
**Kanon manzil:** https://antiplagiat.uz
**Kategoriya:** Ta'lim / Academic integrity / Plagiarism detection
**Til:** O'zbek (uz), Rus (ru), Ingliz (en)
**Mamlakatlar:** O'zbekiston va MDH
---
## Asosiy xizmatlar / Core Services
AntiPlagiat.uz quyidagi xizmatlarni taqdim etadi:
1. **Plagiat tekshiruvi** — PDF, DOC, DOCX, TXT formatdagi hujjatlarni plagiatga tekshirish. Maks fayl hajmi: 20 MB. Natija foiz ko'rinishida beriladi.
2. **SI (Sun'iy Intellekt) detektor** — Matnning sun'iy intellekt tomonidan yozilganligini aniqlash. AI generatsiya ehtimolini foizda ko'rsatadi.
3. **Rasmiy sertifikat** — Orijinallik tasdiqlangan hujjatlar uchun rasmiy sertifikat beriladi.
4. **Batafsil hisobot** — O'xshashlik manbalari, mos keladigan so'zlar, AI tahlili ballari ko'rsatiladi.
---
## Texnik ma'lumotlar / Technical Details
- **Framework:** Next.js (React, App Router)
- **Lokalizatsiya:** /uz, /ru, /en yo'llar orqali
- **To'lov tizimi:** Payme (SSL himoyalangan)
- **Qo'llab-quvvatlangan formatlar:** PDF, DOC, DOCX, TXT
- **Maksimal fayl:** 20 MB
- **Aniqlik darajasi:** 98.7%
- **Tekshirilgan hujjatlar:** 50,000+
---
## Sahifalar tuzilishi / Site Structure
### Ommaviy sahifalar (Public pages)
| URL | Maqsad |
|----------------------------------|-------------------------------------|
| /uz | Bosh sahifa (O'zbek) |
| /ru | Bosh sahifa (Rus) |
| /en | Bosh sahifa (Ingliz) |
| /uz/plagiat | Plagiat tekshiruvi (autentifikatsiya)|
| /ru/plagiat | Plagiat tekshiruvi (Rus) |
| /en/plagiat | Plagiarism check (English) |
| /uz/si | SI detektor (O'zbek) |
| /ru/si | SI detektor (Rus) |
| /en/si | AI Content detector (English) |
| /uz/history | Tekshiruv tarixi |
| /uz/cabinet | Shaxsiy kabinet (dashboard) |
### Dinamik sahifalar
| URL shakli | Maqsad |
|----------------------------------|-------------------------------------|
| /uz/{id} | Muayyan tekshiruv natijasi |
| /ru/{id} | Tekshiruv natijasi (Rus) |
| /en/{id} | Check result (English) |
---
## Foydalanuvchilar / Target Audience
- Talabalara: kurs ishlari, dissertatsiyalar, referatlar uchun
- O'qituvchilar: talabalar ishlarini tekshirish uchun
- Ilmiy xodimlar: maqolalar va tadqiqotlarni tekshirish uchun
- Muassasalar: akademik halollik nazorati uchun
---
## Aloqa / Contact
- **Veb-sayt:** https://anti-plagiat.uz
- **Twitter/X:** @antiplagiatuz
- **Egalik kompaniya:** Pedagok.uz
---
## Litsenziya va foydalanish / Usage
AntiPlagiat.uz kontenti faqat ma'lumot maqsadida foydalanilishi mumkin.
Foydalanuvchilar ma'lumotlari maxfiy saqlanadi va tahlil tugagach o'chiriladi.
Xizmat O'zbekiston qonunchiligiga muvofiq ishlaydi.
---
## Crawling yo'riqnomasi / Crawling Guidelines
AI botlar va qidiruv tizimlari uchun:
- robots.txt: https://anti-plagiat.uz/robots.txt
- sitemap.xml: https://anti-plagiat.uz/sitemap.xml
- Foydalanuvchi ma'lumotlarini (cabinet, history, individual check results) crawl qilmang
- API (/api/*) yo'llarini crawl qilmang
- Preferred crawl delay: 2 soniya

112
public/robots.txt Normal file
View File

@@ -0,0 +1,112 @@
# robots.txt — anti-plagiat.uz
# Yangilangan: 2026-04-12
# ─── Umumiy qoidalar (barcha botlar) ───────────────────────────────────────
User-agent: *
Allow: /
Allow: /uz/
Allow: /ru/
Allow: /en/
Allow: /uz/plagiat
Allow: /ru/plagiat
Allow: /en/plagiat
Allow: /uz/si
Allow: /ru/si
Allow: /en/si
# API va autentifikatsiya marshrutlarini bloklash
Disallow: /api/
Disallow: /_next/
Disallow: /uz/cabinet/
Disallow: /ru/cabinet/
Disallow: /en/cabinet/
# Crawl tezligi (ortiqcha yuklanmasin)
Crawl-delay: 2
# ─── Google ───────────────────────────────────────────────────────────────
User-agent: Googlebot
Allow: /
Disallow: /api/
Disallow: /_next/
Crawl-delay: 1
User-agent: Googlebot-Image
Disallow: /
# ─── Bing ─────────────────────────────────────────────────────────────────
User-agent: Bingbot
Allow: /
Disallow: /api/
Disallow: /_next/
Crawl-delay: 2
# ─── AI Crawler agentlari ─────────────────────────────────────────────────
# GPT / OpenAI
User-agent: GPTBot
Allow: /
Allow: /uz/
Allow: /ru/
Allow: /en/
Disallow: /api/
Disallow: /_next/
Disallow: /resources/media/
# Claude (Anthropic)
User-agent: ClaudeBot
Allow: /
Allow: /uz/
Allow: /ru/
Allow: /en/
Disallow: /api/
Disallow: /_next/
# Perplexity
User-agent: PerplexityBot
Allow: /
Disallow: /api/
Disallow: /_next/
# Meta AI
User-agent: Meta-ExternalAgent
Allow: /
Disallow: /api/
Disallow: /_next/
# Gemini / Google AI
User-agent: Google-Extended
Allow: /
Disallow: /api/
Disallow: /_next/
# Cohere
User-agent: cohere-ai
Allow: /
Disallow: /api/
Disallow: /_next/
# Common Crawl (AI training ma'lumotlar to'plami)
User-agent: CCBot
Allow: /
Disallow: /api/
Disallow: /_next/
Disallow: /resources/media/
# ─── Noxush botlar ────────────────────────────────────────────────────────
User-agent: MJ12bot
Disallow: /
User-agent: DotBot
Disallow: /
User-agent: AhrefsBot
Disallow: /
User-agent: SemrushBot
Disallow: /
# ─── Sitemap manzili ──────────────────────────────────────────────────────
Sitemap: https://anti-plagiat.uz/sitemap.xml
# ─── AI ma'lumot fayli ────────────────────────────────────────────────────
# AI modellar uchun: https://anti-plagiat.uz/llms.txt

View File

@@ -1,84 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<!-- ============================== -->
<!-- Bosh sahifalar / Home pages -->
<!-- ============================== -->
<url>
<loc>https://anti-plagiat.uz/uz</loc>
<lastmod>2026-04-06</lastmod>
<lastmod>2026-04-12</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en"/>
</url>
<url>
<loc>https://anti-plagiat.uz/uz/plagat</loc>
<lastmod>2026-04-06</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagat"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagat"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagat"/>
</url>
<url>
<loc>https://anti-plagiat.uz/uz/cabinet</loc>
<lastmod>2026-04-06</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet"/>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru" />
</url>
<url>
<loc>https://anti-plagiat.uz/ru</loc>
<lastmod>2026-04-06</lastmod>
<lastmod>2026-04-12</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en"/>
</url>
<url>
<loc>https://anti-plagiat.uz/ru/plagat</loc>
<lastmod>2026-04-06</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagat"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagat"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagat"/>
</url>
<url>
<loc>https://anti-plagiat.uz/ru/cabinet</loc>
<lastmod>2026-04-06</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet"/>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru" />
</url>
<url>
<loc>https://anti-plagiat.uz/en</loc>
<lastmod>2026-04-06</lastmod>
<lastmod>2026-04-12</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en"/>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru" />
</url>
<!-- ============================== -->
<!-- Plagiat tekshiruvi sahifalari -->
<!-- ============================== -->
<url>
<loc>https://anti-plagiat.uz/en/plagat</loc>
<lastmod>2026-04-06</lastmod>
<loc>https://anti-plagiat.uz/uz/plagiat</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagiat" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagiat" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagiat" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/plagiat" />
</url>
<url>
<loc>https://anti-plagiat.uz/ru/plagiat</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagiat" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagiat" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagiat" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/plagiat" />
</url>
<url>
<loc>https://anti-plagiat.uz/en/plagiat</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.9</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagiat" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagiat" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagiat" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/plagiat" />
</url>
<!-- ============================== -->
<!-- SI Detektor sahifalari -->
<!-- ============================== -->
<url>
<loc>https://anti-plagiat.uz/uz/si</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/plagat"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/plagat"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/plagat"/>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/si" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/si" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/si" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/si" />
</url>
<url>
<loc>https://anti-plagiat.uz/ru/si</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/si" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/si" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/si" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/si" />
</url>
<url>
<loc>https://anti-plagiat.uz/en/si</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/si" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/si" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/si" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/si" />
</url>
<!-- ============================== -->
<!-- Tekshiruv tarixi sahifalari -->
<!-- ============================== -->
<url>
<loc>https://anti-plagiat.uz/uz/history</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/history" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/history" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/history" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/history" />
</url>
<url>
<loc>https://anti-plagiat.uz/ru/history</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/history" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/history" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/history" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/history" />
</url>
<url>
<loc>https://anti-plagiat.uz/en/history</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>weekly</changefreq>
<priority>0.6</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/history" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/history" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/history" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/history" />
</url>
<!-- ============================== -->
<!-- Shaxsiy kabinet sahifalari -->
<!-- (noindex - autentifikatsiya) -->
<!-- ============================== -->
<url>
<loc>https://anti-plagiat.uz/uz/cabinet</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/cabinet" />
</url>
<url>
<loc>https://anti-plagiat.uz/ru/cabinet</loc>
<lastmod>2026-04-12</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/cabinet" />
</url>
<url>
<loc>https://anti-plagiat.uz/en/cabinet</loc>
<lastmod>2026-04-06</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet"/>
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet"/>
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet"/>
<lastmod>2026-04-12</lastmod>
<changefreq>monthly</changefreq>
<priority>0.4</priority>
<xhtml:link rel="alternate" hreflang="uz" href="https://anti-plagiat.uz/uz/cabinet" />
<xhtml:link rel="alternate" hreflang="ru" href="https://anti-plagiat.uz/ru/cabinet" />
<xhtml:link rel="alternate" hreflang="en" href="https://anti-plagiat.uz/en/cabinet" />
<xhtml:link rel="alternate" hreflang="x-default" href="https://anti-plagiat.uz/ru/cabinet" />
</url>
</urlset>

View File

@@ -23,4 +23,5 @@ export interface PaymentModalProps {
price: PriceCalculate;
onConfirmPayment: () => void;
isLoading: boolean;
hasSertificate: boolean;
}

View File

@@ -55,6 +55,7 @@ export const PaymentModal: React.FC<PaymentModalProps> = ({
price,
onConfirmPayment,
isLoading,
hasSertificate,
}) => {
const dialogRef = useRef<HTMLDivElement>(null);
const status = isLoading ? 'loading' : 'idle';
@@ -144,18 +145,20 @@ export const PaymentModal: React.FC<PaymentModalProps> = ({
</div>
{/* Certificate badge */}
<div className="flex items-center gap-2 text-sm text-emerald-700 bg-emerald-50 border border-emerald-100 rounded-lg px-3.5 py-2.5">
<svg
width="15"
height="15"
viewBox="0 0 24 24"
fill="currentColor"
className="shrink-0"
>
<path d="M12 1l2.753 5.527 6.247.907-4.5 4.385 1.063 6.181L12 15.027l-5.563 2.973 1.063-6.181L3 7.434l6.247-.907z" />
</svg>
<span>{t('certificateIncluded')}</span>
</div>
{hasSertificate && (
<div className="flex items-center gap-2 text-sm text-emerald-700 bg-emerald-50 border border-emerald-100 rounded-lg px-3.5 py-2.5">
<svg
width="15"
height="15"
viewBox="0 0 24 24"
fill="currentColor"
className="shrink-0"
>
<path d="M12 1l2.753 5.527 6.247.907-4.5 4.385 1.063 6.181L12 15.027l-5.563 2.973 1.063-6.181L3 7.434l6.247-.907z" />
</svg>
<span>{t('certificateIncluded')}</span>
</div>
)}
{/* Payment method label */}
<div>

View File

@@ -43,9 +43,9 @@ export function useCertificateModal({
const certificateMutation = useMutation({
mutationFn: (payload: CertificatePayload) =>
apiRequest('POST', links.sertifikat(document_id), payload).then(
(res) => res.data as ArrayBuffer,
),
apiRequest<ArrayBuffer>('POST', links.sertifikat(document_id), payload, {
responseType: 'arraybuffer',
}).then((res) => res.data),
onSuccess: (data: ArrayBuffer) => {
if (data) {
const blob = new Blob([data], { type: 'application/pdf' });
@@ -54,7 +54,7 @@ export function useCertificateModal({
a.href = objectUrl;
a.download = `certificate-${document_id}.pdf`;
a.click();
URL.revokeObjectURL(objectUrl);
setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
}
setSuccess(true);
setTimeout(() => {

View File

@@ -3,6 +3,9 @@ import { SEO_DATA, type SupportedLocale } from '../config/seo.config';
// ─── Site-wide constants ───────────────────────────────────────────────────────
export const SERTIFICATE_PRICE = 20600;
export const PLAGIAT_SERVICE_FEE = 20600;
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? 'https://antiplagiat.uz';
const OG_IMAGE_URL = `${SITE_URL}/og-image.png`; // 1200×630 px recommended
const TWITTER_HANDLE = '@antiplagiatuz'; // update or remove if unused

View File

@@ -45,7 +45,7 @@ function extractErrorMessage(error: AxiosError): string {
// ─── Constants ─────────────────────────────────────────────────────────────────
// const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
const baseUrl = 'https://dev-api.anti-plagiat.uz/api/v1';
const baseUrl = 'https://api.anti-plagiat.uz/api/v1';
const DEFAULT_LOCALE = 'uz'; // fallback locale for redirect
// ─── Token helpers ─────────────────────────────────────────────────────────────

View File

@@ -1,7 +1,7 @@
export const links = {
login: '/users/login/',
register: '/users/register/',
plagiarismCheck: '/shared/document/',
plagiarismCheck: '/shared/documents/',
history: '/shared/documents/list/',
detail: (id: number) => `/shared/documents/${id}/`,
payment: (order_id: number) => `/users/payme/link/${order_id}/`,

View File

@@ -18,7 +18,7 @@ function NavigationMenu({
data-slot="navigation-menu"
data-viewport={viewport}
className={cn(
'group/navigation-menu relative flex max-w-max flex-1 items-center justify-center',
' relative flex max-w-max flex-1 items-center justify-center',
className,
)}
{...props}

View File

@@ -0,0 +1,12 @@
import { CabinetSection } from '@/widgets/cabinet/lib/types';
import { create } from 'zustand';
type CabinetNavZustand = {
navItem: CabinetSection;
setNavItem: (item: CabinetSection) => void;
};
export const useCabinetNav = create<CabinetNavZustand>((set) => ({
navItem: 'dashboard',
setNavItem: (item: CabinetSection) => set({ navItem: item }),
}));

View File

@@ -1,14 +1,43 @@
'use client';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useCabinetNav } from '@/shared/zustand/cabinetNav';
import type { CabinetSection } from '../types';
const VALID_SECTIONS: CabinetSection[] = [
'dashboard',
'plagiat',
'si',
'payments',
'profile',
];
export const useCabinet = () => {
const { navItem, setNavItem } = useCabinetNav();
const navItemZustrand = useCabinetNav((state) => state.navItem);
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
const [activeSection, setActiveSection] =
useState<CabinetSection>('dashboard');
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
useEffect(() => {
if (navItemZustrand) {
const activeSection: CabinetSection = VALID_SECTIONS.includes(
navItemZustrand as CabinetSection,
)
? (navItemZustrand as CabinetSection)
: 'dashboard';
setActiveSection(activeSection);
} else {
const activeSection: CabinetSection = VALID_SECTIONS.includes(
navItem as CabinetSection,
)
? (navItem as CabinetSection)
: 'dashboard';
setActiveSection(activeSection);
}
}, [navItemZustrand]);
const navigate = (section: CabinetSection) => {
setActiveSection(section);
setNavItem(section);
setIsSidebarOpen(false);
};

View File

@@ -1,13 +1,13 @@
'use client';
import React, { useState } from 'react';
import React from 'react';
import { Clock, XCircle, ReceiptText } from 'lucide-react';
import { useMutation, useQuery } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import { useTranslations } from 'next-intl';
import { apiRequest } from '@/shared/request/apiRequest';
import { links } from '@/shared/request/links';
import PaymentStatus from '@/widgets/detail/paidStatus';
import { toast } from 'react-toastify';
import { PaymentModal } from '@/features/modals/paymentModal/ui/Paymentmodal';
// import { toast } from 'react-toastify';
// import { PaymentModal } from '@/features/modals/paymentModal/ui/Paymentmodal';
// ─── Types ─────────────────────────────────────────────────────────────────────
@@ -38,7 +38,7 @@ function formatPrice(price: string) {
export function PaymentsTable() {
const t = useTranslations('Cabinet');
const [isPaymentOpen, setIsPaymentOpen] = useState(false);
// const [isPaymentOpen, setIsPaymentOpen] = useState(false);
const { data, isLoading } = useQuery({
queryKey: ['pay_history'],
queryFn: (): Promise<Inspection[]> =>
@@ -47,29 +47,29 @@ export function PaymentsTable() {
),
});
const payment = useMutation({
mutationKey: ['payload'],
mutationFn: ({ order_id }: { order_id: number }) =>
apiRequest<{ payment_link: string }>('POST', links.payment(order_id)),
onSuccess: (res) => {
window.open(res.data.payment_link, '_self');
setIsPaymentOpen(false);
},
onError: (err) => {
const message =
err instanceof Error ? err.message : 'An unexpected error occurred.';
toast.error(message);
setIsPaymentOpen(false);
},
});
// const payment = useMutation({
// mutationKey: ['payload'],
// mutationFn: ({ order_id }: { order_id: number }) =>
// apiRequest<{ payment_link: string }>('POST', links.payment(order_id)),
// onSuccess: (res) => {
// window.open(res.data.payment_link, '_self');
// // setIsPaymentOpen(false);
// },
// onError: (err) => {
// const message =
// err instanceof Error ? err.message : 'An unexpected error occurred.';
// toast.error(message);
// // setIsPaymentOpen(false);
// },
// });
const handleSubmit = ({ document_id }: { document_id: number }) => {
if (document_id === 0) {
toast.error('Id not found');
return;
}
payment.mutate({ order_id: document_id });
};
// const handleSubmit = ({ document_id }: { document_id: number }) => {
// if (document_id === 0) {
// toast.error('Id not found');
// return;
// }
// payment.mutate({ order_id: document_id });
// };
return (
<>
@@ -116,7 +116,7 @@ export function PaymentsTable() {
</thead>
<tbody className="divide-y divide-slate-50">
{data.map((row) => {
const service_fee = row.total_price + row.discount;
// const service_fee = row.total_price + row.discount;
return (
<tr
key={row.id}
@@ -145,14 +145,7 @@ export function PaymentsTable() {
</td>
<td className="px-5 py-3.5">
{row.state ? (
<span
onClick={() => {
if (row.state === 'unpaid') {
setIsPaymentOpen(true);
}
}}
className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-emerald-600 bg-emerald-50"
>
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs font-medium text-emerald-600 bg-emerald-50">
<PaymentStatus status={row.state} />
</span>
) : (
@@ -162,7 +155,7 @@ export function PaymentsTable() {
</span>
)}
</td>
<PaymentModal
{/* <PaymentModal
isOpen={isPaymentOpen}
onClose={() => setIsPaymentOpen(false)}
price={{
@@ -174,7 +167,7 @@ export function PaymentsTable() {
handleSubmit({ document_id: 0 });
}}
isLoading={payment.isPending}
/>
/> */}
</tr>
);
})}

View File

@@ -10,7 +10,7 @@ import PaymentStatus from './paidStatus';
import Sertifikat from '@/features/modals/sertificateModal/sertifikat';
// ── Types ────────────────────────────────────────────────────────────────────
const baseUrl = 'https://dev-api.anti-plagiat.uz/api/v1';
const baseUrl = 'https://api.anti-plagiat.uz/api/v1';
interface AnalyzeText {
[key: string]: number | string;
}
@@ -399,10 +399,25 @@ export default function DocumentDetailPage({ id }: { id: number }) {
<PaymentStatus status={doc.state} />
<Sertifikat document_id={Number(id)} />
{doc.file && (
<a
href={`${baseUrl}${doc.file}`}
target="_blank"
rel="noopener noreferrer"
<button
onClick={async () => {
const url = `${baseUrl}/shared/documents/${doc.id}/download`;
const res = await apiRequest<ArrayBuffer>(
'GET',
url,
undefined,
{ responseType: 'arraybuffer', baseURL: baseUrl },
);
const blob = new Blob([res.data], {
type: 'application/pdf',
});
const objectUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = objectUrl;
a.download = `document-${id}.pdf`;
a.click();
setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
}}
className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-slate-900 text-white text-xs font-semibold hover:bg-slate-700 transition-colors"
>
<svg
@@ -419,7 +434,7 @@ export default function DocumentDetailPage({ id }: { id: number }) {
/>
</svg>
{t('downloadPdf')}
</a>
</button>
)}
</div>
</div>
@@ -486,7 +501,7 @@ export default function DocumentDetailPage({ id }: { id: number }) {
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm p-8">
<div className="flex flex-wrap justify-around gap-8">
<ScoreRing
value={res.ai}
value={res.originality}
label={t('scoreOriginality')}
color="#10b981"
/>
@@ -502,7 +517,7 @@ export default function DocumentDetailPage({ id }: { id: number }) {
color="#6366f1"
/>
<ScoreRing
value={res.originality}
value={res.ai}
label={t('scoreAiContent')}
color="#ef4444"
/>

View File

@@ -10,6 +10,7 @@ import { apiRequest } from '@/shared/request/apiRequest';
import { links } from '@/shared/request/links';
import { toast } from 'react-toastify';
import { PaymentModal } from '@/features/modals/paymentModal/ui/Paymentmodal';
import { PLAGIAT_SERVICE_FEE, SERTIFICATE_PRICE } from '@/shared/lib/metadata';
// ─── State badge ───────────────────────────────────────────────────────────────
@@ -48,7 +49,7 @@ export const HistoryTableRow: React.FC<
const payment = useMutation({
mutationKey: ['payment', item.order_id],
mutationFn: ({ order_id }: { order_id: number }) =>
apiRequest<{ payment_link: string }>('POST', links.payment(order_id)),
apiRequest<{ payment_link: string }>('POST', links.demo_pay(order_id)),
onSuccess: (res) => {
window.open(res.data.payment_link, '_self');
setIsPaymentOpen(false);
@@ -60,8 +61,9 @@ export const HistoryTableRow: React.FC<
});
const price = item.price_calculation ?? {
service_fee: 41200,
service_fee: item.state === 'unpaid' ? PLAGIAT_SERVICE_FEE : 0,
discount: 0,
certificate: item.certificate ? SERTIFICATE_PRICE : 0,
total_price: 41200,
currency: 'UZS',
};
@@ -142,6 +144,7 @@ export const HistoryTableRow: React.FC<
payment.mutate({ order_id: Number(item.order_id) })
}
isLoading={payment.isPending}
hasSertificate={item.certificate}
/>
</>
);

View File

@@ -1,26 +1,5 @@
import { MenuItem } from './model';
import { LanguageRoutes } from '@/shared/config/i18n/types';
const getMenu = (t: (key: string) => string): MenuItem[] => [
{ title: t('aboutSite'), url: '/about' },
// {
// title: 'Products',
// url: '#',
// items: [
// {
// title: 'Blog',
// description: 'The latest industry news, updates, and info',
// icon: Book,
// url: '#',
// },
// ],
// },
{
title: t('contact'),
url: '/contact',
},
];
const languages: { name: string; key: LanguageRoutes }[] = [
{
name: "O'zbekcha",
@@ -36,4 +15,4 @@ const languages: { name: string; key: LanguageRoutes }[] = [
},
];
export { getMenu, languages };
export { languages };

View File

@@ -4,4 +4,5 @@ export interface MenuItem {
description?: string;
icon?: React.ComponentType<{ className?: string }>;
items?: MenuItem[];
key: string;
}

View File

@@ -1,3 +1,5 @@
'use client';
import { usePathname } from 'next/navigation';
import { MenuItem } from '../lib/model';
const SubMenuLink = ({
@@ -7,11 +9,17 @@ const SubMenuLink = ({
item: MenuItem;
logOut?: () => void;
}) => {
const pathname = usePathname();
const isCabinet = pathname.includes('/cabinet');
return (
<a
className="flex flex-row gap-4 rounded-md p-3 leading-none no-underline transition-colors outline-none select-none hover:bg-muted hover:text-accent-foreground"
href={item.url}
onClick={() => {
href={isCabinet && item.url === '/cabinet' ? undefined : item.url}
onClick={(e) => {
if (isCabinet && item.url === '/cabinet') {
e.preventDefault();
}
if (logOut) {
logOut();
}

View File

@@ -2,37 +2,70 @@
import { Link } from '@/shared/config/i18n/navigation';
import { Button } from '@/shared/ui/button';
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from '@/shared/ui/navigation-menu';
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/shared/ui/dropdown-menu';
import SubMenuLink from './SubMenuLink';
import { ChangeLang } from './ChangeLang';
import { useLoginModal, useRegisterModal } from '@/shared/zustand/auth';
import { useTranslations } from 'next-intl';
import { useUserPlagiatStore } from '@/shared/zustand/user';
import { LogOut, User } from 'lucide-react';
import {
ChevronDown,
LogOut,
User,
LayoutDashboard,
FileSearch,
BrainCircuit,
CreditCard,
} from 'lucide-react';
import { useEffect, useState } from 'react';
import { useCabinetNav } from '@/shared/zustand/cabinetNav';
function AuthButtons() {
const t = useTranslations('Navbar');
const t_cab = useTranslations('Cabinet');
const setNavItem = useCabinetNav((state) => state.setNavItem);
const [localUser, setLocalUser] = useState<{
id: number;
name: string;
surname: string;
} | null>(null);
const [open, setOpen] = useState(false);
const auth = {
login: { title: t('login'), url: '#' },
signup: { title: t('signup'), url: '#' },
};
const userItem = [
{ title: t('profile'), url: '/cabinet', icon: User },
{ title: t('logout'), url: '/', icon: LogOut },
{ title: t('profile'), url: '/cabinet', icon: User, key: 'profile' },
{
url: '/cabinet',
title: t_cab('dashboard'),
icon: LayoutDashboard,
key: 'dashboard',
},
{
url: '/cabinet',
title: t_cab('plagiat'),
icon: FileSearch,
key: 'plagiat',
},
{
url: '/cabinet',
title: t_cab('siNav'),
icon: BrainCircuit,
key: 'si',
},
{
url: '/cabinet',
title: t_cab('payments'),
icon: CreditCard,
key: 'payments',
},
{ title: t('logout'), url: '/', icon: LogOut, key: 'logout' },
];
const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal);
@@ -51,7 +84,6 @@ function AuthButtons() {
useEffect(() => {
const data = localStorage.getItem('user');
if (data) {
setLocalUser(JSON.parse(data));
} else {
@@ -65,33 +97,31 @@ function AuthButtons() {
<div className="sm:flex hidden">
<ChangeLang />
</div>
<NavigationMenu viewport={true}>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger className="text-lg">
{localUser.name}
</NavigationMenuTrigger>
<NavigationMenuContent className="bg-popover text-popover-foreground">
{userItem.map((subItem) => (
<NavigationMenuLink
asChild
key={subItem.title}
className="w-80"
>
<SubMenuLink
logOut={() => {
if (subItem.url !== '/cabinet') {
clearTokens();
}
}}
item={subItem}
/>
</NavigationMenuLink>
))}
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger className="inline-flex items-center gap-1 text-lg font-medium outline-none">
{localUser.name}
<ChevronDown className="size-4" />
</DropdownMenuTrigger>
<DropdownMenuContent className="">
{userItem.map((subItem) => (
<DropdownMenuItem key={subItem.title} asChild>
<SubMenuLink
logOut={() => {
setOpen(false);
if (subItem.url !== '/cabinet') {
clearTokens();
} else {
setNavItem(
subItem.key as import('@/widgets/cabinet/lib/types').CabinetSection,
);
}
}}
item={subItem}
/>
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
);
}

View File

@@ -1,4 +1,3 @@
import { Accordion } from '@/shared/ui/accordion';
import { Button } from '@/shared/ui/button';
import {
Sheet,
@@ -8,8 +7,6 @@ import {
SheetTrigger,
} from '@/shared/ui/sheet';
import { Menu } from 'lucide-react';
import { getMenu } from '../lib/data';
import RenderMobileMenuItem from './RenderMobileMenuItem';
import { ChangeLang } from './ChangeLang';
import Link from 'next/link';
import { AuthButtons } from './authButtons';
@@ -19,7 +16,6 @@ import Image from 'next/image';
const Navbar = () => {
const t = useTranslations('Navbar');
const menu = getMenu(t);
return (
<section className="py-1 flex items-center justify-center w-full ">
@@ -72,13 +68,6 @@ const Navbar = () => {
</SheetTitle>
</SheetHeader>
<div className="flex flex-col gap-6 p-4">
<Accordion
type="single"
collapsible
className="flex w-full flex-col gap-4"
>
{menu.map((item) => RenderMobileMenuItem(item))}
</Accordion>
<AuthButtons />
</div>
</SheetContent>

View File

@@ -13,6 +13,8 @@ import { useMutation } from '@tanstack/react-query';
import { links } from '@/shared/request/links';
import { apiRequest } from '@/shared/request/apiRequest';
import { PriceCalculate } from '@/features/modals/paymentModal/lib/types';
import { SERTIFICATE_PRICE, PLAGIAT_SERVICE_FEE } from '@/shared/lib/metadata';
// import { fromTheme } from 'tailwind-merge';
// ─── Initial States ──────────────────────────────────────────────────────────
@@ -25,7 +27,8 @@ const INITIAL_FORM: PlagiarismFormState = {
};
const PRICE: PriceCalculate = {
service_fee: 0,
service_fee: PLAGIAT_SERVICE_FEE,
certificate: SERTIFICATE_PRICE,
discount: 0,
total_price: 0,
};
@@ -71,8 +74,8 @@ export function usePlagiarismForm() {
const priceInfo: PriceCalculate = {
total_price: resdata?.total_price || 0,
discount: resdata?.discount || 0,
certificate: resdata?.certificate || 0,
service_fee: resdata?.service_fee || 0,
certificate: form.certificate ? SERTIFICATE_PRICE : 0,
service_fee: PLAGIAT_SERVICE_FEE,
};
setPrices(priceInfo);
console.log('order_id:', resdata.id);

View File

@@ -209,6 +209,7 @@ export function PlagiarismCheckForm() {
price={prices}
onConfirmPayment={handleSubmit}
isLoading={isLoading}
hasSertificate={!!form.certificate}
/>
</>
);