diff --git a/package.json b/package.json
index 13aa12f..36187c4 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"@radix-ui/react-toast": "^1.2.11",
"@radix-ui/react-tooltip": "^1.2.6",
"@reduxjs/toolkit": "^2.7.0",
+ "@taylordb/query-builder": "^0.10.1",
"aos": "^2.3.4",
"axios": "^1.9.0",
"class-variance-authority": "^0.7.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eb1dd52..e6613b2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -53,6 +53,9 @@ importers:
'@reduxjs/toolkit':
specifier: ^2.7.0
version: 2.7.0(react-redux@9.2.0(@types/react@19.1.2)(react@19.1.0)(redux@5.0.1))(react@19.1.0)
+ '@taylordb/query-builder':
+ specifier: ^0.10.1
+ version: 0.10.1
aos:
specifier: ^2.3.4
version: 2.3.4
@@ -1089,6 +1092,9 @@ packages:
'@rushstack/eslint-patch@1.11.0':
resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==}
+ '@socket.io/component-emitter@3.1.2':
+ resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
+
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
@@ -1189,6 +1195,12 @@ packages:
'@tailwindcss/postcss@4.1.4':
resolution: {integrity: sha512-bjV6sqycCEa+AQSt2Kr7wpGF1bOZJ5wsqnLEkqSbM/JEHxx/yhMH8wHmdkPyApF9xhHeMSwnnkDUUMMM/hYnXw==}
+ '@taylordb/query-builder@0.10.1':
+ resolution: {integrity: sha512-WUyohbO8R+xFC+t+zfTP5VSLakGlBu2gsdWbFWwru4KqLNFW/NCsIvSDhzNObVbtbSgvkf+oVC0li+/z9uZYig==}
+
+ '@taylordb/shared@0.4.4':
+ resolution: {integrity: sha512-Xykr4I26JapNLePkapBGjz15t9Ep1iLs30VbfCcc2z30x8Qy/2tm+sSa5LcacCP2EaxNVDp2UuYKhZ7kOWBLBQ==}
+
'@trivago/prettier-plugin-sort-imports@5.2.2':
resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==}
engines: {node: '>18.12'}
@@ -1589,6 +1601,15 @@ packages:
supports-color:
optional: true
+ debug@4.3.7:
+ resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@4.4.0:
resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
engines: {node: '>=6.0'}
@@ -1653,6 +1674,13 @@ packages:
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ engine.io-client@6.6.3:
+ resolution: {integrity: sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==}
+
+ engine.io-parser@5.2.3:
+ resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
+ engines: {node: '>=10.0.0'}
+
enhanced-resolve@5.18.1:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'}
@@ -1836,6 +1864,9 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ eventemitter3@5.0.1:
+ resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
@@ -1847,6 +1878,9 @@ packages:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
+ fast-json-patch@3.1.1:
+ resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==}
+
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
@@ -2685,6 +2719,14 @@ packages:
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+ socket.io-client@4.8.1:
+ resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io-parser@4.2.4:
+ resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==}
+ engines: {node: '>=10.0.0'}
+
sonner@2.0.3:
resolution: {integrity: sha512-njQ4Hht92m0sMqqHVDL32V2Oun9W1+PHO9NDv9FHfJjT3JT22IG4Jpo3FPQy+mouRKCXFWO+r67v6MrHX2zeIA==}
peerDependencies:
@@ -2896,6 +2938,22 @@ packages:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ ws@8.17.1:
+ resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xmlhttprequest-ssl@2.1.2:
+ resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==}
+ engines: {node: '>=0.4.0'}
+
yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
@@ -2903,6 +2961,9 @@ packages:
zod@3.24.3:
resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
+ zod@4.2.1:
+ resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==}
+
snapshots:
'@alloc/quick-lru@5.2.0': {}
@@ -3744,6 +3805,8 @@ snapshots:
'@rushstack/eslint-patch@1.11.0': {}
+ '@socket.io/component-emitter@3.1.2': {}
+
'@standard-schema/spec@1.0.0': {}
'@standard-schema/utils@0.3.0': {}
@@ -3820,6 +3883,24 @@ snapshots:
postcss: 8.5.3
tailwindcss: 4.1.4
+ '@taylordb/query-builder@0.10.1':
+ dependencies:
+ '@taylordb/shared': 0.4.4
+ eventemitter3: 5.0.1
+ fast-json-patch: 3.1.1
+ json-to-graphql-query: 2.3.0
+ lodash: 4.17.21
+ socket.io-client: 4.8.1
+ zod: 4.2.1
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ '@taylordb/shared@0.4.4':
+ dependencies:
+ lodash: 4.17.21
+
'@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.5.3)':
dependencies:
'@babel/generator': 7.27.0
@@ -4246,6 +4327,10 @@ snapshots:
dependencies:
ms: 2.1.3
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
debug@4.4.0:
dependencies:
ms: 2.1.3
@@ -4302,6 +4387,20 @@ snapshots:
emoji-regex@9.2.2: {}
+ engine.io-client@6.6.3:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ engine.io-parser: 5.2.3
+ ws: 8.17.1
+ xmlhttprequest-ssl: 2.1.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ engine.io-parser@5.2.3: {}
+
enhanced-resolve@5.18.1:
dependencies:
graceful-fs: 4.2.11
@@ -4641,6 +4740,8 @@ snapshots:
esutils@2.0.3: {}
+ eventemitter3@5.0.1: {}
+
fast-deep-equal@3.1.3: {}
fast-glob@3.3.1:
@@ -4659,6 +4760,8 @@ snapshots:
merge2: 1.4.1
micromatch: 4.0.8
+ fast-json-patch@3.1.1: {}
+
fast-json-stable-stringify@2.1.0: {}
fast-levenshtein@2.0.6: {}
@@ -5455,6 +5558,24 @@ snapshots:
is-arrayish: 0.3.2
optional: true
+ socket.io-client@4.8.1:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ engine.io-client: 6.6.3
+ socket.io-parser: 4.2.4
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-parser@4.2.4:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ transitivePeerDependencies:
+ - supports-color
+
sonner@2.0.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
react: 19.1.0
@@ -5720,6 +5841,12 @@ snapshots:
word-wrap@1.2.5: {}
+ ws@8.17.1: {}
+
+ xmlhttprequest-ssl@2.1.2: {}
+
yocto-queue@0.1.0: {}
zod@3.24.3: {}
+
+ zod@4.2.1: {}
diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx
index 608ce4d..d1bc22d 100644
--- a/src/app/about/page.tsx
+++ b/src/app/about/page.tsx
@@ -1,20 +1,15 @@
import AboutPage from '@/pages-templates/about';
-import { mainPageApi } from '@/features/pages/api/pages.api';
-
-import { makeStore } from '@/shared/store';
+import { fetchAboutUsPageContent } from '@/features/pages/services/pages.service';
export const metadata = {
- title: "О нас",
- description: "Узнайте больше о нашей компании, истории и ценностях. Качественное топливо и отличный сервис.",
+ title: 'О нас',
+ description:
+ 'Узнайте больше о нашей компании, истории и ценностях. Качественное топливо и отличный сервис.',
};
export default async function About() {
- const store = makeStore();
-
- const { data } = await store.dispatch(
- mainPageApi.endpoints.fetchAboutUsPageContent.initiate(),
- );
+ const data = await fetchAboutUsPageContent();
if (!data) return null;
diff --git a/src/app/api-utlities/presenters/taylor-presenters.ts b/src/app/api-utlities/presenters/taylor-presenters.ts
new file mode 100644
index 0000000..54926fc
--- /dev/null
+++ b/src/app/api-utlities/presenters/taylor-presenters.ts
@@ -0,0 +1,238 @@
+import { isEmpty } from 'lodash';
+
+import {
+ AttachmentColumnValue,
+ TableRaws,
+} from '@/shared/types/database.types';
+
+// Helper to get image URL from Attachment array
+export const getAttachmentUrl = (
+ attachments: AttachmentColumnValue[] | undefined | null,
+): string | null => {
+ if (isEmpty(attachments) || !attachments?.[0]) return null;
+ const attachment = attachments[0];
+ return `${process.env.TAYLOR_MEDIA_URL}/${attachment.url}`;
+};
+
+// Helper to get link select name (link to selectTable returns object with name)
+export const getLinkSelectName = (
+ link: { name: string } | undefined | null,
+): string | null => {
+ return link?.name || null;
+};
+
+// Helper to get multiple link select names (for arrays of links)
+export const getLinkSelectNames = (
+ links: Array<{ name: string }> | undefined | null,
+): string[] => {
+ if (!links || isEmpty(links)) return [];
+ return links.map((link) => link.name);
+};
+
+// Presenters for TaylorDB query builder results (direct array format, no wrapper)
+
+export const presentPartnersFromTaylor = (
+ partners: TableRaws<'partnyory'>[],
+): Array<{ id: number; name: string; poster: string | null }> => {
+ return partners.map((partner, index) => ({
+ id: index + 1,
+ name: partner.nazvanie || '',
+ poster: getAttachmentUrl(partner.izobrozhenie),
+ }));
+};
+
+export const presentJobsFromTaylor = (
+ jobs: TableRaws<'vakansii'>[],
+): Array<{
+ id: number;
+ name: string;
+ tags: string[];
+ location: string | null;
+ type: string | null;
+}> => {
+ return jobs.map((job, index) => ({
+ id: index + 1,
+ name: job.zagolovok || '',
+ // tegi is a LinkColumnType, so it returns objects when loaded with .with()
+ tags: Array.isArray(job.tegi)
+ ? (job.tegi as Array<{ name: string }>).map((tag) => tag.name)
+ : [],
+ // tip and lokaciya are SingleSelectColumnType, which return arrays of strings
+ location: job.lokaciya?.[0] || null,
+ type: job.tip?.[0] || null,
+ }));
+};
+
+export const presentDiscountsFromTaylor = (
+ discounts: TableRaws<'akcii'>[],
+): Array<{
+ id: number;
+ name: string;
+ description: string;
+ expiresAt: string;
+ image: string | null;
+}> => {
+ return discounts.map((discount, index) => ({
+ id: index + 1,
+ name: discount.zagolovok || '',
+ description: discount.opisanie || '',
+ expiresAt: discount.do || '',
+ image: getAttachmentUrl(discount.foto),
+ }));
+};
+
+export const presentStationsFromTaylor = (
+ stations: TableRaws<'azs'>[],
+): Array<{
+ id: number;
+ name: string;
+ description: string;
+ address: string;
+ workingHours: string | null;
+ latitude: number;
+ longitude: number;
+ carWash: boolean;
+ ai92: boolean;
+ ai95: boolean;
+ dt: boolean;
+ z100: boolean;
+ propan: boolean;
+ electricCharge: boolean;
+ miniMarket: boolean;
+ toilet: boolean;
+ region: string | null;
+ image: string | null;
+}> => {
+ return stations.map((station, index) => ({
+ id: index + 1,
+ name: station.imya || '',
+ description: station.opisanie || '',
+ address: station.adress || '',
+ // chasyRaboty and region are SingleSelectColumnType, which return arrays of strings
+ workingHours: station.chasyRaboty?.[0] || null,
+ // Parse string coordinates to numbers
+ latitude: parseFloat(station.lat || '0') || 0,
+ longitude: parseFloat(station.long || '0') || 0,
+ carWash: station.avtomojka || false,
+ ai92: station.ai92 || false,
+ ai95: station.ai95 || false,
+ dt: station.dt || false,
+ z100: station.z100 || false,
+ propan: station.propan || false,
+ electricCharge: station.zaryadnayaStanciya || false,
+ miniMarket: station.miniMarket || false,
+ toilet: station.tualet || false,
+ region: station.region?.[0] || null,
+ image: getAttachmentUrl(station.foto),
+ }));
+};
+
+export const presentTeamMembersFromTaylor = (
+ members: TableRaws<'komanda'>[],
+): Array<{
+ name: string;
+ photo: string | null;
+ profession: string;
+}> => {
+ return members.map((member) => ({
+ name: member.polnoeImya || '',
+ photo: getAttachmentUrl(member.foto),
+ profession: member.zvanie || '',
+ }));
+};
+
+export const presentHistoryItemsFromTaylor = (
+ historyItems: TableRaws<'istoriyaKompanii'>[],
+): Array<{
+ name: string;
+ year: string;
+ description: string;
+}> => {
+ return historyItems.map((item) => ({
+ name: item.zagolovok || '',
+ year: String(item.god || ''),
+ description: item.opisanie || '',
+ }));
+};
+
+export const presentReviewsFromTaylor = (
+ reviews: TableRaws<'otzyvy'>[],
+): Array<{
+ id: number;
+ fullname: string;
+ review: string;
+ rating: number;
+}> => {
+ return reviews.map((review) => ({
+ id: review.id || 0,
+ fullname: review.polnoeImya || '',
+ review: review.otzyv || '',
+ rating: review.rejting || 0,
+ }));
+};
+
+export const presentCharitiesFromTaylor = (
+ charities: TableRaws<'blagotvoritelnyjFond'>[],
+): Array<{
+ id: number;
+ name: string;
+ description: string;
+ date: string;
+ location: string;
+ image: string | null;
+}> => {
+ return charities.map((charity, index) => ({
+ id: index + 1,
+ name: charity.zagolovok || '',
+ description: charity.opisanie || '',
+ date: charity.data || '',
+ location: charity.lokaciya || '',
+ image: getAttachmentUrl(charity.foto),
+ }));
+};
+
+export const presentCertificatesFromTaylor = (
+ certificates: TableRaws<'sertifikaty'>[],
+): Array<{
+ id: number;
+ name: string;
+ description: string;
+ issuedAt: string;
+ validUntil: string;
+ image: string | null;
+}> => {
+ return certificates.map((certificate, index) => ({
+ id: index + 1,
+ name: certificate.nazvanie || '',
+ description: certificate.opisanie || '',
+ issuedAt: certificate.dataVydachi || '',
+ validUntil: certificate.dejstvitelenDo || '',
+ image: getAttachmentUrl(certificate.foto),
+ }));
+};
+
+export const presentTextsFromTaylor = (
+ texts: TableRaws<'tekstovyjKontentSajta'>[],
+): Array<{
+ key: string;
+ value: string | null;
+}> => {
+ return texts.map((item) => ({
+ key: item.klyuchNeIzmenyat || '',
+ value: item.znachenie || null,
+ }));
+};
+
+export const presentMediaFromTaylor = (
+ media: TableRaws<'mediaKontentSajta'>[],
+): Array<{
+ key: string;
+ name: string;
+ photo: string | null;
+}> => {
+ return media.map((record) => ({
+ key: record.klyuchNeIzmenyat || '',
+ name: record.mestopolozheniya || '',
+ photo: getAttachmentUrl(record.foto),
+ }));
+};
diff --git a/src/app/api-utlities/requests/about-us-page.request copy.ts b/src/app/api-utlities/requests/about-us-page.request copy.ts
deleted file mode 100644
index ee16f00..0000000
--- a/src/app/api-utlities/requests/about-us-page.request copy.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import {
- historyRequest,
- reviewsRequest,
- stationsWithImageRequest,
- teamRequest,
-} from './common';
-
-export const aboutUsPageRequest = {
- ...teamRequest,
- ...historyRequest,
- ...stationsWithImageRequest,
- ...reviewsRequest,
-};
diff --git a/src/app/api-utlities/requests/certificates-page.request.ts b/src/app/api-utlities/requests/certificates-page.request.ts
deleted file mode 100644
index f69d4e3..0000000
--- a/src/app/api-utlities/requests/certificates-page.request.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { certificatesRequest } from './common';
-
-export const certificatesPageRequest = {
- ...certificatesRequest,
-};
diff --git a/src/app/api-utlities/requests/charity-page.request copy.ts b/src/app/api-utlities/requests/charity-page.request copy.ts
deleted file mode 100644
index 9e005de..0000000
--- a/src/app/api-utlities/requests/charity-page.request copy.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import { charityRequest } from './common';
-
-export const charityPageRequest = {
- ...charityRequest,
-};
diff --git a/src/app/api-utlities/requests/main-page.request.ts b/src/app/api-utlities/requests/main-page.request.ts
deleted file mode 100644
index aa7770b..0000000
--- a/src/app/api-utlities/requests/main-page.request.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import {
- discountsRequest,
- jobsRequest,
- partnersRequest,
- stationsRequest,
-} from './common';
-
-export const mainPageRequest = {
- ...partnersRequest,
- ...jobsRequest,
- ...discountsRequest,
- ...stationsRequest,
-};
diff --git a/src/app/charity/page.tsx b/src/app/charity/page.tsx
index 9559d4c..947b972 100644
--- a/src/app/charity/page.tsx
+++ b/src/app/charity/page.tsx
@@ -1,8 +1,6 @@
import { CharityPage } from '@/pages-templates/charity';
-import { mainPageApi } from '@/features/pages/api/pages.api';
-
-import { makeStore } from '@/shared/store';
+import { fetchCharityPageContent } from '@/features/pages/services/pages.service';
export const metadata = {
title: 'Благотворительность',
@@ -11,13 +9,9 @@ export const metadata = {
};
export default async function Charity() {
- const store = makeStore();
+ const data = await fetchCharityPageContent();
- const { data, isLoading, error } = await store.dispatch(
- mainPageApi.endpoints.fetchCharityPageContent.initiate(),
- );
-
- if (isLoading || !data) return null;
+ if (!data) return null;
return ;
}
diff --git a/src/app/clients/certificates/page.tsx b/src/app/clients/certificates/page.tsx
index bb64e97..f1f6cb8 100644
--- a/src/app/clients/certificates/page.tsx
+++ b/src/app/clients/certificates/page.tsx
@@ -1,8 +1,6 @@
import { CertificatesPage } from '@/pages-templates/clients/certificates';
-import { mainPageApi } from '@/features/pages/api/pages.api';
-
-import { makeStore } from '@/shared/store';
+import { fetchCertificatesPageContent } from '@/features/pages/services/pages.service';
export const metadata = {
title: 'Сертификаты',
@@ -11,13 +9,9 @@ export const metadata = {
};
export default async function Certificates() {
- const store = makeStore();
+ const data = await fetchCertificatesPageContent();
- const { data, isLoading, error } = await store.dispatch(
- mainPageApi.endpoints.fetchCertificatesPageContent.initiate(),
- );
-
- if (isLoading || !data) return null;
+ if (!data) return null;
return ;
}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 7134cb9..56f43d7 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,10 +1,12 @@
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
-import { textControlApi } from '@/shared/language/api/text-control.api';
-import { mediaControlApi } from '@/shared/media/api/media-control.api';
+import {
+ fetchMediaContent,
+ fetchTextContent,
+} from '@/features/pages/services/pages.service';
+
import { Providers } from '@/shared/providers/providers';
-import { makeStore } from '@/shared/store';
import { MediaItem } from '@/shared/types/media.type';
import { TextItem } from '@/shared/types/text.types';
@@ -29,17 +31,11 @@ export default async function RootLayout({
}: Readonly<{
children: React.ReactNode;
}>) {
- const store = makeStore();
-
- // Запрос текстов
- const textResponse = await store.dispatch(
- textControlApi.endpoints.fetchText.initiate(),
- );
-
- // Запрос медиа
- const mediaResponse = await store.dispatch(
- mediaControlApi.endpoints.fetchMedia.initiate(),
- );
+ // Fetch texts and media using TaylorDB query builder
+ const [textItems, mediaItems] = await Promise.all([
+ fetchTextContent(),
+ fetchMediaContent(),
+ ]);
return (
{children}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a340dee..617e021 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,6 +1,4 @@
-import { mainPageApi } from '@/features/pages/api/pages.api';
-
-import { makeStore } from '@/shared/store';
+import { fetchMainPageContent } from '@/features/pages/services/pages.service';
import { AboutSection } from '@/widgets/about-section';
import { CharitySection } from '@/widgets/charity-section';
@@ -13,13 +11,9 @@ import { StatsSection } from '@/widgets/stats-section';
import { VacanciesSection } from '@/widgets/vacancies-section';
export default async function Home() {
- const store = makeStore();
+ const data = await fetchMainPageContent();
- const { data, isLoading, error } = await store.dispatch(
- mainPageApi.endpoints.fetchMainPageContent.initiate(),
- );
-
- if (isLoading || !data) return null;
+ if (!data) return null;
return (
diff --git a/src/features/pages/api/pages.api.ts b/src/features/pages/api/pages.api.ts
deleted file mode 100644
index bc68c99..0000000
--- a/src/features/pages/api/pages.api.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-import { jsonToGraphQLQuery } from 'json-to-graphql-query';
-
-import {
- AboutUsPageData,
- CertificatesPageData,
- CharityPageData,
- MainPageData,
-} from '@/app/api-utlities/@types/pages';
-import {
- presentCertificates,
- presentCharities,
- presentDiscounts,
- presentHistoryItems,
- presentJobs,
- presentPartners,
- presentReviews,
- presentStations,
- presentTeamMembers,
-} from '@/app/api-utlities/presenters';
-import { aboutUsPageRequest } from '@/app/api-utlities/requests/about-us-page.request copy';
-import { certificatesPageRequest } from '@/app/api-utlities/requests/certificates-page.request';
-import { charityPageRequest } from '@/app/api-utlities/requests/charity-page.request copy';
-import { mainPageRequest } from '@/app/api-utlities/requests/main-page.request';
-
-import { taylorAPI } from '@/shared/api/taylor-api';
-
-export const mainPageApi = taylorAPI.injectEndpoints({
- endpoints: (builder) => ({
- fetchMainPageContent: builder.query({
- query: () => ({
- url: '',
- method: 'POST',
- body: {
- query: jsonToGraphQLQuery({ query: mainPageRequest }),
- },
- }),
-
- transformResponse: (response: any) => {
- return {
- partners: presentPartners(response.data.partnyory),
- jobs: presentJobs(response.data.vakansii),
- discounts: presentDiscounts(response.data.akcii),
- stations: presentStations(response.data.azs),
- };
- },
- }),
-
- fetchAboutUsPageContent: builder.query({
- query: () => ({
- url: '',
- method: 'POST',
- body: {
- query: jsonToGraphQLQuery({ query: aboutUsPageRequest }),
- },
- }),
-
- transformResponse: (response: any) => {
- return {
- team: presentTeamMembers(response.data.komanda),
- history: presentHistoryItems(response.data.istoriyaKompanii),
- stations: presentStations(response.data.azs),
- reviews: presentReviews(response.data.otzyvy),
- };
- },
- }),
-
- fetchCharityPageContent: builder.query({
- query: () => ({
- url: '',
- method: 'POST',
- body: {
- query: jsonToGraphQLQuery({ query: charityPageRequest }),
- },
- }),
-
- transformResponse: (response: any) => {
- return {
- charities: presentCharities(response.data.blagotvoritelnyjFond),
- };
- },
- }),
-
- fetchCertificatesPageContent: builder.query({
- query: () => ({
- url: '',
- method: 'POST',
- body: {
- query: jsonToGraphQLQuery({ query: certificatesPageRequest }),
- },
- }),
-
- transformResponse: (response: any) => {
- return {
- certificates: presentCertificates(response.data.sertifikaty),
- };
- },
- }),
- }),
-});
diff --git a/src/features/pages/services/pages.service.ts b/src/features/pages/services/pages.service.ts
new file mode 100644
index 0000000..240d87c
--- /dev/null
+++ b/src/features/pages/services/pages.service.ts
@@ -0,0 +1,182 @@
+import {
+ AboutUsPageData,
+ CertificatesPageData,
+ CharityPageData,
+ MainPageData,
+} from '@/app/api-utlities/@types/pages';
+import {
+ presentCertificatesFromTaylor,
+ presentCharitiesFromTaylor,
+ presentDiscountsFromTaylor,
+ presentHistoryItemsFromTaylor,
+ presentJobsFromTaylor,
+ presentMediaFromTaylor,
+ presentPartnersFromTaylor,
+ presentReviewsFromTaylor,
+ presentStationsFromTaylor,
+ presentTeamMembersFromTaylor,
+ presentTextsFromTaylor,
+} from '@/app/api-utlities/presenters/taylor-presenters';
+
+import { taylorQueryBuilder } from '@/shared/api/taylor-query-builder';
+
+/**
+ * Fetches main page content using TaylorDB query builder
+ * Replaces the RTK Query GraphQL approach with type-safe query builder
+ */
+export async function fetchMainPageContent(): Promise {
+ // Use batch queries to fetch all data in a single request
+ const [partnersData, jobsData, discountsData, stationsData] =
+ await taylorQueryBuilder
+ .batch([
+ // Fetch partners
+ taylorQueryBuilder
+ .selectFrom('partnyory')
+ .selectAll()
+ .with({
+ izobrozhenie: (qb) => qb.selectAll(),
+ }),
+
+ // Fetch jobs
+ taylorQueryBuilder
+ .selectFrom('vakansii')
+ .selectAll()
+ .with({
+ tegi: (qb) => qb.select(['name']),
+ }),
+
+ // Fetch discounts
+ taylorQueryBuilder
+ .selectFrom('akcii')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ }),
+
+ // Fetch stations
+ taylorQueryBuilder
+ .selectFrom('azs')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ }),
+ ])
+ .execute();
+
+ // Transform the data using TaylorDB-specific presenters
+ // The query builder returns arrays directly
+ return {
+ partners: presentPartnersFromTaylor(partnersData),
+ jobs: presentJobsFromTaylor(jobsData),
+ discounts: presentDiscountsFromTaylor(discountsData),
+ stations: presentStationsFromTaylor(stationsData),
+ };
+}
+
+/**
+ * Fetches about us page content using TaylorDB query builder
+ */
+export async function fetchAboutUsPageContent(): Promise {
+ // Use batch queries to fetch all data in a single request
+ const [teamData, historyData, stationsData, reviewsData] =
+ await taylorQueryBuilder
+ .batch([
+ // Fetch team members
+ taylorQueryBuilder
+ .selectFrom('komanda')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ }),
+
+ // Fetch history items
+ taylorQueryBuilder.selectFrom('istoriyaKompanii').selectAll(),
+
+ // Fetch stations
+ taylorQueryBuilder
+ .selectFrom('azs')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ }),
+
+ // Fetch reviews (filtered by published status)
+ taylorQueryBuilder
+ .selectFrom('otzyvy')
+ .selectAll()
+ .where('status', '=', 'Опубликовано'),
+ ])
+ .execute();
+
+ return {
+ team: presentTeamMembersFromTaylor(teamData),
+ history: presentHistoryItemsFromTaylor(historyData),
+ stations: presentStationsFromTaylor(stationsData),
+ reviews: presentReviewsFromTaylor(reviewsData),
+ };
+}
+
+/**
+ * Fetches charity page content using TaylorDB query builder
+ */
+export async function fetchCharityPageContent(): Promise {
+ const charitiesData = await taylorQueryBuilder
+ .selectFrom('blagotvoritelnyjFond')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ })
+ .execute();
+
+ return {
+ charities: presentCharitiesFromTaylor(charitiesData),
+ };
+}
+
+/**
+ * Fetches certificates page content using TaylorDB query builder
+ */
+export async function fetchCertificatesPageContent(): Promise {
+ const certificatesData = await taylorQueryBuilder
+ .selectFrom('sertifikaty')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ })
+ .execute();
+
+ return {
+ certificates: presentCertificatesFromTaylor(certificatesData),
+ };
+}
+
+/**
+ * Fetches text content using TaylorDB query builder
+ */
+export async function fetchTextContent(): Promise<
+ Array<{ key: string; value: string | null }>
+> {
+ const textsData = await taylorQueryBuilder
+ .selectFrom('tekstovyjKontentSajta')
+ .selectAll()
+ .execute();
+
+ return presentTextsFromTaylor(textsData);
+}
+
+/**
+ * Fetches media content using TaylorDB query builder
+ */
+export async function fetchMediaContent(): Promise<
+ Array<{ key: string; name: string; photo: string | null }>
+> {
+ const mediaData = await taylorQueryBuilder
+ .selectFrom('mediaKontentSajta')
+ .selectAll()
+ .with({
+ foto: (qb) => qb.selectAll(),
+ })
+ .execute();
+
+ return presentMediaFromTaylor(mediaData);
+}
diff --git a/src/shared/api/taylor-query-builder.ts b/src/shared/api/taylor-query-builder.ts
new file mode 100644
index 0000000..8731f02
--- /dev/null
+++ b/src/shared/api/taylor-query-builder.ts
@@ -0,0 +1,13 @@
+import { createQueryBuilder } from '@taylordb/query-builder';
+
+import { TaylorDatabase } from '../types/database.types';
+
+// Initialize TaylorDB query builder instance
+// Note: If you have generated types from taylor.types.ts, you can import them here
+// import { TaylorDatabase } from '@/path/to/taylor.types';
+
+export const taylorQueryBuilder = createQueryBuilder({
+ baseId: process.env.TAYLOR_BASE_ID || '',
+ baseUrl: process.env.TAYLOR_API_ENDPOINT || '',
+ apiKey: process.env.TAYLOR_API_TOKEN || '',
+});
diff --git a/src/shared/language/api/text-control.api.ts b/src/shared/language/api/text-control.api.ts
deleted file mode 100644
index 495780d..0000000
--- a/src/shared/language/api/text-control.api.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { jsonToGraphQLQuery } from 'json-to-graphql-query';
-
-import { presentTexts } from '@/app/api-utlities/presenters';
-import { textsRequest } from '@/app/api-utlities/requests/common';
-
-import { taylorAPI } from '@/shared/api/taylor-api';
-import { TextItem } from '@/shared/types/text.types';
-
-export const textControlApi = taylorAPI.injectEndpoints({
- endpoints: (builder) => ({
- fetchText: builder.query({
- query: () => ({
- url: '',
- method: 'POST',
- body: {
- query: jsonToGraphQLQuery({ query: textsRequest }),
- },
- }),
-
- transformResponse: (response: any) => {
- return presentTexts(response.data.tekstovyjKontentSajta);
- },
- }),
- }),
-});
diff --git a/src/shared/types/database.types.ts b/src/shared/types/database.types.ts
new file mode 100644
index 0000000..0d0fc13
--- /dev/null
+++ b/src/shared/types/database.types.ts
@@ -0,0 +1,548 @@
+/**
+ * Copyright (c) 2025 TaylorDB
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+interface FileInformation {
+ fieldname: string;
+ originalname: string;
+ encoding: string;
+ mimetype: string;
+ destination: string;
+ filename: string;
+ path: string;
+ size: number;
+ format: string;
+ width: number;
+ height: number;
+}
+
+interface UploadResponse {
+ collectionName: string;
+ fileInformation: FileInformation;
+ metadata: {
+ thumbnails: any[];
+ clips: any[];
+ };
+ baseId: string;
+ storageAdaptor: string;
+ _id: string;
+ __v: number;
+}
+
+export interface AttachmentColumnValue {
+ url: string;
+ fileType: string;
+ size: number;
+}
+
+export class Attachment {
+ public readonly collectionName: string;
+ public readonly fileInformation: FileInformation;
+ public readonly metadata: { thumbnails: any[]; clips: any[] };
+ public readonly baseId: string;
+ public readonly storageAdaptor: string;
+ public readonly _id: string;
+
+ constructor(data: UploadResponse) {
+ this.collectionName = data.collectionName;
+ this.fileInformation = data.fileInformation;
+ this.metadata = data.metadata;
+ this.baseId = data.baseId;
+ this.storageAdaptor = data.storageAdaptor;
+ this._id = data._id;
+ }
+
+ toColumnValue(): AttachmentColumnValue {
+ return {
+ url: this.fileInformation.path,
+ fileType: this.fileInformation.mimetype,
+ size: this.fileInformation.size,
+ };
+ }
+}
+
+type IsWithinOperatorValue =
+ | 'pastWeek'
+ | 'pastMonth'
+ | 'pastYear'
+ | 'nextWeek'
+ | 'nextMonth'
+ | 'nextYear'
+ | 'daysFromNow'
+ | 'daysAgo'
+ | 'currentWeek'
+ | 'currentMonth'
+ | 'currentYear';
+
+type DefaultDateFilterValue =
+ | (
+ | 'today'
+ | 'tomorrow'
+ | 'yesterday'
+ | 'oneWeekAgo'
+ | 'oneWeekFromNow'
+ | 'oneMonthAgo'
+ | 'oneMonthFromNow'
+ )
+ | ['exactDay' | 'exactTimestamp', string]
+ | ['daysAgo' | 'daysFromNow', number];
+
+type DateFilters = {
+ '=': DefaultDateFilterValue;
+ '!=': DefaultDateFilterValue;
+ '<': DefaultDateFilterValue;
+ '>': DefaultDateFilterValue;
+ '<=': DefaultDateFilterValue;
+ '>=': DefaultDateFilterValue;
+ isWithIn:
+ | IsWithinOperatorValue
+ | { value: 'daysAgo' | 'daysFromNow'; date: number };
+ isEmpty: boolean;
+ isNotEmpty: boolean;
+};
+
+type DateAggregations = {
+ empty: number;
+ filled: number;
+ unique: number;
+ percentEmpty: number;
+ percentFilled: number;
+ percentUnique: number;
+ min: number | null;
+ max: number | null;
+ daysRange: number | null;
+ monthRange: number | null;
+};
+
+type TextFilters = {
+ '=': string;
+ '!=': string;
+ caseEqual: string;
+ hasAnyOf: string[];
+ contains: string;
+ startsWith: string;
+ endsWith: string;
+ doesNotContain: string;
+ isEmpty: never;
+ isNotEmpty: never;
+};
+
+type LinkFilters = {
+ hasAnyOf: number[];
+ hasAllOf: number[];
+ isExactly: number[];
+ '=': number;
+ hasNoneOf: number[];
+ contains: string;
+ doesNotContain: string;
+ isEmpty: never;
+ isNotEmpty: never;
+};
+
+type SelectFilters = {
+ hasAnyOf: O[number][];
+ hasAllOf: O[number][];
+ isExactly: O[number][];
+ '=': O[number];
+ hasNoneOf: O[number][];
+ contains: string;
+ doesNotContain: string;
+ isEmpty: never;
+ isNotEmpty: never;
+};
+
+type LinkAggregations = {
+ empty: number;
+ filled: number;
+ percentEmpty: number;
+ percentFilled: number;
+};
+
+type NumberFilters = {
+ '=': number;
+ '!=': number;
+ '>': number;
+ '>=': number;
+ '<': number;
+ '<=': number;
+ hasAnyOf: number[];
+ hasNoneOf: number[];
+ isEmpty: never;
+ isNotEmpty: never;
+};
+
+type NumberAggregations = {
+ sum: number;
+ average: number;
+ median: number;
+ min: number | null;
+ max: number | null;
+ range: number;
+ standardDeviation: number;
+ histogram: Record;
+ empty: number;
+ filled: number;
+ unique: number;
+ percentEmpty: number;
+ percentFilled: number;
+ percentUnique: number;
+};
+
+type CheckboxFilters = {
+ '=': number;
+};
+
+/**
+ *
+ * Column types
+ *
+ */
+export type ColumnType<
+ S,
+ U,
+ I,
+ R extends boolean,
+ F extends { [key: string]: any } = object,
+ A extends { [key: string]: any } = object,
+> = {
+ raw: S;
+ insert: I;
+ update: U;
+ filters: F;
+ aggregations: A;
+ isRequired: R;
+};
+
+export type DateColumnType = ColumnType<
+ string,
+ string,
+ string,
+ R,
+ DateFilters,
+ DateAggregations
+>;
+
+export type TextColumnType = ColumnType<
+ string,
+ string,
+ string,
+ R,
+ TextFilters
+>;
+
+export type ALinkColumnType<
+ T extends string,
+ S,
+ U,
+ I,
+ R extends boolean,
+ F extends { [key: string]: any } = LinkFilters,
+ A extends LinkAggregations = LinkAggregations,
+> = ColumnType & {
+ linkedTo: T;
+};
+
+export type LinkColumnType<
+ T extends string,
+ R extends boolean,
+> = ALinkColumnType<
+ T,
+ object,
+ number | number[] | { newIds: number[]; deletedIds: number[] },
+ number | number[],
+ R
+>;
+
+export type AttachmentColumnType = ALinkColumnType<
+ 'attachmentTable',
+ AttachmentColumnValue[],
+ Attachment[] | { newIds: number[]; deletedIds: number[] } | number[],
+ Attachment[] | number[],
+ R
+>;
+
+export type NumberColumnType = ColumnType<
+ number,
+ number,
+ number,
+ R,
+ NumberFilters,
+ NumberAggregations
+>;
+
+export type CheckboxColumnType = ColumnType<
+ boolean,
+ boolean,
+ boolean,
+ R,
+ CheckboxFilters
+>;
+
+export type AutoGeneratedNumberColumnType = ColumnType<
+ number,
+ never,
+ never,
+ false,
+ NumberFilters,
+ NumberAggregations
+>;
+
+export type AutoGeneratedDateColumnType = ColumnType<
+ string,
+ never,
+ never,
+ false,
+ DateFilters,
+ DateAggregations
+>;
+
+export type SingleSelectColumnType<
+ O extends readonly string[],
+ R extends boolean,
+> = ALinkColumnType<
+ 'selectTable',
+ O[number],
+ O[number] | O[number][],
+ O[number] | O[number][],
+ R,
+ SelectFilters
+>;
+
+export type TableRaws = {
+ [K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
+ infer S,
+ any,
+ any,
+ infer R,
+ any,
+ any
+ >
+ ? R extends true
+ ? S
+ : S | undefined
+ : never;
+};
+
+export type TableInserts = {
+ [K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
+ any,
+ infer I,
+ any,
+ infer R,
+ any,
+ any
+ >
+ ? R extends true
+ ? I
+ : I | undefined
+ : never;
+};
+
+export type TableUpdates = {
+ [K in keyof TaylorDatabase[T]]: TaylorDatabase[T][K] extends ColumnType<
+ any,
+ any,
+ infer U,
+ any,
+ any,
+ any
+ >
+ ? U
+ : never;
+};
+
+export type SelectTable = {
+ id: AutoGeneratedNumberColumnType;
+ name: TextColumnType;
+ color: TextColumnType;
+};
+
+export type AttachmentTable = {
+ id: AutoGeneratedNumberColumnType;
+ name: TextColumnType;
+ metadata: TextColumnType;
+ size: NumberColumnType;
+ fileType: TextColumnType;
+ url: TextColumnType;
+};
+
+export type CollaboratorsTable = {
+ id: AutoGeneratedNumberColumnType;
+ name: TextColumnType;
+ emailAddress: TextColumnType;
+ avatar: TextColumnType;
+};
+
+export type TaylorDatabase = {
+ /**
+ *
+ *
+ * Internal tables, these tables can not be queried directly.
+ *
+ */
+ selectTable: SelectTable;
+ attachmentTable: AttachmentTable;
+ collaboratorsTable: CollaboratorsTable;
+ vakansii: VakansiiTable;
+ partnyory: PartnyoryTable;
+ azs: AzsTable;
+ akcii: AkciiTable;
+ istoriyaKompanii: IstoriyaKompaniiTable;
+ komanda: KomandaTable;
+ otzyvy: OtzyvyTable;
+ tekstovyjKontentSajta: TekstovyjKontentSajtaTable;
+ sertifikaty: SertifikatyTable;
+ mediaKontentSajta: MediaKontentSajtaTable;
+ blagotvoritelnyjFond: BlagotvoritelnyjFondTable;
+};
+
+export const VakansiiTipOptions = ['Офис', 'Заправки'] as const;
+export const VakansiiLokaciyaOptions = ['Душанбе'] as const;
+
+type VakansiiTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ zagolovok: TextColumnType;
+ tip: SingleSelectColumnType;
+ lokaciya: SingleSelectColumnType;
+ tegi: LinkColumnType<'selectTable', false>;
+};
+type PartnyoryTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ nazvanie: TextColumnType;
+ izobrozhenie: AttachmentColumnType;
+};
+
+export const AzsChasyRabotyOptions = ['Круглосуточно'] as const;
+export const AzsRegionOptions = [
+ 'Душанбе',
+ 'Бохтар',
+ 'Худжанд',
+ 'Регар',
+ 'Вахдат',
+ 'А.Джоми',
+ 'Обикиик',
+ 'Кулоб',
+ 'Дахана',
+ 'Ёвон',
+ 'Панч',
+ 'Исфара',
+ 'Мастчох',
+ 'Хисор',
+] as const;
+
+type AzsTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ imya: TextColumnType;
+ adress: TextColumnType;
+ opisanie: TextColumnType;
+ chasyRaboty: SingleSelectColumnType;
+ lat: TextColumnType;
+ long: TextColumnType;
+ avtomojka: CheckboxColumnType;
+ dt: CheckboxColumnType;
+ ai92: CheckboxColumnType;
+ ai95: CheckboxColumnType;
+ z100: CheckboxColumnType;
+ propan: CheckboxColumnType;
+ zaryadnayaStanciya: CheckboxColumnType;
+ miniMarket: CheckboxColumnType;
+ tualet: CheckboxColumnType;
+ region: SingleSelectColumnType;
+ foto: AttachmentColumnType;
+};
+type AkciiTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ zagolovok: TextColumnType;
+ opisanie: TextColumnType;
+ do: DateColumnType;
+ foto: AttachmentColumnType;
+};
+type IstoriyaKompaniiTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ zagolovok: TextColumnType;
+ god: NumberColumnType;
+ opisanie: TextColumnType;
+};
+type KomandaTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ polnoeImya: TextColumnType;
+ foto: AttachmentColumnType;
+ zvanie: TextColumnType;
+};
+
+export const OtzyvyStatusOptions = ['Опубликовано'] as const;
+
+type OtzyvyTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ polnoeImya: TextColumnType;
+ otzyv: TextColumnType;
+ rejting: NumberColumnType;
+ status: SingleSelectColumnType;
+};
+type TekstovyjKontentSajtaTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ klyuchNeIzmenyat: TextColumnType;
+ znachenie: TextColumnType;
+ opisanie: LinkColumnType<'selectTable', false>;
+};
+type SertifikatyTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ nazvanie: TextColumnType;
+ opisanie: TextColumnType;
+ dataVydachi: DateColumnType;
+ dejstvitelenDo: DateColumnType;
+ foto: AttachmentColumnType;
+};
+
+export const MediaKontentSajtaStranicaOptions = [
+ 'Главная',
+ 'О нас',
+ 'Благотворительность',
+ 'Общая',
+ 'Клиенты',
+ 'Программа лояльности',
+] as const;
+
+type MediaKontentSajtaTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ mestopolozheniya: TextColumnType;
+ klyuchNeIzmenyat: TextColumnType;
+ foto: AttachmentColumnType;
+ stranica: SingleSelectColumnType<
+ typeof MediaKontentSajtaStranicaOptions,
+ false
+ >;
+};
+type BlagotvoritelnyjFondTable = {
+ id: NumberColumnType;
+ createdAt: AutoGeneratedDateColumnType;
+ updatedAt: AutoGeneratedDateColumnType;
+ zagolovok: TextColumnType;
+ opisanie: TextColumnType;
+ data: DateColumnType;
+ lokaciya: TextColumnType;
+ foto: AttachmentColumnType;
+};