@@ -1,7 +1,7 @@ import axios from 'axios' import { Template } from '#/domains/copywrite/proxy/types/template' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { Message } from '#/shared/lib/types/model' export class CopywriteProxy { @@ -12,21 +12,21 @@ export class CopywriteProxy { } static async getGeneration(token?: string): Promise { - const { data } = await axios.get(API_URL + '/copywrite/', { + const { data } = await axios.get(getApiUrl() + '/copywrite/', { headers: { Authorization: `Bearer ${token}` }, }) return data } static async getTemplates(token?: string): Promise { - const { data } = await axios.get(API_URL + '/copywrite/templates/', { + const { data } = await axios.get(getApiUrl() + '/copywrite/templates/', { headers: { Authorization: `Bearer ${token}` }, }) return data } static async createTemplates(token?: string): Promise { - const { data } = await axios.post(API_URL + '/copywrite/templates/', { + const { data } = await axios.post(getApiUrl() + '/copywrite/templates/', { headers: { Authorization: `Bearer ${token}` }, }) return data @@ -1,11 +1,11 @@ import axios from 'axios' import { IShortModel } from '#/entities/model-entity' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export async function getAudio(token?: string): Promise { try { - const { data } = await axios.get(API_URL + '/ml_models/?category=audio', { + const { data } = await axios.get(getApiUrl() + '/ml_models/?category=audio', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,10 +1,10 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getBalance = async (token: string): Promise => { try { - const { data } = await axios.get<{ current_token_balance: number }>(API_URL + '/payments/user-balance', { + const { data } = await axios.get<{ current_token_balance: number }>(getApiUrl() + '/payments/user-balance', { headers: { Authorization: `Bearer ${token}`, }, @@ -2,14 +2,14 @@ import axios from 'axios' import { Message, MessageSend } from '../types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export async function sendMediaMessage(model: string | null, modelType: 'video' | 'image' | 'audio', dataForSend: MessageSend | FormData, token?: string) { const HeaderDataType = dataForSend instanceof FormData ? 'multipart/form-data' : 'application/json' - return await axios.post(API_URL + `/media/${modelType}/${model}`, dataForSend, { + return await axios.post(getApiUrl() + `/media/${modelType}/${model}`, dataForSend, { withCredentials: true, validateStatus: (status) => status < 500, headers: { @@ -20,7 +20,7 @@ export async function sendMediaMessage(model: string | null, modelType: 'vide } export async function getImagesBySlug(slug: string, token: string, type:'image' | 'video' | 'audio', offset?: number, limit = 10) { - return await axios.get(API_URL + `/media/${type}/${slug}?limit=${limit}&offset=${offset}`, { + return await axios.get(getApiUrl() + `/media/${type}/${slug}?limit=${limit}&offset=${offset}`, { validateStatus: (status) => status < 500, headers: { Authorization: `Bearer ${token}`, @@ -2,10 +2,10 @@ import axios from 'axios' import { IModel } from '../types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export async function getBotParams(slug: string, token?: string) { - return await axios.get(API_URL + `/ml_models/${slug}`, { + return await axios.get(getApiUrl() + `/ml_models/${slug}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -2,10 +2,10 @@ import axios from 'axios' import { IShortModel } from '../types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export async function getModelsImages(token?: string) { - return await axios.get(API_URL + '/ml_models/?category=images', { + return await axios.get(getApiUrl() + '/ml_models/?category=images', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,6 +1,6 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { IUserSetting } from '../model/types' @@ -9,7 +9,7 @@ export const addUserSettings = async ( setting: Omit ): Promise => { try { - const { data } = await axios.post(API_URL + '/api/users/settings/', setting, { + const { data } = await axios.post(getApiUrl() + '/api/users/settings/', setting, { headers: { Authorization: `Bearer ${token}`, }, @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { AccountType } from '../model/types' export const getAccountType = async (token: string | null | undefined): Promise => { @@ -10,7 +10,7 @@ export const getAccountType = async (token: string | null | undefined): Promise< try { const { data } = await axios.get>( - API_URL + '/auth/account-type', + getApiUrl() + '/auth/account-type', { headers: { Authorization: `Bearer ${token}`, @@ -1,12 +1,12 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { IUserSetting } from '../model/types' export const getUserSettings = async (token: string): Promise => { try { - const { data } = await axios.get(API_URL + '/api/users/settings/', { + const { data } = await axios.get(getApiUrl() + '/api/users/settings/', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,5 +1,4 @@ import { api } from '#/shared/api' -import { API_URL } from '#/shared/lib/constants' import { Agent } from 'https' import { IUserSetting } from '../model/types' @@ -1,6 +1,6 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { getUpdatedSettingsLocal } from '../lib/helpers/update-setting-local' import { IUserSetting, SettingValueType } from '../model/types' @@ -13,7 +13,7 @@ export const updateUserSettings = async ( ) => { try { const { data } = await axios.put( - API_URL + `/api/users/settings/${id}`, + getApiUrl() + `/api/users/settings/${id}`, { value: value }, { headers: { @@ -1,9 +1,8 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit' -import { createAction } from '@reduxjs/toolkit/src' import axios, { AxiosResponse } from 'axios' import { loadingThunk } from '#/app/store/store' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' type UserState = { status: loadingThunk @@ -91,7 +90,7 @@ const initialState: UserState & ResponseAllInfo = { } export const getAll = async (token: string | null | undefined): Promise => { - const { data } = await axios.get>(API_URL + '/auth/me', { + const { data } = await axios.get>(getApiUrl() + '/auth/me', { headers: { Authorization: `Bearer ${token}`, }, @@ -106,7 +105,7 @@ export const getAllInfo = createAsyncThunk('user/getAllInfo', async (token: stri }) export const unfollowEmail = createAsyncThunk('user/unfollowEmail', async (token: string | null | undefined) => { - await axios.patch(API_URL + '/auth/email-sub', {}, { headers: { Authorization: `Bearer ${token}` } }) + await axios.patch(getApiUrl() + '/auth/email-sub', {}, { headers: { Authorization: `Bearer ${token}` } }) }) export const userSlice = createSlice({ @@ -119,39 +118,9 @@ export const userSlice = createSlice({ }, extraReducers: (builder) => { builder.addCase(getAllInfo.fulfilled, (state, action) => { + Object.assign(state, action.payload) state.status = 'succeeded' state.referral = '' - const { - uid, - is_subscribed_to_emails, - email, - account_type, - first_name, - last_name, - profile_picture_link, - is_active, - is_staff, - created_at, - payment_plan, - is_confirmed, - is_social, - referral_code, - show_balance, - } = action.payload - state.is_subscribed_to_emails = is_subscribed_to_emails - state.account_type = account_type - state.email = email - state.payment_plan = payment_plan - state.is_confirmed = is_confirmed - state.first_name = first_name - state.last_name = last_name - state.profile_picture_link = profile_picture_link - state.is_active = is_active - state.is_staff = is_staff - state.created_at = created_at - state.is_social = is_social - state.referral_code = referral_code - state.show_balance = show_balance }) builder.addCase(getAllInfo.pending, (state) => { state.status = 'pending' @@ -159,7 +128,7 @@ export const userSlice = createSlice({ builder.addCase(getAllInfo.rejected, (state) => { state.status = 'failed' }) - builder.addCase(unfollowEmail.fulfilled, (state, action) => { + builder.addCase(unfollowEmail.fulfilled, (state) => { state.is_subscribed_to_emails = !state.is_subscribed_to_emails }) }, @@ -7,7 +7,6 @@ import { useSession } from 'next-auth/react' import { ButtonGray, ButtonUI, Error, InputStyleDark, Loader, Modal } from '#/shared' import { accountApi } from '#/shared/api/account-endpoints' -import { API_URL } from '#/shared/lib/constants' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' import { DateInput } from '#/shared/ui/date-input/date-input' @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { ResponseGetBusinessGroups, ResponseGetPersons } from '../model/types' @@ -15,7 +15,7 @@ export const addBusinessGroup = async ( { uid: string; title: string; token_limit: string }, AxiosResponse >( - API_URL + '/auth/business-groups/', + getApiUrl() + '/auth/business-groups/', { title: title, token_limit: token_limit, @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { ResponseGetBusinessGroups, ResponseGetPersons } from '../model/types' @@ -10,7 +10,7 @@ export const addBusinessGroupUser = async ( token?: string ): Promise => { try { - const { data } = await axios.post(API_URL + `/auth/business-groups/${group_id}/accounts/${email}/`, { + const { data } = await axios.post(getApiUrl() + `/auth/business-groups/${group_id}/accounts/${email}/`, { headers: { Authorization: `Bearer ${token}`, }, @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { ResponseGetBusinessGroups } from '../model/types' @@ -12,7 +12,7 @@ export const changeBusinessGroup = async ( ): Promise => { try { const { data } = await axios.put( - API_URL + `/auth/business-groups/${group_id}/`, + getApiUrl() + `/auth/business-groups/${group_id}/`, { title: title, token_limit: token_limit, @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { ResponseGetBusinessGroups, ResponseGetPersons } from '../model/types' @@ -10,7 +10,7 @@ export const deleteBusinessGroupUser = async ( token?: string ): Promise => { try { - const { data } = await axios.delete(API_URL + `/auth/business-groups/${group_id}/accounts/${email}/`, { + const { data } = await axios.delete(getApiUrl() + `/auth/business-groups/${group_id}/accounts/${email}/`, { headers: { Authorization: `Bearer ${token}`, }, @@ -1,13 +1,13 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { ResponseGetBusinessGroups } from '../model/types' export const getBusinessGroup = async (group_id: string, token?: string): Promise => { try { const { data } = await axios.get( - API_URL + `/auth/business-groups/${group_id}/`, + getApiUrl() + `/auth/business-groups/${group_id}/`, { headers: { Authorization: `Bearer ${token}`, @@ -14,7 +14,7 @@ import { ResponseGetBusinessGroups } from '#/features/business-group/model/types import { ResponseGetPersons } from '#/features/invite-person-in-business' import { IEmailForms } from '#/features/register-by-email/model/types' import { ButtonGray, ButtonUI, Error, InputStyleDark, Loader, Modal, ModalProps } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import styles from './add-business-group.module.scss' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' @@ -50,7 +50,7 @@ export const ChangeBusinessGroup: FC = ({ open, onClose, compa }, [current_group, session?.access]) useEffect(() => { - axios.get(API_URL + '/auth/business-host/accounts?have_group=false', { + axios.get(getApiUrl() + '/auth/business-host/accounts?have_group=false', { headers: { Authorization: `Bearer ${session?.access}` }, }).then((res) => { setAddUsers(res.data) @@ -1,11 +1,11 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const downloadFileReq = async (start_date: string, end_date: string, token?: string): Promise => { try { const { data } = await axios.get( - API_URL + `/auth/business-security/download-report?end_date=${end_date}&start_date=${end_date}`, + getApiUrl() + `/auth/business-security/download-report?end_date=${end_date}&start_date=${end_date}`, { headers: { Authorization: `Bearer ${token}`, @@ -6,7 +6,7 @@ import { useRouter } from 'next/navigation' import { useSession } from 'next-auth/react' import { ButtonGray, ButtonUI, Error, Loader, Modal } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { DateInput } from '#/shared/ui/date-input/date-input' import styles from './invite-modal.module.scss' @@ -22,7 +22,7 @@ export const DownloadModal = ({ open, setOpen }: { open: boolean; setOpen: React const downloadFile = () => { setIsLoading(true) axios.get( - API_URL + + getApiUrl() + `/auth/business-security/download-report?${startDate ? `start_date=${startDate}` : ''}${endDate ? `&end_date=${endDate}` : ''}`, { responseType: 'arraybuffer', @@ -1,14 +1,14 @@ import axios, { AxiosResponse } from 'axios' import { ResponseGetPersons } from '#/features/invite-person-in-business' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { InviteRoles, inviteRoles } from '../../invite-person-in-business/lib/constants' export const updateLimit = async (email?: string, limit?: string, token?: string, role?: InviteRoles) => { try { const { data } = await axios.put<{ token_limit: string; role: string }, AxiosResponse>( - API_URL + `/auth/business-host/accounts/${email}`, + getApiUrl() + `/auth/business-host/accounts/${email}`, { token_limit: limit, account_privileges: Object.entries(inviteRoles).find(([key, value]) => value === role)![0], @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { AllowedModels } from './types' export const changeAccess = async ( @@ -11,7 +11,7 @@ export const changeAccess = async ( if (!value) { try { const { data } = await axios.put<{ models: string }, AxiosResponse>( - API_URL + '/auth/business-host/allowed-models', + getApiUrl() + '/auth/business-host/allowed-models', { models: [title], }, @@ -30,7 +30,7 @@ export const changeAccess = async ( if (value) { try { const { data } = await axios.delete<{ models: string }, AxiosResponse>( - API_URL + '/auth/business-host/allowed-models', + getApiUrl() + '/auth/business-host/allowed-models', { headers: { Authorization: `Bearer ${token}`, @@ -3,7 +3,7 @@ import axios from 'axios' import { RootState } from '#/app/store/store' import { api, createChat as createChatApi, getAllChats } from '#/shared/api/endpoints' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { Chat } from './types' @@ -46,7 +46,7 @@ export const createChatForModel = createAsyncThunk( 'chats/deleteByUid', async ({ uid, token }) => { - await axios.delete(API_URL + `/chats/${uid}/`, { + await axios.delete(getApiUrl() + `/chats/${uid}/`, { headers: { Authorization: `Bearer ${token}` }, }) return uid @@ -3,7 +3,7 @@ import axios, { AxiosResponse } from 'axios' import { Dayjs } from 'dayjs' import { RequestStats, ResponseStats } from '#/features/get-admin-stats' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' async function getStats( token: string | null | undefined, @@ -32,7 +32,7 @@ async function getStats( try { const { data } = await axios.get>( - API_URL + '/admin/stats' + queryParams, + getApiUrl() + '/admin/stats' + queryParams, { headers: { Authorization: `Bearer ${token}`, @@ -1,6 +1,6 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { InviteRoles, inviteRoles } from '../lib/constants' import { ResponseGetPersons } from '../model/types' @@ -13,7 +13,7 @@ export const invitePerson = async ( ) => { return await axios.post<{ email: string; token_limit: string }, AxiosResponse>( - API_URL + '/auth/business-host', + getApiUrl() + '/auth/business-host', { group: group === '' ? null : group, email, @@ -10,7 +10,7 @@ import { Frequency, FrequencySelect, } from '#/features/register-business/lib/constants-step-information' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const createAccount = async (information: DataForCreate, token: string | null) => { const indexOfS = Object.values(FrequencySelect).indexOf(information.frequency as unknown as FrequencySelect) @@ -32,7 +32,7 @@ export const createAccount = async (information: DataForCreate, token: string | job_title: information.job_title, } - const res = await axios.post(API_URL + '/auth/business-host/create', data, { + const res = await axios.post(getApiUrl() + '/auth/business-host/create', data, { headers: { Authorization: `Bearer ${token}`, }, @@ -1,13 +1,14 @@ import axios, { AxiosResponse } from 'axios' -import * as process from 'process' +import { getEnv } from '#/shared/lib/env-store' import { DaDataResponse } from './types' -const url = process.env.NEXT_PUBLIC_URL_DADATA as string - -const token = process.env.NEXT_PUBLIC_TOKEN_DADATA export const getCompanyData = async (prompt: any) => { - if (!token) { + const env = getEnv() + const url = env?.NEXT_PUBLIC_URL_DADATA + const token = env?.NEXT_PUBLIC_TOKEN_DADATA + + if (!token || !url) { return null } @@ -16,7 +16,7 @@ import { PasswordOptions } from '#/features/register-by-email/lib/constants' import { IEmailForms } from '#/features/register-by-email/model/types' import { emailOptions } from '#/shared' import { InputStyleDark } from '#/shared' -import { API_URL } from '#/shared/lib/constants/constants' +import { getApiUrl } from '#/shared/lib/constants' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' import { useDeviceType } from '#/shared/lib/hooks/use-device-type' @@ -64,7 +64,7 @@ export const RegisterEmailForm: React.FC = ({ successLo req_data.referer = localStorage.getItem('referral') } - const { status, data: result } = await axios.post(API_URL + '/auth/register', req_data) + const { status, data: result } = await axios.post(getApiUrl() + '/auth/register', req_data) if (status !== 201) { setLoading(false) @@ -1,8 +1,8 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const removePerson = async (person_uid?: string, token?: string) => { - return await axios.delete(API_URL + `/auth/business-host`, { + return await axios.delete(getApiUrl() + `/auth/business-host`, { data: { uid: person_uid, }, @@ -1,9 +1,9 @@ -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import axios from 'axios' export const resendInvation = async (email: string, token?: string) => { return await axios.post( - API_URL + `/auth/business-host/re-invite/${email}`, + getApiUrl() + `/auth/business-host/re-invite/${email}`, {}, { headers: { @@ -3,7 +3,7 @@ import axios from 'axios' import { useSession } from 'next-auth/react' import { dataLine as data } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' type ResponseStats = { source: string; amount: string }[] @@ -28,7 +28,7 @@ const statsColors = [ const getStatistic = async (type: string, interval: string, token?: string) => { return await axios.get( - API_URL + `/payments/expenses?source_strategy=${type}&interval_strategy=${interval}`, + getApiUrl() + `/payments/expenses?source_strategy=${type}&interval_strategy=${interval}`, { headers: { Authorization: `Bearer ${token}` }, validateStatus: () => true, @@ -74,10 +74,7 @@ export const authOptions: NextAuthOptions = { throw new Error('Непредвиденная ошибка') } - const info = await getAll( - (result.data as { access_token: string }).access_token - ) - + const info = await getAll((result.data as { access_token: string }).access_token) return { ...info.token, tokenExpiry: AuthConstants.getExpiresDate() } } @@ -87,12 +84,12 @@ export const authOptions: NextAuthOptions = { token.refresh = user.token.refresh token.tokenExpiry = AuthConstants.getExpiresDate() return token - } catch (error) { + } catch { return { ...token, ...user } } } - const shouldRefreshTime = Math.round(Date.now() - token.tokenExpiry) >= 0 + const shouldRefreshTime = Math.round(Date.now() - (token.tokenExpiry as number)) >= 0 if (shouldRefreshTime) { return await AuthProxy.refreshToken(token) @@ -124,6 +121,7 @@ export const authOptions: NextAuthOptions = { async session({ session, token }) { session.access = token.access session.refresh = token.refresh + session.error = token.error return session }, }, @@ -13,12 +13,10 @@ export abstract class AuthConstants { public static readonly client_secret_yandex = process.env.NEXT_PUBLIC_CLIENT_SECRET_YANDEX - public static readonly sessionTime = Number(process.env.SESSION_TIME) + public static readonly sessionTime = Number(process.env.NEXT_PUBLIC_SESSION_TIME) * 1000 - /* Время в часах через которое обновляется access токен **/ - // private static readonly expiresTime = 0.5 - // private static readonly expiresTime = 0.002778 - private static readonly expiresTime = this.sessionTime * 1000 // 5 минут + + private static readonly expiresTime = this.sessionTime public static readonly getExpiresDate = () => Date.now() + this.expiresTime } @@ -1,36 +1,29 @@ import axios from 'axios' import { JWT } from 'next-auth/jwt' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { AuthConstants } from './constants' export class AuthorizationProxy { public readonly loginByEmail = async (email: string, password: string) => { - return await fetch(API_URL + '/auth/login', { + return await fetch(getApiUrl() + '/auth/login', { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - email, - password, - }), + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ email, password }), }) } public readonly loginByEmailToken = async (emailToken: string) => { - return await fetch(API_URL + `/auth/login-from-token/${emailToken}`, { + return await fetch(getApiUrl() + `/auth/login-from-token/${emailToken}`, { method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, + headers: { 'Content-Type': 'application/json' }, }) } public readonly exchangeTokenYandex = async (yandex_token: string) => { return await axios.post<{ access_token: string } | { error_description: string }>( - API_URL + '/auth/login-social/convert-token', + getApiUrl() + '/auth/login-social/convert-token', { grant_type: 'convert_token', client_id: AuthConstants.django_app_client_id_yandex, @@ -40,10 +33,6 @@ export class AuthorizationProxy { }, { validateStatus: () => true } ) - - // const finalData = await getAll(data.access_token) - - // return finalData.token } public readonly exchangeTokenYandexTest = async (yandex_token: string) => { @@ -60,15 +49,18 @@ export class AuthorizationProxy { public readonly refreshToken = async (tokenObject: JWT): Promise => { try { - const { data } = await axios.post(API_URL + '/auth/token/refresh', { - refresh: tokenObject.refresh, - }) + const { data } = await axios.post<{ access?: string; refresh?: string }>( + getApiUrl() + '/auth/refresh', + { refresh: tokenObject.refresh } + ) return { - access: data.access, - refresh: data.refresh, + ...tokenObject, + access: data.access!, + refresh: data.refresh ?? tokenObject.refresh, tokenExpiry: AuthConstants.getExpiresDate(), + error: undefined, } - } catch (error) { + } catch { return { ...tokenObject, error: 'RefreshAccessTokenError', @@ -0,0 +1,18 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== 'GET') { + return res.status(405).json({ error: 'Method not allowed' }) + } + + const env = Object.entries(process.env) + .filter(([key]) => key.startsWith('NEXT')) + .sort(([a], [b]) => a.localeCompare(b)) + .reduce>((acc, [key, value]) => { + acc[key] = value ?? '' + return acc + }, {}) + + res.status(200).json(env) +} @@ -17,6 +17,7 @@ import { TourManager, getTourSteps, TourCard, setTourCompleted } from '#/feature import { pingFangFont } from '#/shared/lib/constants/font/font' import { getDeviceType } from '#/shared/lib/helpers' import { useBlockTelegram } from '#/shared/lib/hooks/use-block-telegram' +import { useEnv } from '#/shared/lib/hooks/use-env' import { Providers } from '#/widgets/providers' import ErrorBoundary from './error-boundary' @@ -33,6 +34,8 @@ axios.defaults.validateStatus = () => true axios.interceptors.response.use(async (response) => { if (![401, 404, 403].includes(response.status)) return response + if (typeof window === 'undefined') return response + const session = await getSession() if (!session) { @@ -44,7 +47,7 @@ axios.interceptors.response.use(async (response) => { axios.interceptors.response.use( (response) => response, (error) => { - if (!error.response) { + if (!error.response && typeof window !== 'undefined') { window.location.href = '/network-error' } return error @@ -84,7 +87,7 @@ function AppContent({ Component, pageProps }: { Component: NextPageWithLayout; p - + @@ -104,19 +107,21 @@ function AppContent({ Component, pageProps }: { Component: NextPageWithLayout; p function App({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLayout) { useBlockTelegram() + const { env } = useEnv() + + // Fallback на process.env для SSR/prerender — useEnv пустой до fetch + const unleashUrl = env?.NEXT_PUBLIC_UNLEASH_URL || process.env.NEXT_PUBLIC_UNLEASH_URL || '' + const unleashClientKey = env?.NEXT_PUBLIC_UNLEASH_CLIENT_KEY || process.env.NEXT_PUBLIC_UNLEASH_CLIENT_KEY || '' + const unleashAppName = env?.NEXT_PUBLIC_UNLEASH_APP_NAME || process.env.NEXT_PUBLIC_UNLEASH_APP_NAME || '' return ( <> - + @@ -3,12 +3,12 @@ import axios from 'axios' import { VideoLink, VideoModel } from './models' import { IModel,IShortModel } from '#/entities/model-entity' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' const model_api = { async getBots(token?: string): Promise { try { - const { data } = await axios.get(API_URL + '/ml_models/?category=chat-bots', { + const { data } = await axios.get(getApiUrl() + '/ml_models/?category=chat-bots', { headers: { Authorization: `Bearer ${token}`, }, @@ -21,7 +21,7 @@ const model_api = { async getBotParams(slug: string, token?: string): Promise { try { - const { data } = await axios.get(API_URL + `/ml_models/${slug}`, { + const { data } = await axios.get(getApiUrl() + `/ml_models/${slug}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -34,7 +34,7 @@ const model_api = { async getImages(token?: string): Promise { try { - const { data } = await axios.get(API_URL + '/ml_models/?category=images', { + const { data } = await axios.get(getApiUrl() + '/ml_models/?category=images', { headers: { Authorization: `Bearer ${token}`, }, @@ -51,7 +51,7 @@ const videos = { async getVideoLinks(token?: string): Promise { // Получение ссылок на изображения try { - const { data } = await axios.get(API_URL + '/media/video/links/', { + const { data } = await axios.get(getApiUrl() + '/media/video/links/', { headers: { Authorization: `Bearer ${token}`, }, @@ -65,7 +65,7 @@ const videos = { async getVideoModels(token?: string): Promise { // Получение всех моделей видео try { - const { data } = await axios.get(API_URL + '/ml_models/?category=videos', { + const { data } = await axios.get(getApiUrl() + '/ml_models/?category=videos', { headers: { Authorization: `Bearer ${token}`, }, @@ -83,7 +83,7 @@ const videos = { ): Promise { // Отправка сообщения для генерации видео try { - const response = await fetch(API_URL + `/media/video/${slug}`, { + const response = await fetch(getApiUrl() + `/media/video/${slug}`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, @@ -1,12 +1,11 @@ import React, { useCallback, useEffect, useRef, useState } from 'react' import axios, { AxiosError, AxiosResponse } from 'axios' import { useSession } from 'next-auth/react' -import process from 'process' import { useAppDispatch } from '#/app/store/store' import { getUserBalance } from '#/entities/balance' import { Message, MessageSend } from '#/entities/message' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { Variant } from '#/shared/lib/hooks/use-show-data' import { Device } from '#/shared/lib/types/entities' import { IMessageRequest } from '#/shared/lib/types/types-gpt' @@ -24,7 +23,7 @@ const formDataHelper = (file: File, dataForSend: MessageSend): FormData => export const ModelsWithChatsEndpoints = { getData: async (chatUid: string, offset: number, token?: string) => { try { - const { data } = await axios.get(API_URL + `/chats/${chatUid}/messages/?limit=10&offset=${offset}`, { + const { data } = await axios.get(getApiUrl() + `/chats/${chatUid}/messages/?limit=10&offset=${offset}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -42,7 +41,7 @@ export const ModelsWithChatsEndpoints = { const HeaderDataType = dataForSend instanceof FormData ? 'multipart/form-data' : 'application/json' return await axios.post>( - API_URL + `/chats/${chatUid}/messages/`, + getApiUrl() + `/chats/${chatUid}/messages/`, dataForSend, { withCredentials: true, @@ -173,7 +172,7 @@ export function useModel( } const deleteMessage = (message_uid: string) => { - axios.delete(process.env.NEXT_PUBLIC_API_HOST + `/chats/${currentChat}/messages/${message_uid}`, { + axios.delete(getApiUrl() + `/chats/${currentChat}/messages/${message_uid}`, { headers: { Authorization: `Bearer ${data?.access}`, }, @@ -188,7 +187,7 @@ export function useModel( export const ModelsWithImagesEndpoints = { getData: async (type: string, offset: number, token?: string) => { try { - const { data } = await axios.get(API_URL + `/media/image/${type}?limit=10&offset=${offset}`, { + const { data } = await axios.get(getApiUrl() + `/media/image/${type}?limit=10&offset=${offset}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -206,7 +205,7 @@ export const ModelsWithImagesEndpoints = { const HeaderDataType = dataForSend instanceof FormData ? 'multipart/form-data' : 'application/json' try { - const { data } = await axios.post>(API_URL + `/media/image/${type}`, dataForSend, { + const { data } = await axios.post>(getApiUrl() + `/media/image/${type}`, dataForSend, { withCredentials: true, headers: { Authorization: `Bearer ${token}`, @@ -347,7 +346,7 @@ export function useModelImages(showMessage: (message: string) => void, type: export const ModelsMediaApi = { getData: async (type: string, token?: string) => { try { - const { data } = await axios.get(API_URL + `/media/audio/${type}`, { + const { data } = await axios.get(getApiUrl() + `/media/audio/${type}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -363,7 +362,7 @@ export const ModelsMediaApi = { }, sendData: async (type: string | null, dataForSend: MessageSend | FormData, token?: string) => { try { - const { data } = await axios.post>(API_URL + `/media/audio/${type}`, dataForSend, { + const { data } = await axios.post>(getApiUrl() + `/media/audio/${type}`, dataForSend, { withCredentials: true, headers: { Authorization: `Bearer ${token}`, @@ -1,6 +1,6 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export interface PredictPriceRequest { model_slug: string @@ -18,7 +18,7 @@ export async function predictPrice( token?: string ): Promise { const { data: result } = await axios.post( - API_URL + '/ml_model/predict-price/', + getApiUrl() + '/ml_model/predict-price/', data, { headers: { @@ -1,7 +1,7 @@ import axios, { AxiosResponse } from 'axios' import { User } from 'next-auth' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { IOffer } from '#/views/subscription' interface IUserBalance { @@ -25,7 +25,7 @@ interface DataForLogin { export const accountApi = { async getPaymentsPlans(token: string): Promise { try { - const { data } = await axios.get(API_URL + '/payments/plans', { + const { data } = await axios.get(getApiUrl() + '/payments/plans', { headers: { Authorization: `Bearer ${token}`, }, @@ -42,23 +42,26 @@ export const accountApi = { return null } - try { - const { data } = await axios.post>( - API_URL + '/payments/plans', - { - uid: plan, - is_test: 1, + const response = await axios.post>( + getApiUrl() + '/payments/plans', + { + uid: plan, + is_test: 1, + }, + { + headers: { + Authorization: `Bearer ${token}`, }, - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ) - return data.payment_url - } catch (err) { - return null + } + ) + + if (response.status >= 400) { + const error = new Error('Payment failed') as Error & { response: { data: unknown } } + error.response = { data: response.data } + throw error } + + return response.data.payment_url }, async changePassword( @@ -66,10 +69,10 @@ export const accountApi = { password_1: string, password_2: string, current_password: string - ): Promise { - try { - const { status } = await axios.put( - API_URL + '/auth/reset-pass', + ): Promise<{status:number,data:{detail:string}}>{ + + const response= await axios.put( + getApiUrl() + '/auth/reset-pass', { password_1, password_2, @@ -82,14 +85,12 @@ export const accountApi = { } ) - return status - } catch (err) { - return 400 - } + return response + }, async getApiKeys(token: string | null): Promise { - return await axios.get(API_URL + '/public/api-key', { + return await axios.get(getApiUrl() + '/public/api-key', { headers: { Authorization: `Bearer ${token}`, }, @@ -97,7 +98,7 @@ export const accountApi = { }, async createApiKeys(data: any, token: string | null): Promise { - return await axios.post(API_URL + '/public/api-key', data, { + return await axios.post(getApiUrl() + '/public/api-key', data, { headers: { Authorization: `Bearer ${token}`, }, @@ -105,7 +106,7 @@ export const accountApi = { }, async deleteApiKey(name: any, token: string | null): Promise { - return await axios.delete(API_URL + '/public/api-key', { + return await axios.delete(getApiUrl() + '/public/api-key', { data: { name, }, @@ -117,7 +118,7 @@ export const accountApi = { async loginByEmail(email: string, password: string): Promise { try { - const { data } = await axios.post>(API_URL + '/auth/login', { + const { data } = await axios.post>(getApiUrl() + '/auth/login', { email, password, }) @@ -130,7 +131,7 @@ export const accountApi = { async removeSub(token?: string) { try { - const { status } = await axios.delete(API_URL + '/payments/plans', { + const { status } = await axios.delete(getApiUrl() + '/payments/plans', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,6 +1,5 @@ import axios, { AxiosResponse } from 'axios' import { Session } from 'next-auth' -import * as process from 'process' import { Chat } from '#/shared/api/type-model-chats' import { Error } from '#/shared/lib/types/entities' @@ -9,7 +8,7 @@ import { IMessageRequest, ISendMessageResponse } from '#/shared/lib/types/types- import { Message } from '../lib/types/model' -const API_URL = process.env.NEXT_PUBLIC_API_HOST +import { getApiUrl } from '#/shared/lib/constants' type Result = { question: string @@ -61,7 +60,7 @@ export const api = { async getMessagesChatGPT(token: string | null, uid: string): Promise { try { - const { data } = await axios.get(API_URL + `/chats/${uid}/messages/`, { + const { data } = await axios.get(getApiUrl() + `/chats/${uid}/messages/`, { headers: { Authorization: `Bearer ${token}`, }, @@ -79,7 +78,7 @@ export const api = { async updRenameChat(uid: string, title: string, token: string | undefined) { try { const { data } = await axios.put<{ uid: string; title: string; created_at: string }>( - API_URL + `/chats/${uid}/`, + getApiUrl() + `/chats/${uid}/`, { title: title }, { withCredentials: true, @@ -97,7 +96,7 @@ export const api = { async sendMessageChatGPT(token: string, message: any, uid: string): Promise { try { const { data } = await axios.post>( - API_URL + `/chats/${uid}/messages/`, + getApiUrl() + `/chats/${uid}/messages/`, message, { withCredentials: true, @@ -115,7 +114,7 @@ export const api = { async getFavoritesModel(token: string | null, session: Session | null): Promise { try { - const { data } = await axios.get(API_URL + `/ml_models/${session?.user?.name}`, { + const { data } = await axios.get(getApiUrl() + `/ml_models/${session?.user?.name}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -129,7 +128,7 @@ export const api = { async getAllModels(token: string | null): Promise { try { - const { data } = await axios.get(API_URL + '/ml_models/', { + const { data } = await axios.get(getApiUrl() + '/ml_models/', { headers: { Authorization: token ? `Bearer ${token}` : '', }, @@ -146,7 +145,7 @@ export const api = { export const createChat = async (model: string, token?: string) => { try { const { data } = await axios.post( - API_URL + `/chats/?model=${model}`, + getApiUrl() + `/chats/?model=${model}`, { title: 'Новый чат', model, @@ -162,7 +161,7 @@ export const createChat = async (model: string, token?: string) => { export const getAllChats = async (model: string, token?: string): Promise => { try { - const { data } = await axios.get(API_URL + `/chats/?model=${model}`, { + const { data } = await axios.get(getApiUrl() + `/chats/?model=${model}`, { headers: { Authorization: `Bearer ${token}` }, }) @@ -181,7 +180,7 @@ export const getAllChats = async (model: string, token?: string): Promise { try { const { data, status } = await axios.put( - API_URL + '/ml_models/favourites ', + getApiUrl() + '/ml_models/favourites ', { uid: model_id, }, @@ -199,7 +198,7 @@ export const addToFavorites = async (model_id: string, token?: string) => { export const deleteFromFavorites = async (model_id: string, token?: string) => { try { - const { status, data } = await axios.delete(API_URL + '/ml_models/favorites', { + const { status, data } = await axios.delete(getApiUrl() + '/ml_models/favorites', { headers: { Authorization: `Bearer ${token}`, }, @@ -230,7 +229,7 @@ export interface PaymentHistory { export const getPaymentsHistory = async (token?: string) => { try { - const { data } = await axios.get(API_URL + '/payments/history', { + const { data } = await axios.get(getApiUrl() + '/payments/history', { headers: { Authorization: `Bearer ${token}`, }, @@ -256,7 +255,7 @@ export interface IReferral { export const getReferral = async (token?: string) => { try { - const { data } = await axios.get(API_URL + '/payments/referral-account', { + const { data } = await axios.get(getApiUrl() + '/payments/referral-account', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,14 +1,21 @@ import axios from 'axios' +import { getApiUrl } from '#/shared/lib/constants' + export const api = axios.create({ validateStatus: () => true, - baseURL: process.env.NEXT_PUBLIC_API_HOST, +}) + +api.interceptors.request.use((config) => { + const baseURL = getApiUrl() + if (baseURL) config.baseURL = baseURL + return config }) api.interceptors.response.use( (response) => response, (error) => { - if (!error.response) { + if (!error.response && typeof window !== 'undefined') { window.location.href = '/network-error' } return error @@ -1,6 +1,11 @@ import * as process from 'process' -export const API_HOST = process.env.NEXT_PUBLIC_MAIN_URL +import { getEnv } from '#/shared/lib/env-store' + +export const getApiHost = () => + typeof window !== 'undefined' ? (getEnv()?.NEXT_PUBLIC_MAIN_URL ?? '') : (process.env.NEXT_PUBLIC_MAIN_URL ?? '') +export const getApiUrl = () => + typeof window !== 'undefined' ? (getEnv()?.NEXT_PUBLIC_API_HOST ?? '') : (process.env.NEXT_PUBLIC_API_HOST ?? '') export enum ModelPagesList { '/chatgpt', @@ -10,8 +15,6 @@ export enum ModelPagesList { '/kandinsky', } -export const API_URL = process.env.NEXT_PUBLIC_API_HOST - export const surpriseMePrompts = [ "Vintage 90's anime style. stylish model posing in 7/11 convenience store., sci-fi.", @@ -1 +1,6 @@ -export { API_HOST, API_URL, ModelPagesList, surpriseMePrompts } from './constants' +export { + getApiHost, + getApiUrl, + ModelPagesList, + surpriseMePrompts, +} from './constants' @@ -1,3 +1,4 @@ export { useAutoScroll } from './use-auto-scroll' export { useDeviceType } from './use-device-type' +export { useEnv } from './use-env' export { useFeatureFlag } from './use-feature-flag' \ No newline at end of file @@ -0,0 +1,62 @@ +import { useEffect, useState } from 'react' + +import { setEnv } from '#/shared/lib/env-store' + +type EnvRecord = Record + +const CACHE_TTL_MS = 5 * 60 * 1000 // 5 минут + +let cache: EnvRecord | null = null +let cacheTimestamp = 0 +let fetchPromise: Promise | null = null + +function isCacheValid(): boolean { + return cache !== null && Date.now() - cacheTimestamp < CACHE_TTL_MS +} + +function fetchEnv(): Promise { + if (isCacheValid()) return Promise.resolve(cache!) + if (fetchPromise) return fetchPromise + + fetchPromise = fetch('/api/env') + .then((r) => r.json()) + .then((data) => { + cache = data + cacheTimestamp = Date.now() + setEnv(data) + return data + }) + .finally(() => { + fetchPromise = null + }) + + return fetchPromise +} + +export function useEnv(): { env: EnvRecord | null; loading: boolean; error: Error | null } { + const [env, setEnv] = useState(isCacheValid() ? cache : null) + const [loading, setLoading] = useState(!isCacheValid()) + const [error, setError] = useState(null) + + useEffect(() => { + const load = () => { + if (isCacheValid()) { + setEnv(cache) + setLoading(false) + return + } + + fetchEnv() + .then(setEnv) + .catch(setError) + .finally(() => setLoading(false)) + } + + load() + + const interval = setInterval(load, CACHE_TTL_MS) + return () => clearInterval(interval) + }, []) + + return { env, loading, error } +} @@ -13,6 +13,7 @@ declare module 'next-auth' { expires: ISODateString access: string refresh: string + error?: 'RefreshAccessTokenError' } interface User { @@ -30,5 +31,6 @@ declare module 'next-auth/jwt' { access: string refresh: string tokenExpiry: number + error?: 'RefreshAccessTokenError' } } @@ -0,0 +1,11 @@ +export type EnvRecord = Record + +let store: EnvRecord | null = null + +export function getEnv(): EnvRecord | null { + return store +} + +export function setEnv(env: EnvRecord): void { + store = env +} @@ -16,7 +16,7 @@ import { DownloadModal } from '#/features/business-security-download' import { NextPageWithLayout } from '#/pages/_app' import { ButtonUI, Input, Loader, Modal, SwitchCustom } from '#/shared' import { accountApi } from '#/shared/api/account-endpoints' -import { API_URL } from '#/shared/lib/constants/constants' +import { getApiUrl } from '#/shared/lib/constants' import { getDeviceType } from '#/shared/lib/helpers' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' import { ScreenForInactive } from '#/widgets/business' @@ -60,7 +60,7 @@ const Account: NextPageWithLayout = () => { try { setLoading(true) - await axios.put(API_URL + '/auth/reset-profile-pic', formData, { + await axios.put(getApiUrl() + '/auth/reset-profile-pic', formData, { headers: { Authorization: `Bearer ${data?.access}`, 'Content-Type': 'multipart/form-data', @@ -125,7 +125,7 @@ const Account: NextPageWithLayout = () => { } const status = await accountApi.changePassword(data.access, newPassword1, newPassword2, currentPassword) - if (status === 200) { + if (Number(status) === 200) { showMessage('Пароль успешно изменён!') setNewPassword1('') setNewPassword2('') @@ -189,7 +189,7 @@ const Account: NextPageWithLayout = () => { let resStatus = 404 try { const { status } = await axios.post( - API_URL + '/payments/promocode', + getApiUrl() + '/payments/promocode', { code: promocode }, { headers: { Authorization: `Bearer ${data.access}` } } ) @@ -222,7 +222,7 @@ const Account: NextPageWithLayout = () => { try { await axios.put( - API_URL + '/auth/user-data', + getApiUrl() + '/auth/user-data', { email: email, first_name: name, @@ -239,7 +239,7 @@ const Account: NextPageWithLayout = () => { const deleteAccount = async () => { if (!data) return try { - const { status } = await axios.delete(API_URL + '/auth/remove', { + const { status } = await axios.delete(getApiUrl() + '/auth/remove', { headers: { Authorization: `Bearer ${data.access}`, }, @@ -4,7 +4,7 @@ import Image from 'next/image' import { useSession } from 'next-auth/react' import { TooltipCustom } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { InputStyleSmallDark } from '#/shared/ui/input' import axios from 'axios' @@ -58,7 +58,7 @@ export const KeyItem: React.FC = ({ children, limit: initialLimit, return } axios.patch( - API_URL + '/public/api-key', + getApiUrl() + '/public/api-key', { token_limit: limit === '' ? null : Number(limit), name, @@ -1,16 +1,16 @@ -import { API_URL } from "#/shared/lib/constants" -import axios from "axios" +import { getApiUrl } from '#/shared/lib/constants' +import axios from 'axios' -const client_secret = process.env.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_SECRET -const client_id = process.env.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_ID +import { getEnv } from '#/shared/lib/env-store' export async function getTokenByAPIGoogle(token: string) { - const { data } = await axios.post(API_URL + '/auth/login-social/convert-token', { + const env = getEnv() + const { data } = await axios.post(getApiUrl() + '/auth/login-social/convert-token', { grant_type: 'convert_token', - client_id: client_id, - client_secret: client_secret, + client_id: env?.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_ID, + client_secret: env?.NEXT_PUBLIC_DJANGO_GOOGLE_APP_CLIENT_SECRET, backend: 'google-oauth2', - token: token, + token, }) return data @@ -5,7 +5,7 @@ import axios from 'axios' import Image from 'next/image' import Link from 'next/link' import { useRouter } from 'next/router' -import { API_URL } from '#/shared/lib/constants/constants' +import { getApiUrl } from '#/shared/lib/constants' import { getDeviceType, getRandomImage } from '#/shared/lib/helpers' import { NextPageWithLayout } from '#/pages/_app' @@ -20,22 +20,57 @@ const ChangePassword: NextPageWithLayout = () => { const { query, push } = useRouter() + const [error, setError] = useState('') + + const [loading, setLoading] = useState(false) + const changePassword = async () => { - let formData: any = new FormData() - - formData.append('password_1', password1) - formData.append('password_2', password2) - - if (password1.trim() && password2.trim()) { - try { - await axios.post(API_URL + `/auth/change-pass?token=${query.token}`, formData, { - headers: { - 'content-type': 'multipart/form-data ', - }, - }) - setIsChange(true) + setError('') + + if (!password1.trim() || !password2.trim()) { + setError('Пожалуйста, заполните оба поля') + return + } + + if (password1.length < 6) { + setError('Пароль должен содержать не менее 6 символов') + return + } + + if (password1 !== password2) { + setError('Пароли не совпадают') + return + } + + setLoading(true) + + try { + let formData: any = new FormData() + formData.append('password_1', password1) + formData.append('password_2', password2) + + const response = await axios.post(getApiUrl() + `/auth/change-pass?token=${query.token}`, formData, { + headers: { + 'content-type': 'multipart/form-data', + }, + }) + if (response.status != 200) { + setError(response.data.detail) setTimeout(() => push('/login'), 5000) - } catch (err) {} + return + } + setIsChange(true) + setTimeout(() => push('/login'), 5000) + } catch (err: any) { + if (err.response?.data?.detail) { + setError(err.response.data.detail) + } else if (err.response?.data?.message) { + setError(err.response.data.message) + } else { + setError('Произошла ошибка при смене пароля') + } + } finally { + setLoading(false) } } @@ -52,7 +87,7 @@ const ChangePassword: NextPageWithLayout = () => { sx={{ padding: 0, margin: desktop ? 0 : '60px auto', - backgroundColor: '#373737', + backgroundColor: '#373737', }} > { {desktop && ( - + { > Восстановление пароля + {error && ( + + {error} + + )} { const tokenData = window.location.search.slice(1).split('=')[1] formData.append("token", tokenData) - axios.post(API_URL + '/auth/confirm', formData, { + axios.post(getApiUrl() + '/auth/confirm', formData, { headers: { 'Content-Type': 'multipart/form-data', }, validateStatus: (status) => status < 400 @@ -6,7 +6,7 @@ import axios from 'axios' import Image from 'next/image' import Router from 'next/router' import { Error, Input } from '#/shared' -import { API_URL } from '#/shared/lib/constants/constants' +import { getApiUrl } from '#/shared/lib/constants' import { getDeviceType, getRandomImage } from '#/shared/lib/helpers' import { NextPageWithLayout } from '#/pages/_app' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' @@ -18,7 +18,7 @@ const Reset: NextPageWithLayout = () => { const [isSend, setIsSend] = useState(false) const {showMessage, } = useShowDataStore() const sendMail = () => { - axios.post(API_URL + '/auth/update-pass', { + axios.post(getApiUrl() + '/auth/update-pass', { email: input_email, }) .then(function (response) { @@ -11,7 +11,7 @@ import styles2 from '#/widgets/business-models/ui/models-list/models-list.module import { getAll, ResponseAllInfo } from '#/entities/user-account/model/user-type-slice' import { ResponseGetPersons } from '#/features/invite-person-in-business' import { Error, InputStyleDark } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' import { DateInput } from '#/shared/ui/date-input/date-input' import { Info } from '#/widgets/business-info' @@ -65,7 +65,7 @@ export default function BusinessHost() { } const download = () => { - axios.get(API_URL + `/auth/business-host/download-expenses?type=employees&from_date=${fromDate}&to_date=${toDate}`, { + axios.get(getApiUrl() + `/auth/business-host/download-expenses?type=employees&from_date=${fromDate}&to_date=${toDate}`, { responseType: 'arraybuffer', headers: { Authorization: `Bearer ${data?.access}` }, }).then((res) => { @@ -82,7 +82,7 @@ export default function BusinessHost() { } useEffect(() => { - axios.put(API_URL + '/auth/business-host', { token_cap_enabled: mailing }, { headers: { Authorization: `Bearer ${data?.access}` } }) + axios.put(getApiUrl() + '/auth/business-host', { token_cap_enabled: mailing }, { headers: { Authorization: `Bearer ${data?.access}` } }) }, [mailing]) return ( @@ -145,7 +145,7 @@ const MailingBlock = ({ info, mailing }: { info: InfoBusiness | null | undefined } const req = async (mailingArr: string[]) => { - await axios.put(API_URL + '/auth/business-host', { token_cap_emails: mailingArr }, { headers: { Authorization: `Bearer ${data?.access}` } }) + await axios.put(getApiUrl() + '/auth/business-host', { token_cap_emails: mailingArr }, { headers: { Authorization: `Bearer ${data?.access}` } }) } return ( @@ -1,6 +1,6 @@ import axios from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export type InfoBusiness = { company_name: string @@ -18,7 +18,7 @@ export type InfoBusiness = { } export const getInfo = async (token?: string): Promise => { try { - const { data } = await axios.get(API_URL + '/auth/business-host', { + const { data } = await axios.get(getApiUrl() + '/auth/business-host', { headers: { Authorization: `Bearer ${token}`, }, @@ -1,10 +1,10 @@ import axios from 'axios' import { AllowedModels } from '#/features/changeAccessToModel' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getModels = async (token?: string): Promise => { try { - const { data } = await axios.get(API_URL + '/auth/business-host/allowed-models', { + const { data } = await axios.get(getApiUrl() + '/auth/business-host/allowed-models', { headers: { Authorization: `Bearer ${token}`, }, @@ -2,11 +2,11 @@ import axios from 'axios' import { ResponseGetPersons } from '#/features/invite-person-in-business' import { ResponseGetBusinessGroups, ResponseGetIpList } from '#/features/invite-person-in-business/model/types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getBusinessGroups = async (token?: string): Promise => { try { - const { data } = await axios.get(API_URL + '/auth/business-groups', { + const { data } = await axios.get(getApiUrl() + '/auth/business-groups', { headers: { Authorization: `Bearer ${token}`, }, @@ -2,11 +2,11 @@ import axios from 'axios' import { ResponseGetPersons } from '#/features/invite-person-in-business' import { ResponseGetIpList } from '#/features/invite-person-in-business/model/types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getIpList = async (token?: string): Promise => { try { - const { data } = await axios.get(API_URL + '/auth/business-host/ip-whitelist', { + const { data } = await axios.get(getApiUrl() + '/auth/business-host/ip-whitelist', { headers: { Authorization: `Bearer ${token}`, }, @@ -2,7 +2,7 @@ import axios from 'axios' import { Dayjs } from 'dayjs' import { ResponseGetLogsList } from '#/features/invite-person-in-business/model/types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getLogsList = async ( offset: number, @@ -14,7 +14,7 @@ export const getLogsList = async ( ): Promise => { try { const { data } = await axios.get( - API_URL + + getApiUrl() + `/auth/business-host/logs/?${from_date ? 'from-date=' + from_date + '&' : ''}${ to_date ? '&to-date=' + to_date + '&' : '' }&limit=${limit}&offset=${offset}&log-identity=${logType}`, @@ -1,12 +1,12 @@ import axios from 'axios' import { ResponseGetPersons } from '#/features/invite-person-in-business' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' export const getPersons = async (token?: string, security?: boolean): Promise => { try { const { data } = await axios.get( - API_URL + `/auth/business-host/accounts${security ? '?type=sec' : '?type=regular&type=admin'}`, + getApiUrl() + `/auth/business-host/accounts${security ? '?type=sec' : '?type=regular&type=admin'}`, { headers: { Authorization: `Bearer ${token}`, @@ -17,7 +17,7 @@ import { AddBusinessGroup } from '#/features/business-group' import { ChangeBusinessGroup } from '#/features/business-group/ui/change-business-group' import { ResponseGetBusinessGroups } from '#/features/invite-person-in-business/model/types' import { Search } from '#/shared' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { getBusinessGroups } from '#/widgets/business-persons/api/get-businessGroups' import ArrowUpOrDown from '#/widgets/top-bar-model/ui/arrow-up-or-down' @@ -57,7 +57,7 @@ export const BusinessGroups = ({ company_uid }: { company_uid?: string }) => { const deleteGroup = async (group_id: string) => { await axios - .delete(API_URL + `/auth/business-groups/${group_id}/`, { + .delete(getApiUrl() + `/auth/business-groups/${group_id}/`, { headers: { Authorization: `Bearer ${data?.access}`, }, @@ -35,7 +35,6 @@ import { Select, } from '#/shared' import { Search } from '#/shared' -import { API_URL } from '#/shared/lib/constants' // import styles from '#/widgets/business-models/ui/models-list/models-list.module.scss' import { getBusinessGroups } from '#/widgets/business-persons/api/get-businessGroups' import ArrowUpOrDown from '#/widgets/top-bar-model/ui/arrow-up-or-down' @@ -1,10 +1,10 @@ import { Message, MessageSend } from '#/entities/message' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { IMessageRequest } from '#/shared/lib/types/types-gpt' import axios, { AxiosError, AxiosResponse } from 'axios' export async function getImagesGalery(token?: string, offset?: number, limit = 10) { - return await axios.get(API_URL + `/media/gallery/images?limit=${limit}&offset=${offset}`, { + return await axios.get(getApiUrl() + `/media/gallery/images?limit=${limit}&offset=${offset}`, { headers: { Authorization: `Bearer ${token}`, }, @@ -1,15 +1,15 @@ import { NavigationSearchModelLink } from './types' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import axios from 'axios' export const getModelChatLinks = async (token: string) => { - return await axios.get(API_URL + '/api/chats/links', { + return await axios.get(getApiUrl() + '/api/chats/links', { headers: { Authorization: `Bearer ${token}` }, }) } export const getModelMediaLinks = async (token: string) => { - return await axios.get(API_URL + '/api/media/images/links', { + return await axios.get(getApiUrl() + '/api/media/images/links', { headers: { Authorization: `Bearer ${token}` }, }) } @@ -5,7 +5,7 @@ import { useRouter } from 'next/router' import { useSession } from 'next-auth/react' import { getReferral, IReferral } from '#/shared/api/endpoints' -import { API_HOST } from '#/shared/lib/constants' +import { getApiHost } from '#/shared/lib/constants' import { useShowDataStore } from '#/shared/lib/hooks/use-show-data' import { useAppSelector } from '#/app/store/store' interface IProps { @@ -15,7 +15,7 @@ interface IProps { export const Referral = ({ device }: IProps) => { const email = useAppSelector((state) => state.user.email) const { push } = useRouter() - const url = API_HOST + '/r/' + email + const url = getApiHost() + '/r/' + email const { showMessage } = useShowDataStore() const { data } = useSession() @@ -1,12 +1,12 @@ import axios, { AxiosResponse } from 'axios' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { WhisperResponse } from '../ui/whisper/whisper' export const getAudioList = async (token: string) => { try { - const { data } = await axios.get(API_URL + '/ml_models/whisper', { + const { data } = await axios.get(getApiUrl() + '/ml_models/whisper', { headers: { Authorization: `Bearer ${token}`, }, @@ -8,7 +8,7 @@ import Image from 'next/image' import { useSession } from 'next-auth/react' import { useAppSelector } from '#/app/store/store' -import { API_URL } from '#/shared/lib/constants' +import { getApiUrl } from '#/shared/lib/constants' import { decodeError } from '#/shared/lib/helpers/decode-error' import { styleInputWithoutBorderFocus } from '#/shared/ui/input' import styles from '#/shared/ui/search/search.module.scss' @@ -47,7 +47,7 @@ export const WhisperWidget = () => { const { data: session } = useSession() const removeAudio = async (uid: string) => { try { - const { status } = await axios.delete(API_URL + '/ml_models/whisper', { + const { status } = await axios.delete(getApiUrl() + '/ml_models/whisper', { headers: { Authorization: `Bearer ${session?.access}`, }, @@ -75,7 +75,7 @@ export const WhisperWidget = () => { formData.append('audio', audio) try { - const { data: result } = await axios.post(API_URL + '/ml_models/whisper', formData, { + const { data: result } = await axios.post(getApiUrl() + '/ml_models/whisper', formData, { headers: { 'content-type': 'multipart/form-data ', Authorization: `Bearer ${data?.access}`, @@ -29,4 +29,3 @@ NEXT_PUBLIC_DJANGO_VK_APP_CLIENT_SECRET=YWv1YXdE69FKN5NZpf583qvU0mq7wbsdrLShBLxn NEXT_PUBLIC_WS_API_URL=wss://devapi.air.fail/rtc NEXT_PUBLIC_SESSION_TIME=1000000 -SESSION_TIME=1000000