Major addition. User register, login and update is now functional on frontend, removed UUID5 for UUID4 for users and many more changes

This commit is contained in:
Thastertyn committed 2025-03-16 22:24:54 +01:00
1 parent d87c280109
commit d0690f2f06
67 files changed
+3389 -1066

No files matched your search

+21
View File
@@ -0,0 +1,21 @@
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
export class ApiError extends Error {
public readonly url: string;
public readonly status: number;
public readonly statusText: string;
public readonly body: unknown;
public readonly request: ApiRequestOptions;
constructor(request: ApiRequestOptions, response: ApiResult, message: string) {
super(message);
this.name = 'ApiError';
this.url = response.url;
this.status = response.status;
this.statusText = response.statusText;
this.body = response.body;
this.request = request;
}
}
@@ -0,0 +1,21 @@
export type ApiRequestOptions<T = unknown> = {
readonly body?: any;
readonly cookies?: Record<string, unknown>;
readonly errors?: Record<number | string, string>;
readonly formData?: Record<string, unknown> | any[] | Blob | File;
readonly headers?: Record<string, unknown>;
readonly mediaType?: string;
readonly method:
| 'DELETE'
| 'GET'
| 'HEAD'
| 'OPTIONS'
| 'PATCH'
| 'POST'
| 'PUT';
readonly path?: Record<string, unknown>;
readonly query?: Record<string, unknown>;
readonly responseHeader?: string;
readonly responseTransformer?: (data: unknown) => Promise<T>;
readonly url: string;
};
+7
View File
@@ -0,0 +1,7 @@
export type ApiResult<TData = any> = {
readonly body: TData;
readonly ok: boolean;
readonly status: number;
readonly statusText: string;
readonly url: string;
};
@@ -0,0 +1,126 @@
export class CancelError extends Error {
constructor(message: string) {
super(message);
this.name = 'CancelError';
}
public get isCancelled(): boolean {
return true;
}
}
export interface OnCancel {
readonly isResolved: boolean;
readonly isRejected: boolean;
readonly isCancelled: boolean;
(cancelHandler: () => void): void;
}
export class CancelablePromise<T> implements Promise<T> {
private _isResolved: boolean;
private _isRejected: boolean;
private _isCancelled: boolean;
readonly cancelHandlers: (() => void)[];
readonly promise: Promise<T>;
private _resolve?: (value: T | PromiseLike<T>) => void;
private _reject?: (reason?: unknown) => void;
constructor(
executor: (
resolve: (value: T | PromiseLike<T>) => void,
reject: (reason?: unknown) => void,
onCancel: OnCancel
) => void
) {
this._isResolved = false;
this._isRejected = false;
this._isCancelled = false;
this.cancelHandlers = [];
this.promise = new Promise<T>((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
const onResolve = (value: T | PromiseLike<T>): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
return;
}
this._isResolved = true;
if (this._resolve) this._resolve(value);
};
const onReject = (reason?: unknown): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
return;
}
this._isRejected = true;
if (this._reject) this._reject(reason);
};
const onCancel = (cancelHandler: () => void): void => {
if (this._isResolved || this._isRejected || this._isCancelled) {
return;
}
this.cancelHandlers.push(cancelHandler);
};
Object.defineProperty(onCancel, 'isResolved', {
get: (): boolean => this._isResolved,
});
Object.defineProperty(onCancel, 'isRejected', {
get: (): boolean => this._isRejected,
});
Object.defineProperty(onCancel, 'isCancelled', {
get: (): boolean => this._isCancelled,
});
return executor(onResolve, onReject, onCancel as OnCancel);
});
}
get [Symbol.toStringTag]() {
return "Cancellable Promise";
}
public then<TResult1 = T, TResult2 = never>(
onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
onRejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null
): Promise<TResult1 | TResult2> {
return this.promise.then(onFulfilled, onRejected);
}
public catch<TResult = never>(
onRejected?: ((reason: unknown) => TResult | PromiseLike<TResult>) | null
): Promise<T | TResult> {
return this.promise.catch(onRejected);
}
public finally(onFinally?: (() => void) | null): Promise<T> {
return this.promise.finally(onFinally);
}
public cancel(): void {
if (this._isResolved || this._isRejected || this._isCancelled) {
return;
}
this._isCancelled = true;
if (this.cancelHandlers.length) {
try {
for (const cancelHandler of this.cancelHandlers) {
cancelHandler();
}
} catch (error) {
console.warn('Cancellation threw an error', error);
return;
}
}
this.cancelHandlers.length = 0;
if (this._reject) this._reject(new CancelError('Request aborted'));
}
public get isCancelled(): boolean {
return this._isCancelled;
}
}
+57
View File
@@ -0,0 +1,57 @@
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import type { ApiRequestOptions } from './ApiRequestOptions';
type Headers = Record<string, string>;
type Middleware<T> = (value: T) => T | Promise<T>;
type Resolver<T> = (options: ApiRequestOptions<T>) => Promise<T>;
export class Interceptors<T> {
_fns: Middleware<T>[];
constructor() {
this._fns = [];
}
eject(fn: Middleware<T>): void {
const index = this._fns.indexOf(fn);
if (index !== -1) {
this._fns = [...this._fns.slice(0, index), ...this._fns.slice(index + 1)];
}
}
use(fn: Middleware<T>): void {
this._fns = [...this._fns, fn];
}
}
export type OpenAPIConfig = {
BASE: string;
CREDENTIALS: 'include' | 'omit' | 'same-origin';
ENCODE_PATH?: ((path: string) => string) | undefined;
HEADERS?: Headers | Resolver<Headers> | undefined;
PASSWORD?: string | Resolver<string> | undefined;
TOKEN?: string | Resolver<string> | undefined;
USERNAME?: string | Resolver<string> | undefined;
VERSION: string;
WITH_CREDENTIALS: boolean;
interceptors: {
request: Interceptors<AxiosRequestConfig>;
response: Interceptors<AxiosResponse>;
};
};
export const OpenAPI: OpenAPIConfig = {
BASE: '',
CREDENTIALS: 'include',
ENCODE_PATH: undefined,
HEADERS: undefined,
PASSWORD: undefined,
TOKEN: undefined,
USERNAME: undefined,
VERSION: '0.0.1',
WITH_CREDENTIALS: false,
interceptors: {
request: new Interceptors(),
response: new Interceptors(),
},
};
+347
View File
@@ -0,0 +1,347 @@
import axios from 'axios';
import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios';
import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';
export const isString = (value: unknown): value is string => {
return typeof value === 'string';
};
export const isStringWithValue = (value: unknown): value is string => {
return isString(value) && value !== '';
};
export const isBlob = (value: any): value is Blob => {
return value instanceof Blob;
};
export const isFormData = (value: unknown): value is FormData => {
return value instanceof FormData;
};
export const isSuccess = (status: number): boolean => {
return status >= 200 && status < 300;
};
export const base64 = (str: string): string => {
try {
return btoa(str);
} catch (err) {
// @ts-ignore
return Buffer.from(str).toString('base64');
}
};
export const getQueryString = (params: Record<string, unknown>): string => {
const qs: string[] = [];
const append = (key: string, value: unknown) => {
qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
};
const encodePair = (key: string, value: unknown) => {
if (value === undefined || value === null) {
return;
}
if (value instanceof Date) {
append(key, value.toISOString());
} else if (Array.isArray(value)) {
value.forEach(v => encodePair(key, v));
} else if (typeof value === 'object') {
Object.entries(value).forEach(([k, v]) => encodePair(`${key}[${k}]`, v));
} else {
append(key, value);
}
};
Object.entries(params).forEach(([key, value]) => encodePair(key, value));
return qs.length ? `?${qs.join('&')}` : '';
};
const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => {
const encoder = config.ENCODE_PATH || encodeURI;
const path = options.url
.replace('{api-version}', config.VERSION)
.replace(/{(.*?)}/g, (substring: string, group: string) => {
if (options.path?.hasOwnProperty(group)) {
return encoder(String(options.path[group]));
}
return substring;
});
const url = config.BASE + path;
return options.query ? url + getQueryString(options.query) : url;
};
export const getFormData = (options: ApiRequestOptions): FormData | undefined => {
if (options.formData) {
const formData = new FormData();
const process = (key: string, value: unknown) => {
if (isString(value) || isBlob(value)) {
formData.append(key, value);
} else {
formData.append(key, JSON.stringify(value));
}
};
Object.entries(options.formData)
.filter(([, value]) => value !== undefined && value !== null)
.forEach(([key, value]) => {
if (Array.isArray(value)) {
value.forEach(v => process(key, v));
} else {
process(key, value);
}
});
return formData;
}
return undefined;
};
type Resolver<T> = (options: ApiRequestOptions<T>) => Promise<T>;
export const resolve = async <T>(options: ApiRequestOptions<T>, resolver?: T | Resolver<T>): Promise<T | undefined> => {
if (typeof resolver === 'function') {
return (resolver as Resolver<T>)(options);
}
return resolver;
};
export const getHeaders = async <T>(config: OpenAPIConfig, options: ApiRequestOptions<T>): Promise<Record<string, string>> => {
const [token, username, password, additionalHeaders] = await Promise.all([
// @ts-ignore
resolve(options, config.TOKEN),
// @ts-ignore
resolve(options, config.USERNAME),
// @ts-ignore
resolve(options, config.PASSWORD),
// @ts-ignore
resolve(options, config.HEADERS),
]);
const headers = Object.entries({
Accept: 'application/json',
...additionalHeaders,
...options.headers,
})
.filter(([, value]) => value !== undefined && value !== null)
.reduce((headers, [key, value]) => ({
...headers,
[key]: String(value),
}), {} as Record<string, string>);
if (isStringWithValue(token)) {
headers['Authorization'] = `Bearer ${token}`;
}
if (isStringWithValue(username) && isStringWithValue(password)) {
const credentials = base64(`${username}:${password}`);
headers['Authorization'] = `Basic ${credentials}`;
}
if (options.body !== undefined) {
if (options.mediaType) {
headers['Content-Type'] = options.mediaType;
} else if (isBlob(options.body)) {
headers['Content-Type'] = options.body.type || 'application/octet-stream';
} else if (isString(options.body)) {
headers['Content-Type'] = 'text/plain';
} else if (!isFormData(options.body)) {
headers['Content-Type'] = 'application/json';
}
} else if (options.formData !== undefined) {
if (options.mediaType) {
headers['Content-Type'] = options.mediaType;
}
}
return headers;
};
export const getRequestBody = (options: ApiRequestOptions): unknown => {
if (options.body) {
return options.body;
}
return undefined;
};
export const sendRequest = async <T>(
config: OpenAPIConfig,
options: ApiRequestOptions<T>,
url: string,
body: unknown,
formData: FormData | undefined,
headers: Record<string, string>,
onCancel: OnCancel,
axiosClient: AxiosInstance
): Promise<AxiosResponse<T>> => {
const controller = new AbortController();
let requestConfig: AxiosRequestConfig = {
data: body ?? formData,
headers,
method: options.method,
signal: controller.signal,
url,
withCredentials: config.WITH_CREDENTIALS,
};
onCancel(() => controller.abort());
for (const fn of config.interceptors.request._fns) {
requestConfig = await fn(requestConfig);
}
try {
return await axiosClient.request(requestConfig);
} catch (error) {
const axiosError = error as AxiosError<T>;
if (axiosError.response) {
return axiosError.response;
}
throw error;
}
};
export const getResponseHeader = (response: AxiosResponse<unknown>, responseHeader?: string): string | undefined => {
if (responseHeader) {
const content = response.headers[responseHeader];
if (isString(content)) {
return content;
}
}
return undefined;
};
export const getResponseBody = (response: AxiosResponse<unknown>): unknown => {
if (response.status !== 204) {
return response.data;
}
return undefined;
};
export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => {
const errors: Record<number, string> = {
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
404: 'Not Found',
405: 'Method Not Allowed',
406: 'Not Acceptable',
407: 'Proxy Authentication Required',
408: 'Request Timeout',
409: 'Conflict',
410: 'Gone',
411: 'Length Required',
412: 'Precondition Failed',
413: 'Payload Too Large',
414: 'URI Too Long',
415: 'Unsupported Media Type',
416: 'Range Not Satisfiable',
417: 'Expectation Failed',
418: 'Im a teapot',
421: 'Misdirected Request',
422: 'Unprocessable Content',
423: 'Locked',
424: 'Failed Dependency',
425: 'Too Early',
426: 'Upgrade Required',
428: 'Precondition Required',
429: 'Too Many Requests',
431: 'Request Header Fields Too Large',
451: 'Unavailable For Legal Reasons',
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Timeout',
505: 'HTTP Version Not Supported',
506: 'Variant Also Negotiates',
507: 'Insufficient Storage',
508: 'Loop Detected',
510: 'Not Extended',
511: 'Network Authentication Required',
...options.errors,
}
const error = errors[result.status];
if (error) {
throw new ApiError(options, result, error);
}
if (!result.ok) {
const errorStatus = result.status ?? 'unknown';
const errorStatusText = result.statusText ?? 'unknown';
const errorBody = (() => {
try {
return JSON.stringify(result.body, null, 2);
} catch (e) {
return undefined;
}
})();
throw new ApiError(options, result,
`Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}`
);
}
};
/**
* Request method
* @param config The OpenAPI configuration object
* @param options The request options from the service
* @param axiosClient The axios client instance to use
* @returns CancelablePromise<T>
* @throws ApiError
*/
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions<T>, axiosClient: AxiosInstance = axios): CancelablePromise<T> => {
return new CancelablePromise(async (resolve, reject, onCancel) => {
try {
const url = getUrl(config, options);
const formData = getFormData(options);
const body = getRequestBody(options);
const headers = await getHeaders(config, options);
if (!onCancel.isCancelled) {
let response = await sendRequest<T>(config, options, url, body, formData, headers, onCancel, axiosClient);
for (const fn of config.interceptors.response._fns) {
response = await fn(response);
}
const responseBody = getResponseBody(response);
const responseHeader = getResponseHeader(response, options.responseHeader);
let transformedBody = responseBody;
if (options.responseTransformer && isSuccess(response.status)) {
transformedBody = await options.responseTransformer(responseBody)
}
const result: ApiResult = {
url,
ok: isSuccess(response.status),
status: response.status,
statusText: response.statusText,
body: responseHeader ?? transformedBody,
};
catchErrorCodes(options, result);
resolve(result.body);
}
} catch (error) {
reject(error);
}
});
};
+6
View File
@@ -0,0 +1,6 @@
// This file is auto-generated by @hey-api/openapi-ts
export { ApiError } from './core/ApiError';
export { CancelablePromise, CancelError } from './core/CancelablePromise';
export { OpenAPI, type OpenAPIConfig } from './core/OpenAPI';
export * from './sdk.gen';
export * from './types.gen';
+438
View File
@@ -0,0 +1,438 @@
// This file is auto-generated by @hey-api/openapi-ts
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
import type { UserGetUserResponse, UserUpdateUserData, UserUpdateUserResponse, UserRegisterData, UserRegisterResponse, UserDeleteUserResponse, DashboardLoginAccessTokenData, DashboardLoginAccessTokenResponse, DashboardRegisterNewShopData, DashboardRegisterNewShopResponse, ShopLoginAccessTokenData, ShopLoginAccessTokenResponse, ShopDeleteUserData, ShopDeleteUserResponse, ShopLogoutResponse, ShopRegisterData, ShopRegisterResponse, ShopUpdateUserData, ShopUpdateUserResponse, UtilsHealthCheckResponse, UtilsTestDbResponse } from './types.gen';
export class DashboardService {
/**
* Get information about currently logged in user
* @returns UserPublic Successful Response
* @throws ApiError
*/
public static userGetUser(): CancelablePromise<UserGetUserResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/user'
});
}
/**
* Update user details
* @param data The data for the request.
* @param data.requestBody
* @returns boolean Successful Response
* @throws ApiError
*/
public static userUpdateUser(data: UserUpdateUserData): CancelablePromise<UserUpdateUserResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/user',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Register new user
* @param data The data for the request.
* @param data.requestBody
* @returns boolean Successful Response
* @throws ApiError
*/
public static userRegister(data: UserRegisterData): CancelablePromise<UserRegisterResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/user',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Delete user
* @returns boolean Successful Response
* @throws ApiError
*/
public static userDeleteUser(): CancelablePromise<UserDeleteUserResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/user'
});
}
/**
* Login Access Token
* OAuth2 compatible token login for the dashboard.
*
* This endpoint generates an access token required for authenticating future
* requests to the dashboard section of the application. The token is valid for
* a predefined expiration period.
*
* - **username**: User's email
* - **password**: User's password
*
* **Note:** This login is restricted to dashboard access only and cannot be
* used for tenant accounts access to shops
* @param data The data for the request.
* @param data.formData
* @returns Token Successful Response
* @throws ApiError
*/
public static dashboardLoginAccessToken(data: DashboardLoginAccessTokenData): CancelablePromise<DashboardLoginAccessTokenResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/login/access-token',
formData: data.formData,
mediaType: 'application/x-www-form-urlencoded',
errors: {
422: 'Validation Error'
}
});
}
/**
* Register New Shop
* @param data The data for the request.
* @param data.requestBody
* @returns boolean Successful Response
* @throws ApiError
*/
public static dashboardRegisterNewShop(data: DashboardRegisterNewShopData): CancelablePromise<DashboardRegisterNewShopResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/shop',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
}
export class LoginService {
/**
* Login Access Token
* OAuth2 compatible token login for the dashboard.
*
* This endpoint generates an access token required for authenticating future
* requests to the dashboard section of the application. The token is valid for
* a predefined expiration period.
*
* - **username**: User's email
* - **password**: User's password
*
* **Note:** This login is restricted to dashboard access only and cannot be
* used for tenant accounts access to shops
* @param data The data for the request.
* @param data.formData
* @returns Token Successful Response
* @throws ApiError
*/
public static dashboardLoginAccessToken(data: DashboardLoginAccessTokenData): CancelablePromise<DashboardLoginAccessTokenResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/login/access-token',
formData: data.formData,
mediaType: 'application/x-www-form-urlencoded',
errors: {
422: 'Validation Error'
}
});
}
/**
* Login Access Token
* OAuth2 compatible token login, get an access token for future requests
* @param data The data for the request.
* @param data.formData
* @returns Token Successful Response
* @throws ApiError
*/
public static shopLoginAccessToken(data: ShopLoginAccessTokenData): CancelablePromise<ShopLoginAccessTokenResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/shop/{shop_uuid}/login/access-token',
formData: data.formData,
mediaType: 'application/x-www-form-urlencoded',
errors: {
422: 'Validation Error'
}
});
}
}
export class ShopService {
/**
* Login Access Token
* OAuth2 compatible token login, get an access token for future requests
* @param data The data for the request.
* @param data.formData
* @returns Token Successful Response
* @throws ApiError
*/
public static shopLoginAccessToken(data: ShopLoginAccessTokenData): CancelablePromise<ShopLoginAccessTokenResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/shop/{shop_uuid}/login/access-token',
formData: data.formData,
mediaType: 'application/x-www-form-urlencoded',
errors: {
422: 'Validation Error'
}
});
}
/**
* Delete user
* @param data The data for the request.
* @param data.shopUuid
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopDeleteUser(data: ShopDeleteUserData): CancelablePromise<ShopDeleteUserResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/shop/{shop_uuid}/user/delete',
path: {
shop_uuid: data.shopUuid
},
errors: {
422: 'Validation Error'
}
});
}
/**
* User logout
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopLogout(): CancelablePromise<ShopLogoutResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/shop/{shop_uuid}/user/logout'
});
}
/**
* Register new user
* @param data The data for the request.
* @param data.shopUuid
* @param data.requestBody
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopRegister(data: ShopRegisterData): CancelablePromise<ShopRegisterResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/shop/{shop_uuid}/user/register',
path: {
shop_uuid: data.shopUuid
},
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Update user details
* @param data The data for the request.
* @param data.requestBody
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopUpdateUser(data: ShopUpdateUserData): CancelablePromise<ShopUpdateUserResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/shop/{shop_uuid}/user/update',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
}
export class UserService {
/**
* Get information about currently logged in user
* @returns UserPublic Successful Response
* @throws ApiError
*/
public static userGetUser(): CancelablePromise<UserGetUserResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/user'
});
}
/**
* Update user details
* @param data The data for the request.
* @param data.requestBody
* @returns boolean Successful Response
* @throws ApiError
*/
public static userUpdateUser(data: UserUpdateUserData): CancelablePromise<UserUpdateUserResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/user',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Register new user
* @param data The data for the request.
* @param data.requestBody
* @returns boolean Successful Response
* @throws ApiError
*/
public static userRegister(data: UserRegisterData): CancelablePromise<UserRegisterResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/user',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Delete user
* @returns boolean Successful Response
* @throws ApiError
*/
public static userDeleteUser(): CancelablePromise<UserDeleteUserResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/user'
});
}
/**
* Delete user
* @param data The data for the request.
* @param data.shopUuid
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopDeleteUser(data: ShopDeleteUserData): CancelablePromise<ShopDeleteUserResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/shop/{shop_uuid}/user/delete',
path: {
shop_uuid: data.shopUuid
},
errors: {
422: 'Validation Error'
}
});
}
/**
* User logout
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopLogout(): CancelablePromise<ShopLogoutResponse> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/shop/{shop_uuid}/user/logout'
});
}
/**
* Register new user
* @param data The data for the request.
* @param data.shopUuid
* @param data.requestBody
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopRegister(data: ShopRegisterData): CancelablePromise<ShopRegisterResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/shop/{shop_uuid}/user/register',
path: {
shop_uuid: data.shopUuid
},
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
/**
* Update user details
* @param data The data for the request.
* @param data.requestBody
* @returns unknown Successful Response
* @throws ApiError
*/
public static shopUpdateUser(data: ShopUpdateUserData): CancelablePromise<ShopUpdateUserResponse> {
return __request(OpenAPI, {
method: 'PUT',
url: '/shop/{shop_uuid}/user/update',
body: data.requestBody,
mediaType: 'application/json',
errors: {
422: 'Validation Error'
}
});
}
}
export class UtilsService {
/**
* Health Check
* Ping the API whether it's alive or not
* @returns boolean Successful Response
* @throws ApiError
*/
public static utilsHealthCheck(): CancelablePromise<UtilsHealthCheckResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/utils/health-check/'
});
}
/**
* Test Db
* Ping database using select 1 to see if connection works
* @returns boolean Successful Response
* @throws ApiError
*/
public static utilsTestDb(): CancelablePromise<UtilsTestDbResponse> {
return __request(OpenAPI, {
method: 'GET',
url: '/utils/test-db/'
});
}
}
+142
View File
@@ -0,0 +1,142 @@
// This file is auto-generated by @hey-api/openapi-ts
export type Body_Dashboard_login_access_token = {
grant_type?: (string | null);
username: string;
password: string;
scope?: string;
client_id?: (string | null);
client_secret?: (string | null);
};
export type Body_Shop_login_access_token = {
grant_type?: (string | null);
username: string;
password: string;
scope?: string;
client_id?: (string | null);
client_secret?: (string | null);
};
export type HTTPValidationError = {
detail?: Array<ValidationError>;
};
export type ShopAddress = {
street: string;
city: string;
state: string;
postal_code: string;
country: string;
};
export type ShopCreate = {
name: string;
description: string;
currency: string;
contact_email: string;
contact_phone_number: string;
address: ShopAddress;
};
export type Token = {
access_token: string;
token_type?: string;
};
export type UserPublic = {
uuid: string;
username: string;
email: string;
first_name: (string | null);
last_name: (string | null);
phone_number: string;
};
export type UserRegister = {
username: string;
email: string;
phone_number: string;
/**
* Password must conform to this regex:
* ```
* ^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$ %^&*-]).{8,128}$
* ```
*/
password: string;
};
export type UserUpdate = {
email: (string | null);
phone_number: (string | null);
username: (string | null);
first_name?: (string | null);
last_name?: (string | null);
};
export type ValidationError = {
loc: Array<(string | number)>;
msg: string;
type: string;
};
export type UserGetUserResponse = (UserPublic);
export type UserUpdateUserData = {
requestBody: UserUpdate;
};
export type UserUpdateUserResponse = (boolean);
export type UserRegisterData = {
requestBody: UserRegister;
};
export type UserRegisterResponse = (boolean);
export type UserDeleteUserResponse = (boolean);
export type DashboardLoginAccessTokenData = {
formData: Body_Dashboard_login_access_token;
};
export type DashboardLoginAccessTokenResponse = (Token);
export type DashboardRegisterNewShopData = {
requestBody: ShopCreate;
};
export type DashboardRegisterNewShopResponse = (boolean);
export type ShopLoginAccessTokenData = {
formData: Body_Shop_login_access_token;
};
export type ShopLoginAccessTokenResponse = (Token);
export type ShopDeleteUserData = {
shopUuid: unknown;
};
export type ShopDeleteUserResponse = (unknown);
export type ShopLogoutResponse = (unknown);
export type ShopRegisterData = {
requestBody: UserRegister;
shopUuid: unknown;
};
export type ShopRegisterResponse = (unknown);
export type ShopUpdateUserData = {
requestBody: {
[key: string]: unknown;
};
};
export type ShopUpdateUserResponse = (unknown);
export type UtilsHealthCheckResponse = (boolean);
export type UtilsTestDbResponse = (boolean);
-175
View File
@@ -1,175 +0,0 @@
"use client";
import * as React from "react";
import {
AudioWaveform,
BookOpen,
Bot,
Command,
Frame,
GalleryVerticalEnd,
Map,
PieChart,
Settings2,
SquareTerminal
} from "lucide-react";
import { NavMain } from "@/components/nav-main";
import { NavProjects } from "@/components/nav-projects";
import { NavUser } from "@/components/nav-user";
import { TeamSwitcher } from "@/components/team-switcher";
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarRail
} from "@/components/ui/sidebar";
// This is sample data.
const data = {
user: {
name: "shadcn",
email: "m@example.com",
avatar: "/avatars/shadcn.jpg"
},
teams: [
{
name: "Acme Inc",
logo: GalleryVerticalEnd,
plan: "Enterprise"
},
{
name: "Acme Corp.",
logo: AudioWaveform,
plan: "Startup"
},
{
name: "Evil Corp.",
logo: Command,
plan: "Free"
}
],
navMain: [
{
title: "Playground",
url: "#",
icon: SquareTerminal,
isActive: true,
items: [
{
title: "History",
url: "#"
},
{
title: "Starred",
url: "#"
},
{
title: "Settings",
url: "#"
}
]
},
{
title: "Models",
url: "#",
icon: Bot,
items: [
{
title: "Genesis",
url: "#"
},
{
title: "Explorer",
url: "#"
},
{
title: "Quantum",
url: "#"
}
]
},
{
title: "Documentation",
url: "#",
icon: BookOpen,
items: [
{
title: "Introduction",
url: "#"
},
{
title: "Get Started",
url: "#"
},
{
title: "Tutorials",
url: "#"
},
{
title: "Changelog",
url: "#"
}
]
},
{
title: "Settings",
url: "#",
icon: Settings2,
items: [
{
title: "General",
url: "#"
},
{
title: "Team",
url: "#"
},
{
title: "Billing",
url: "#"
},
{
title: "Limits",
url: "#"
}
]
}
],
projects: [
{
name: "Design Engineering",
url: "#",
icon: Frame
},
{
name: "Sales & Marketing",
url: "#",
icon: PieChart
},
{
name: "Travel",
url: "#",
icon: Map
}
]
};
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
return (
<Sidebar collapsible="icon" {...props}>
<SidebarHeader>
<TeamSwitcher teams={data.teams} />
</SidebarHeader>
<SidebarContent>
<NavMain items={data.navMain} />
<NavProjects projects={data.projects} />
</SidebarContent>
<SidebarFooter>
<NavUser user={data.user} />
</SidebarFooter>
<SidebarRail />
</Sidebar>
);
}
@@ -0,0 +1,32 @@
import { Link } from "@tanstack/react-router";
import { Button } from "./ui/button";
import useAuth from "@/hooks/useAuth";
const DynamicLoginButton = () => {
const { logout, user } = useAuth();
if (user) {
return (
<>
<Button variant="secondary" className="hidden px-2 md:block">
<Link to="/dashboard">Dashboard</Link>
</Button>
<Button className="ml-2 mr-2 hidden md:block" onClick={logout}>
Logout
</Button>
</>
);
}
return (
<>
<Button variant="secondary" className="hidden px-2 md:block">
<Link to="/sign-in">Login</Link>
</Button>
<Button className="ml-2 mr-2 hidden md:block">
<Link to="/sign-up">Get Started</Link>
</Button>
</>
);
};
export default DynamicLoginButton;
+10 -6
View File
@@ -1,29 +1,33 @@
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarHeader,
SidebarRail
} from "@/components/ui/sidebar";
import { NavGroup } from "@/components/layout/nav-group";
import { NavUser } from "@/components/layout/nav-user";
import { TeamSwitcher } from "@/components/layout/team-switcher";
import { sidebarData } from "./data/sidebar-data";
import { cn } from "@/lib/utils";
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
return (
<Sidebar collapsible="icon" variant="floating" {...props}>
<SidebarHeader>
<TeamSwitcher teams={sidebarData.teams} />
<h1
className={cn(
"header-fixed peer/header flex h-16 w-[inherit] items-center gap-3 rounded-md bg-background p-4 text-xl font-bold sm:gap-4"
)}
{...props}>
SwagShop
</h1>
</SidebarHeader>
<SidebarContent>
{sidebarData.navGroups.map((props) => (
<NavGroup key={props.title} {...props} />
))}
</SidebarContent>
<SidebarFooter>
{/* <SidebarFooter>
<NavUser user={sidebarData.user} />
</SidebarFooter>
</SidebarFooter> */}
<SidebarRail />
</Sidebar>
);
@@ -1,22 +1,17 @@
import {
IconBarrierBlock,
IconBrowserCheck,
IconBug,
IconChecklist,
IconError404,
IconCoin,
IconForklift,
IconHelp,
IconLayoutDashboard,
IconLock,
IconLockAccess,
IconMessages,
IconNotification,
IconPackages,
IconPackage,
IconPalette,
IconServerOff,
IconPercentage,
IconSettings,
IconTag,
IconTool,
IconUserCog,
IconUserOff,
IconUsers
} from "@tabler/icons-react";
import { AudioWaveform, Command, GalleryVerticalEnd } from "lucide-react";
@@ -47,100 +42,43 @@ export const sidebarData: SidebarData = {
],
navGroups: [
{
title: "General",
title: "Dashboard",
items: [
{
title: "Dashboard",
url: "/",
url: "/dashboard",
icon: IconLayoutDashboard
},
{
title: "Tasks",
url: "/tasks",
icon: IconChecklist
title: "Products",
url: "/dashboard/products",
icon: IconPackage
},
{
title: "Apps",
url: "/apps",
icon: IconPackages
title: "Inventory",
url: "/dashboard/tasks",
icon: IconForklift
},
{
title: "Chats",
url: "/chats",
badge: "3",
icon: IconMessages
title: "Sales",
icon: IconCoin,
items: [
{
title: "Discounts",
url: "/dashboard/sales/discounts",
icon: IconPercentage
},
{
title: "Coupons",
url: "/dashboard/sales/coupons",
icon: IconTag
}
]
},
{
title: "Users",
url: "/users",
title: "Customers",
url: "/dashboard/users",
icon: IconUsers
},
{
title: "NBA",
url: "/nba",
icon: IconChecklist
}
]
},
{
title: "Pages",
items: [
{
title: "Auth",
icon: IconLockAccess,
items: [
{
title: "Sign In",
url: "/sign-in"
},
{
title: "Sign In (2 Col)",
url: "/sign-in-2"
},
{
title: "Sign Up",
url: "/sign-up"
},
{
title: "Forgot Password",
url: "/forgot-password"
},
{
title: "OTP",
url: "/otp"
}
]
},
{
title: "Errors",
icon: IconBug,
items: [
{
title: "Unauthorized",
url: "/401",
icon: IconLock
},
{
title: "Forbidden",
url: "/403",
icon: IconUserOff
},
{
title: "Not Found",
url: "/404",
icon: IconError404
},
{
title: "Internal Server Error",
url: "/500",
icon: IconServerOff
},
{
title: "Maintenance Error",
url: "/503",
icon: IconBarrierBlock
}
]
}
]
},
@@ -153,27 +91,27 @@ export const sidebarData: SidebarData = {
items: [
{
title: "Profile",
url: "/settings",
url: "/dashboard/settings",
icon: IconUserCog
},
{
title: "Account",
url: "/settings/account",
url: "/dashboard/settings/account",
icon: IconTool
},
{
title: "Appearance",
url: "/settings/appearance",
url: "/dashboard/settings/appearance",
icon: IconPalette
},
{
title: "Notifications",
url: "/settings/notifications",
url: "/dashboard/settings/notifications",
icon: IconNotification
},
{
title: "Display",
url: "/settings/display",
url: "/dashboard/settings/display",
icon: IconBrowserCheck
}
]
+2 -6
View File
@@ -8,7 +8,7 @@ import { Menu } from "lucide-react";
import { Card } from "@/components/ui/card";
import { ThemeSwitch } from "./theme-switch";
import { Button } from "@/components/ui/button";
import { Link } from "@tanstack/react-router";
import DynamicLoginButton from "./dynamic-login-button";
const MainNavbar = () => {
return (
@@ -27,11 +27,7 @@ const MainNavbar = () => {
</ul>
<div className="flex items-center">
<Button variant="secondary" className="hidden px-2 md:block">
<Link to="/sign-in">Login</Link>
</Button>
<Button className="ml-2 mr-2 hidden md:block"><Link to="/sign-up">Get Started</Link></Button>
<DynamicLoginButton />
<div className="mr-2 flex items-center gap-2 md:hidden">
<DropdownMenu>
+17 -13
View File
@@ -11,51 +11,55 @@ import {
DropdownMenuShortcut,
DropdownMenuTrigger
} from "@/components/ui/dropdown-menu";
import useAuth from "@/hooks/useAuth";
export function ProfileDropdown() {
const { user, logout } = useAuth();
if (!user) return "";
let shorthandUsername = "";
if (user.first_name && user.last_name) {
shorthandUsername = (user.first_name[0] + user.last_name[0]).toUpperCase();
} else {
shorthandUsername = user.username[0].toUpperCase();
}
return (
<DropdownMenu modal={false}>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
<Avatar className="h-8 w-8">
<AvatarImage src="/avatars/01.png" alt="@shadcn" />
<AvatarFallback>SN</AvatarFallback>
<AvatarFallback>{shorthandUsername}</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56" align="end" forceMount>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">satnaing</p>
<p className="text-sm font-medium leading-none">{user.username}</p>
<p className="text-xs leading-none text-muted-foreground">
satnaingdev@gmail.com
{user.email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem asChild>
<Link to="/settings">
<Link to="/dashboard/settings">
Profile
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to="/settings">
Billing
<DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link to="/settings">
<Link to="/dashboard/settings">
Settings
<DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
</Link>
</DropdownMenuItem>
<DropdownMenuItem>New Team</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<DropdownMenuItem onClick={logout}>
Log out
<DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
</DropdownMenuItem>
+1 -1
View File
@@ -7,7 +7,7 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
<input
type={type}
className={cn(
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"flex h-10 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
ref={ref}
@@ -0,0 +1,167 @@
import * as React from "react";
import { CheckIcon, ChevronsUpDown } from "lucide-react";
import * as RPNInput from "react-phone-number-input";
import flags from "react-phone-number-input/flags";
import { Button } from "@/components/ui/button";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList
} from "@/components/ui/command";
import { Input } from "@/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger
} from "@/components/ui/popover";
import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils";
type PhoneInputProps = Omit<
React.ComponentProps<"input">,
"onChange" | "value" | "ref"
> &
Omit<RPNInput.Props<typeof RPNInput.default>, "onChange"> & {
onChange?: (value: RPNInput.Value) => void;
};
const PhoneInput: React.ForwardRefExoticComponent<PhoneInputProps> =
React.forwardRef<React.ElementRef<typeof RPNInput.default>, PhoneInputProps>(
({ className, onChange, ...props }, ref) => {
return (
<RPNInput.default
ref={ref}
className={cn("flex", className)}
flagComponent={FlagComponent}
countrySelectComponent={CountrySelect}
inputComponent={InputComponent}
smartCaret={false}
/**
* Handles the onChange event.
*
* react-phone-number-input might trigger the onChange event as undefined
* when a valid phone number is not entered. To prevent this,
* the value is coerced to an empty string.
*
* @param {E164Number | undefined} value - The entered value
*/
onChange={(value) => onChange?.(value || ("" as RPNInput.Value))}
{...props}
/>
);
}
);
PhoneInput.displayName = "PhoneInput";
const InputComponent = React.forwardRef<
HTMLInputElement,
React.ComponentProps<"input">
>(({ className, ...props }, ref) => (
<Input
className={cn("rounded-e-lg rounded-s-none", className)}
{...props}
ref={ref}
/>
));
InputComponent.displayName = "InputComponent";
type CountryEntry = { label: string; value: RPNInput.Country | undefined };
type CountrySelectProps = {
disabled?: boolean;
value: RPNInput.Country;
options: CountryEntry[];
onChange: (country: RPNInput.Country) => void;
};
const CountrySelect = ({
disabled,
value: selectedCountry,
options: countryList,
onChange
}: CountrySelectProps) => {
return (
<Popover>
<PopoverTrigger asChild>
<Button
type="button"
variant="outline"
className="flex gap-1 rounded-e-none rounded-s-lg border-r-0 px-3 focus:z-10"
disabled={disabled}>
<FlagComponent
country={selectedCountry}
countryName={selectedCountry}
/>
<ChevronsUpDown
className={cn(
"-mr-2 size-4 opacity-50",
disabled ? "hidden" : "opacity-100"
)}
/>
</Button>
</PopoverTrigger>
<PopoverContent className="w-[300px] p-0">
<Command>
<CommandInput placeholder="Search country..." />
<CommandList>
<ScrollArea className="h-72">
<CommandEmpty>No country found.</CommandEmpty>
<CommandGroup>
{countryList.map(({ value, label }) =>
value ? (
<CountrySelectOption
key={value}
country={value}
countryName={label}
selectedCountry={selectedCountry}
onChange={onChange}
/>
) : null
)}
</CommandGroup>
</ScrollArea>
</CommandList>
</Command>
</PopoverContent>
</Popover>
);
};
interface CountrySelectOptionProps extends RPNInput.FlagProps {
selectedCountry: RPNInput.Country;
onChange: (country: RPNInput.Country) => void;
}
const CountrySelectOption = ({
country,
countryName,
selectedCountry,
onChange
}: CountrySelectOptionProps) => {
return (
<CommandItem className="gap-2" onSelect={() => onChange(country)}>
<FlagComponent country={country} countryName={countryName} />
<span className="flex-1 text-sm">{countryName}</span>
<span className="text-sm text-foreground/50">{`+${RPNInput.getCountryCallingCode(country)}`}</span>
<CheckIcon
className={`ml-auto size-4 ${country === selectedCountry ? "opacity-100" : "opacity-0"}`}
/>
</CommandItem>
);
};
const FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {
const Flag = flags[country];
return (
<span className="flex h-4 w-6 overflow-hidden rounded-sm bg-foreground/20 [&_svg]:size-full">
{Flag && <Flag title={countryName} />}
</span>
);
};
export { PhoneInput };
+1 -1
View File
@@ -4,7 +4,7 @@ import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
import { VariantProps, cva } from "class-variance-authority";
import { PanelLeft } from "lucide-react";
import { cn } from "@/lib/utils";
import { useIsMobile } from "@/hooks/use-mobile";
import { useIsMobile } from "@/hooks/useMobile";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
+93 -57
View File
@@ -1,69 +1,105 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { useNavigate } from "@tanstack/react-router"
import { useState } from "react"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useNavigate } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { handleServerError } from "@/utils/handle-server-error"
import { handleServerError } from "@/utils/handle-server-error";
import { ApiError } from "@/errors/api-error";
import {
DashboardService,
LoginService,
ShopLoginAccessTokenData,
UserPublic,
UserRegister,
UserService,
UserUpdate
} from "@/client";
import { toast } from "./useToast";
const isLoggedIn = () => {
return localStorage.getItem("access_token") !== null
}
return localStorage.getItem("access_token") !== null;
};
const useAuth = () => {
const [error, setError] = useState<string | null>(null)
const navigate = useNavigate()
const queryClient = useQueryClient()
const { data: user } = useQuery<UserPublic | null, Error>({
queryKey: ["currentUser"],
queryFn: UsersService.readUserMe,
enabled: isLoggedIn(),
})
const [error, setError] = useState<string | null>(null);
const [loggedIn, setLoggedIn] = useState(isLoggedIn());
const navigate = useNavigate();
const queryClient = useQueryClient();
const { data: user } = useQuery<UserPublic | null, Error>({
queryKey: ["currentUser"],
queryFn: DashboardService.userGetUser,
enabled: loggedIn
});
const signUpMutation = useMutation({
mutationFn: (data: UserRegister) =>
UsersService.registerUser({ requestBody: data }),
const signUpMutation = useMutation({
mutationFn: (data: UserRegister) =>
DashboardService.userRegister({ requestBody: data }),
onSuccess: () => navigate({ to: "/sign-in" }),
onError: (err: ApiError) => handleServerError(err),
onSettled: () => queryClient.invalidateQueries({ queryKey: ["users"] })
});
onSuccess: () => {
navigate({ to: "/sign-in" })
},
onError: (err: ApiError) => {
handleServerError(err)
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ["users"] })
},
})
const login = async (data: ShopLoginAccessTokenData) => {
const response = await LoginService.dashboardLoginAccessToken({
formData: {
username: data.formData.username,
password: data.formData.password
}
});
localStorage.setItem("access_token", response.access_token);
setLoggedIn(true);
await queryClient.invalidateQueries({ queryKey: ["currentUser"] });
};
const login = async (data: AccessToken) => {
const response = await LoginService.loginAccessToken({
formData: data,
})
localStorage.setItem("access_token", response.access_token)
}
const loginMutation = useMutation({
mutationFn: login,
onSuccess: () => navigate({ to: "/" }),
onError: (err: ApiError) => handleServerError(err)
});
const loginMutation = useMutation({
mutationFn: login,
onSuccess: () => {
navigate({ to: "/" })
},
onError: (err: ApiError) => {
handleError(err)
},
})
const logout = () => {
localStorage.removeItem("access_token");
setLoggedIn(false);
queryClient.invalidateQueries({ queryKey: ["currentUser"] });
navigate({ to: "/", replace: true, reloadDocument: true });
};
const logout = () => {
localStorage.removeItem("access_token")
navigate({ to: "/sign-in" })
}
const updateAccountMutation = useMutation({
mutationFn: (data: UserUpdate) =>
UserService.userUpdateUser({ requestBody: data }),
onSuccess: () => {
toast({ title: "Account updated successfully" });
queryClient.invalidateQueries({ queryKey: ["currentUser"] });
},
onError: (err: ApiError) => handleServerError(err)
});
return {
signUpMutation,
loginMutation,
logout,
user,
error,
resetError: () => setError(null),
}
}
useEffect(() => {
const handleStorageChange = (event: StorageEvent) => {
if (event.key === "access_token") {
const tokenExists = event.newValue !== null;
setLoggedIn(tokenExists);
if (!tokenExists) {
queryClient.removeQueries({ queryKey: ["currentUser"] });
} else {
queryClient.invalidateQueries({ queryKey: ["currentUser"] });
}
}
};
export { isLoggedIn }
export default useAuth
window.addEventListener("storage", handleStorageChange);
return () => window.removeEventListener("storage", handleStorageChange);
}, [queryClient]);
return {
signUpMutation,
loginMutation,
updateAccountMutation,
logout,
user,
error,
resetError: () => setError(null)
};
};
export { isLoggedIn };
export default useAuth;
+6
View File
@@ -15,6 +15,12 @@ import { ThemeProvider } from "./context/theme-context";
import "./index.css";
// Generated Routes
import { routeTree } from "./routeTree.gen";
import { OpenAPI } from "./client";
OpenAPI.BASE = import.meta.env.VITE_API_URL;
OpenAPI.TOKEN = async () => {
return localStorage.getItem("access_token") ?? "";
};
const queryClient = new QueryClient({
defaultOptions: {
@@ -1,4 +1,4 @@
import { HTMLAttributes, useState } from "react";
import { HTMLAttributes } from "react";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -15,6 +15,7 @@ import {
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { PasswordInput } from "@/components/password-input";
import useAuth from "@/hooks/useAuth";
type UserAuthFormProps = HTMLAttributes<HTMLDivElement>;
@@ -34,7 +35,7 @@ const formSchema = z.object({
});
export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
const [isLoading, setIsLoading] = useState(false);
const { loginMutation, resetError } = useAuth();
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
@@ -44,13 +45,13 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
}
});
function onSubmit(data: z.infer<typeof formSchema>) {
setIsLoading(true);
console.log(data);
setTimeout(() => {
setIsLoading(false);
}, 3000);
async function onSubmit(data: z.infer<typeof formSchema>) {
resetError();
try {
await loginMutation.mutateAsync({formData: {username: data.email, password: data.password}});
} catch {
// Error handled in useAuth hook
}
}
return (
@@ -91,8 +92,8 @@ export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
</FormItem>
)}
/>
<Button className="mt-2" disabled={isLoading}>
Login
<Button className="mt-2" disabled={loginMutation.isPending}>
{loginMutation.isPending ? "Logging in..." : "Login"}
</Button>
<div className="relative my-2">
@@ -16,6 +16,8 @@ import { Input } from "@/components/ui/input";
import { PasswordInput } from "@/components/password-input";
import { registerUser } from "@/lib/api";
import { ApiError } from "@/errors/api-error";
import useAuth from "@/hooks/useAuth";
import { PhoneInput } from "@/components/ui/phone-number-input";
type SignUpFormProps = HTMLAttributes<HTMLDivElement>;
@@ -64,6 +66,7 @@ const formSchema = z
});
export function SignUpForm({ className, ...props }: SignUpFormProps) {
const { signUpMutation } = useAuth();
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [successMessage, setSuccessMessage] = useState<string | null>(null);
@@ -85,12 +88,7 @@ export function SignUpForm({ className, ...props }: SignUpFormProps) {
setSuccessMessage(null);
try {
await registerUser({
username: data.username,
email: data.email,
password: data.password,
phone_number: data.phone_number
});
signUpMutation.mutate(data);
setSuccessMessage("Account created successfully!");
} catch (error: unknown) {
setError(error instanceof ApiError ? error.response : "Something went wrong.");
@@ -137,7 +135,7 @@ export function SignUpForm({ className, ...props }: SignUpFormProps) {
<FormItem className="space-y-1">
<FormLabel>Phone Number</FormLabel>
<FormControl>
<Input placeholder="+1234567890" {...field} />
<PhoneInput {...field} />
</FormControl>
<FormMessage />
</FormItem>
-4
View File
@@ -1,4 +1,3 @@
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
@@ -33,9 +32,6 @@ export default function Dashboard() {
<Main>
<div className="mb-2 flex items-center justify-between space-y-2">
<h1 className="text-2xl font-bold tracking-tight">Dashboard</h1>
<div className="flex items-center space-x-2">
<Button>Download</Button>
</div>
</div>
<Tabs
orientation="vertical"
-2
View File
@@ -18,8 +18,6 @@ export default function MainPage() {
<Pricing />
<Faq />
<CallToAction />
{/* [Optional] Consider inserting an image or illustration here to reinforce the platform’s purpose. */}
</div>
</>
);
-3
View File
@@ -1,3 +0,0 @@
export default function Nba() {
return <h1>NBA Testing</h1>;
}
@@ -27,7 +27,7 @@ const appText = new Map<string, string>([
["notConnected", "Not Connected"]
]);
export default function Apps() {
export default function Products() {
const [sort, setSort] = useState("ascending");
const [appType, setAppType] = useState("all");
const [searchTerm, setSearchTerm] = useState("");
@@ -1,86 +1,63 @@
import { z } from "zod";
import { format } from "date-fns";
import { useForm } from "react-hook-form";
import { CalendarIcon, CaretSortIcon, CheckIcon } from "@radix-ui/react-icons";
import { zodResolver } from "@hookform/resolvers/zod";
import { cn } from "@/lib/utils";
import { toast } from "@/hooks/useToast";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList
} from "@/components/ui/command";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage
} from "@/components/ui/form";
import
{
Form,
FormControl, FormField,
FormItem,
FormLabel,
FormMessage
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger
} from "@/components/ui/popover";
import useAuth from "@/hooks/useAuth";
const languages = [
{ label: "English", value: "en" },
{ label: "French", value: "fr" },
{ label: "German", value: "de" },
{ label: "Spanish", value: "es" },
{ label: "Portuguese", value: "pt" },
{ label: "Russian", value: "ru" },
{ label: "Japanese", value: "ja" },
{ label: "Korean", value: "ko" },
{ label: "Chinese", value: "zh" }
] as const;
// const languages = [
// { label: "English", value: "en" },
// { label: "French", value: "fr" },
// { label: "German", value: "de" },
// { label: "Spanish", value: "es" },
// { label: "Portuguese", value: "pt" },
// { label: "Russian", value: "ru" },
// { label: "Japanese", value: "ja" },
// { label: "Korean", value: "ko" },
// { label: "Chinese", value: "zh" }
// ] as const;
const accountFormSchema = z.object({
name: z
.string()
.min(2, {
message: "Name must be at least 2 characters."
})
.max(30, {
message: "Name must not be longer than 30 characters."
}),
dob: z.date({
required_error: "A date of birth is required."
}),
language: z.string({
required_error: "Please select a language."
})
username: z.string().min(3).max(30),
email: z.string().email(),
phone_number: z.string(),
// password: z.string().min(8).max(128),
first_name: z.string().optional(),
last_name: z.string().optional(),
// dob: z.date({
// required_error: "A date of birth is required."
// }),
// language: z.string({
// required_error: "Please select a language."
// })
});
type AccountFormValues = z.infer<typeof accountFormSchema>;
// This can come from your database or API.
const defaultValues: Partial<AccountFormValues> = {
name: ""
};
export function AccountForm() {
const { updateAccountMutation, user } = useAuth();
const form = useForm<AccountFormValues>({
resolver: zodResolver(accountFormSchema),
defaultValues
resolver: zodResolver(accountFormSchema)
});
function onSubmit(data: AccountFormValues) {
toast({
title: "You submitted the following values:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(data, null, 2)}</code>
</pre>
)
updateAccountMutation.mutate({
email: data.email,
// password: data.password,
password: "null",
phone_number: data.phone_number,
username: data.username,
first_name: data.first_name,
last_name: data.last_name
});
}
@@ -89,126 +66,58 @@ export function AccountForm() {
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="name"
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>Name</FormLabel>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="Your name" {...field} />
<Input placeholder="Your username" defaultValue={user?.username} {...field} />
</FormControl>
<FormDescription>
This is the name that will be displayed on your profile and in
emails.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="dob"
name="email"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Date of birth</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}>
{field.value ? (
format(field.value, "MMM d, yyyy")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date: Date) =>
date > new Date() || date < new Date("1900-01-01")
}
/>
</PopoverContent>
</Popover>
<FormDescription>
Your date of birth is used to calculate your age.
</FormDescription>
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="Your email" defaultValue={user?.email} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="language"
name="phone_number"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Language</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant="outline"
role="combobox"
className={cn(
"w-[200px] justify-between",
!field.value && "text-muted-foreground"
)}>
{field.value
? languages.find(
(language) => language.value === field.value
)?.label
: "Select language"}
<CaretSortIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Command>
<CommandInput placeholder="Search language..." />
<CommandEmpty>No language found.</CommandEmpty>
<CommandGroup>
<CommandList>
{languages.map((language) => (
<CommandItem
value={language.label}
key={language.value}
onSelect={() => {
form.setValue("language", language.value);
}}>
<CheckIcon
className={cn(
"mr-2 h-4 w-4",
language.value === field.value
? "opacity-100"
: "opacity-0"
)}
/>
{language.label}
</CommandItem>
))}
</CommandList>
</CommandGroup>
</Command>
</PopoverContent>
</Popover>
<FormDescription>
This is the language that will be used in the dashboard.
</FormDescription>
<FormItem>
<FormLabel>Phone Number</FormLabel>
<FormControl>
<Input placeholder="Your phone number" defaultValue={user?.phone_number} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Update account</Button>
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>Password</FormLabel>
<FormControl>
<Input type="password" placeholder="New password" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Update Account</Button>
</form>
</Form>
);
}
}
+8 -8
View File
@@ -1,9 +1,9 @@
import { Outlet } from "@tanstack/react-router";
import {
IconBrowserCheck,
IconLock,
IconNotification,
IconPalette,
IconTool,
IconUser
} from "@tabler/icons-react";
import { Separator } from "@/components/ui/separator";
@@ -53,26 +53,26 @@ const sidebarNavItems = [
{
title: "Profile",
icon: <IconUser size={18} />,
href: "/settings"
href: "/dashboard/settings"
},
{
title: "Account",
icon: <IconTool size={18} />,
href: "/settings/account"
title: "Security",
icon: <IconLock size={18} />,
href: "/dashboard/settings/security"
},
{
title: "Appearance",
icon: <IconPalette size={18} />,
href: "/settings/appearance"
href: "/dashboard/settings/appearance"
},
{
title: "Notifications",
icon: <IconNotification size={18} />,
href: "/settings/notifications"
href: "/dashboard/settings/notifications"
},
{
title: "Display",
icon: <IconBrowserCheck size={18} />,
href: "/settings/display"
href: "/dashboard/settings/display"
}
];
@@ -1,8 +1,7 @@
import { z } from "zod";
import { useFieldArray, useForm } from "react-hook-form";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Link } from "@tanstack/react-router";
import { cn } from "@/lib/utils";
import { toast } from "@/hooks/useToast";
import { Button } from "@/components/ui/button";
import {
@@ -15,63 +14,71 @@ import {
FormMessage
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { PhoneInput } from "@/components/ui/phone-number-input";
import useAuth from "@/hooks/useAuth";
const profileFormSchema = z.object({
username: z
.string()
.min(2, {
message: "Username must be at least 2 characters."
.string({
required_error: "Please enter your desired username"
})
.max(30, {
message: "Username must not be longer than 30 characters."
.min(3, {
message: "Username must be at least 3 characters."
})
.max(64, {
message: "Username must not be longer than 64 characters."
}),
email: z
.string({
required_error: "Please select an email to display."
.string()
.email({
message: "Please enter your email address."
})
.email(),
bio: z.string().max(160).min(4),
urls: z
.array(
z.object({
value: z.string().url({ message: "Please enter a valid URL." })
})
)
phone_number: z
.string({
required_error: "Please input a valid phone number."
})
.min(2, {
message: "Phone number must be at least 2 characters."
})
.max(16, {
message: "Phone number must not be longer than 16 characters."
}),
first_name: z
.string()
.max(64, {
message: "First name must not be longer than 64 characters."
})
.optional(),
last_name: z
.string()
.max(64, {
message: "Last name must not be longer than 64 characters."
})
.optional()
});
type ProfileFormValues = z.infer<typeof profileFormSchema>;
// This can come from your database or API.
const defaultValues: Partial<ProfileFormValues> = {
bio: "I own a computer.",
urls: [
{ value: "https://shadcn.com" },
{ value: "http://twitter.com/shadcn" }
]
};
export default function ProfileForm() {
const { user, updateAccountMutation } = useAuth();
const defaultValues: ProfileFormValues = {
username: user?.username ?? "",
email: user?.email ?? "",
phone_number: user?.phone_number ?? "",
first_name: user?.first_name ?? "",
last_name: user?.last_name ?? ""
};
const form = useForm<ProfileFormValues>({
resolver: zodResolver(profileFormSchema),
defaultValues,
mode: "onChange"
});
const { fields, append } = useFieldArray({
name: "urls",
control: form.control
});
function onSubmit(data: ProfileFormValues) {
updateAccountMutation.mutate(data);
toast({
title: "You submitted the following values:",
description: (
@@ -92,11 +99,11 @@ export default function ProfileForm() {
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl>
<Input placeholder="shadcn" {...field} />
<Input placeholder="Username" {...field} />
</FormControl>
<FormDescription>
This is your public display name. It can be your real name or a
pseudonym. You can only change this once every 30 days.
pseudonym.
</FormDescription>
<FormMessage />
</FormItem>
@@ -108,18 +115,9 @@ export default function ProfileForm() {
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="Select a verified email to display" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="m@example.com">m@example.com</SelectItem>
<SelectItem value="m@google.com">m@google.com</SelectItem>
<SelectItem value="m@support.com">m@support.com</SelectItem>
</SelectContent>
</Select>
<FormControl>
<Input type="email" {...field} />
</FormControl>
<FormDescription>
You can manage verified email addresses in your{" "}
<Link to="/">email settings</Link>.
@@ -130,56 +128,44 @@ export default function ProfileForm() {
/>
<FormField
control={form.control}
name="bio"
name="first_name"
render={({ field }) => (
<FormItem>
<FormLabel>Bio</FormLabel>
<FormLabel>First Name</FormLabel>
<FormControl>
<Textarea
placeholder="Tell us a little bit about yourself"
className="resize-none"
{...field}
/>
<Input placeholder="John" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="last_name"
render={({ field }) => (
<FormItem>
<FormLabel>Last Name</FormLabel>
<FormControl>
<Input placeholder="Doe" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="phone_number"
render={({ field }) => (
<FormItem>
<FormLabel>Phone number</FormLabel>
<FormControl>
<PhoneInput {...field} />
</FormControl>
<FormDescription>
You can <span>@mention</span> other users and organizations to
link to them.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div>
{fields.map((field, index) => (
<FormField
control={form.control}
key={field.id}
name={`urls.${index}.value`}
render={({ field }) => (
<FormItem>
<FormLabel className={cn(index !== 0 && "sr-only")}>
URLs
</FormLabel>
<FormDescription className={cn(index !== 0 && "sr-only")}>
Add links to your website, blog, or social media profiles.
</FormDescription>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
))}
<Button
type="button"
variant="outline"
size="sm"
className="mt-2"
onClick={() => append({ value: "" })}>
Add URL
</Button>
</div>
<Button type="submit">Update profile</Button>
</form>
</Form>
Whitespace-only changes.
Whitespace-only changes.
+412 -322
View File
@@ -32,41 +32,47 @@ const authSignIn2LazyImport = createFileRoute('/(auth)/sign-in-2')()
const authForgotPasswordLazyImport = createFileRoute(
'/(auth)/forgot-password',
)()
const AuthenticatedSettingsRouteLazyImport = createFileRoute(
'/_authenticated/settings',
)()
const AuthenticatedUsersIndexLazyImport = createFileRoute(
'/_authenticated/users/',
)()
const AuthenticatedTasksIndexLazyImport = createFileRoute(
'/_authenticated/tasks/',
)()
const AuthenticatedSettingsIndexLazyImport = createFileRoute(
'/_authenticated/settings/',
)()
const AuthenticatedNbaIndexLazyImport = createFileRoute(
'/_authenticated/nba/',
)()
const AuthenticatedHelpCenterIndexLazyImport = createFileRoute(
'/_authenticated/help-center/',
)()
const AuthenticatedChatsIndexLazyImport = createFileRoute(
'/_authenticated/chats/',
const AuthenticatedDashboardSettingsRouteLazyImport = createFileRoute(
'/_authenticated/dashboard/settings',
)()
const AuthenticatedAppsIndexLazyImport = createFileRoute(
'/_authenticated/apps/',
const AuthenticatedDashboardUsersIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/users/',
)()
const AuthenticatedSettingsNotificationsLazyImport = createFileRoute(
'/_authenticated/settings/notifications',
const AuthenticatedDashboardTasksIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/tasks/',
)()
const AuthenticatedSettingsDisplayLazyImport = createFileRoute(
'/_authenticated/settings/display',
const AuthenticatedDashboardSettingsIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/settings/',
)()
const AuthenticatedSettingsAppearanceLazyImport = createFileRoute(
'/_authenticated/settings/appearance',
const AuthenticatedDashboardSalesIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/sales/',
)()
const AuthenticatedSettingsAccountLazyImport = createFileRoute(
'/_authenticated/settings/account',
const AuthenticatedDashboardProductsIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/products/',
)()
const AuthenticatedDashboardChatsIndexLazyImport = createFileRoute(
'/_authenticated/dashboard/chats/',
)()
const AuthenticatedDashboardSettingsNotificationsLazyImport = createFileRoute(
'/_authenticated/dashboard/settings/notifications',
)()
const AuthenticatedDashboardSettingsDisplayLazyImport = createFileRoute(
'/_authenticated/dashboard/settings/display',
)()
const AuthenticatedDashboardSettingsAppearanceLazyImport = createFileRoute(
'/_authenticated/dashboard/settings/appearance',
)()
const AuthenticatedDashboardSettingsAccountLazyImport = createFileRoute(
'/_authenticated/dashboard/settings/account',
)()
const AuthenticatedDashboardSalesDiscountsLazyImport = createFileRoute(
'/_authenticated/dashboard/sales/discounts',
)()
const AuthenticatedDashboardSalesCouponsLazyImport = createFileRoute(
'/_authenticated/dashboard/sales/coupons',
)()
// Create/Update Routes
@@ -148,15 +154,6 @@ const authForgotPasswordLazyRoute = authForgotPasswordLazyImport
import('./routes/(auth)/forgot-password.lazy').then((d) => d.Route),
)
const AuthenticatedSettingsRouteLazyRoute =
AuthenticatedSettingsRouteLazyImport.update({
id: '/settings',
path: '/settings',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/route.lazy').then((d) => d.Route),
)
const authSignInRoute = authSignInImport.update({
id: '/(auth)/sign-in',
path: '/sign-in',
@@ -175,41 +172,6 @@ const auth500Route = auth500Import.update({
getParentRoute: () => rootRoute,
} as any)
const AuthenticatedUsersIndexLazyRoute =
AuthenticatedUsersIndexLazyImport.update({
id: '/users/',
path: '/users/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/users/index.lazy').then((d) => d.Route),
)
const AuthenticatedTasksIndexLazyRoute =
AuthenticatedTasksIndexLazyImport.update({
id: '/tasks/',
path: '/tasks/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/tasks/index.lazy').then((d) => d.Route),
)
const AuthenticatedSettingsIndexLazyRoute =
AuthenticatedSettingsIndexLazyImport.update({
id: '/',
path: '/',
getParentRoute: () => AuthenticatedSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/index.lazy').then((d) => d.Route),
)
const AuthenticatedNbaIndexLazyRoute = AuthenticatedNbaIndexLazyImport.update({
id: '/nba/',
path: '/nba/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/nba/index.lazy').then((d) => d.Route),
)
const AuthenticatedHelpCenterIndexLazyRoute =
AuthenticatedHelpCenterIndexLazyImport.update({
id: '/help-center/',
@@ -221,25 +183,6 @@ const AuthenticatedHelpCenterIndexLazyRoute =
),
)
const AuthenticatedChatsIndexLazyRoute =
AuthenticatedChatsIndexLazyImport.update({
id: '/chats/',
path: '/chats/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/chats/index.lazy').then((d) => d.Route),
)
const AuthenticatedAppsIndexLazyRoute = AuthenticatedAppsIndexLazyImport.update(
{
id: '/apps/',
path: '/apps/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any,
).lazy(() =>
import('./routes/_authenticated/apps/index.lazy').then((d) => d.Route),
)
const AuthenticatedDashboardIndexRoute =
AuthenticatedDashboardIndexImport.update({
id: '/dashboard/',
@@ -247,46 +190,145 @@ const AuthenticatedDashboardIndexRoute =
getParentRoute: () => AuthenticatedRouteRoute,
} as any)
const AuthenticatedSettingsNotificationsLazyRoute =
AuthenticatedSettingsNotificationsLazyImport.update({
const AuthenticatedDashboardSettingsRouteLazyRoute =
AuthenticatedDashboardSettingsRouteLazyImport.update({
id: '/dashboard/settings',
path: '/dashboard/settings',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/settings/route.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardUsersIndexLazyRoute =
AuthenticatedDashboardUsersIndexLazyImport.update({
id: '/dashboard/users/',
path: '/dashboard/users/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/users/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardTasksIndexLazyRoute =
AuthenticatedDashboardTasksIndexLazyImport.update({
id: '/dashboard/tasks/',
path: '/dashboard/tasks/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/tasks/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardSettingsIndexLazyRoute =
AuthenticatedDashboardSettingsIndexLazyImport.update({
id: '/',
path: '/',
getParentRoute: () => AuthenticatedDashboardSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/settings/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardSalesIndexLazyRoute =
AuthenticatedDashboardSalesIndexLazyImport.update({
id: '/dashboard/sales/',
path: '/dashboard/sales/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/sales/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardProductsIndexLazyRoute =
AuthenticatedDashboardProductsIndexLazyImport.update({
id: '/dashboard/products/',
path: '/dashboard/products/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/products/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardChatsIndexLazyRoute =
AuthenticatedDashboardChatsIndexLazyImport.update({
id: '/dashboard/chats/',
path: '/dashboard/chats/',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/chats/index.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardSettingsNotificationsLazyRoute =
AuthenticatedDashboardSettingsNotificationsLazyImport.update({
id: '/notifications',
path: '/notifications',
getParentRoute: () => AuthenticatedSettingsRouteLazyRoute,
getParentRoute: () => AuthenticatedDashboardSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/notifications.lazy').then(
(d) => d.Route,
),
import(
'./routes/_authenticated/dashboard/settings/notifications.lazy'
).then((d) => d.Route),
)
const AuthenticatedSettingsDisplayLazyRoute =
AuthenticatedSettingsDisplayLazyImport.update({
const AuthenticatedDashboardSettingsDisplayLazyRoute =
AuthenticatedDashboardSettingsDisplayLazyImport.update({
id: '/display',
path: '/display',
getParentRoute: () => AuthenticatedSettingsRouteLazyRoute,
getParentRoute: () => AuthenticatedDashboardSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/display.lazy').then(
import('./routes/_authenticated/dashboard/settings/display.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedSettingsAppearanceLazyRoute =
AuthenticatedSettingsAppearanceLazyImport.update({
const AuthenticatedDashboardSettingsAppearanceLazyRoute =
AuthenticatedDashboardSettingsAppearanceLazyImport.update({
id: '/appearance',
path: '/appearance',
getParentRoute: () => AuthenticatedSettingsRouteLazyRoute,
getParentRoute: () => AuthenticatedDashboardSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/appearance.lazy').then(
import('./routes/_authenticated/dashboard/settings/appearance.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedSettingsAccountLazyRoute =
AuthenticatedSettingsAccountLazyImport.update({
const AuthenticatedDashboardSettingsAccountLazyRoute =
AuthenticatedDashboardSettingsAccountLazyImport.update({
id: '/account',
path: '/account',
getParentRoute: () => AuthenticatedSettingsRouteLazyRoute,
getParentRoute: () => AuthenticatedDashboardSettingsRouteLazyRoute,
} as any).lazy(() =>
import('./routes/_authenticated/settings/account.lazy').then(
import('./routes/_authenticated/dashboard/settings/account.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardSalesDiscountsLazyRoute =
AuthenticatedDashboardSalesDiscountsLazyImport.update({
id: '/dashboard/sales/discounts',
path: '/dashboard/sales/discounts',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/sales/discounts.lazy').then(
(d) => d.Route,
),
)
const AuthenticatedDashboardSalesCouponsLazyRoute =
AuthenticatedDashboardSalesCouponsLazyImport.update({
id: '/dashboard/sales/coupons',
path: '/dashboard/sales/coupons',
getParentRoute: () => AuthenticatedRouteRoute,
} as any).lazy(() =>
import('./routes/_authenticated/dashboard/sales/coupons.lazy').then(
(d) => d.Route,
),
)
@@ -330,13 +372,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof authSignInImport
parentRoute: typeof rootRoute
}
'/_authenticated/settings': {
id: '/_authenticated/settings'
path: '/settings'
fullPath: '/settings'
preLoaderRoute: typeof AuthenticatedSettingsRouteLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/(auth)/forgot-password': {
id: '/(auth)/forgot-password'
path: '/forgot-password'
@@ -393,33 +428,12 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof errors503LazyImport
parentRoute: typeof rootRoute
}
'/_authenticated/settings/account': {
id: '/_authenticated/settings/account'
path: '/account'
fullPath: '/settings/account'
preLoaderRoute: typeof AuthenticatedSettingsAccountLazyImport
parentRoute: typeof AuthenticatedSettingsRouteLazyImport
}
'/_authenticated/settings/appearance': {
id: '/_authenticated/settings/appearance'
path: '/appearance'
fullPath: '/settings/appearance'
preLoaderRoute: typeof AuthenticatedSettingsAppearanceLazyImport
parentRoute: typeof AuthenticatedSettingsRouteLazyImport
}
'/_authenticated/settings/display': {
id: '/_authenticated/settings/display'
path: '/display'
fullPath: '/settings/display'
preLoaderRoute: typeof AuthenticatedSettingsDisplayLazyImport
parentRoute: typeof AuthenticatedSettingsRouteLazyImport
}
'/_authenticated/settings/notifications': {
id: '/_authenticated/settings/notifications'
path: '/notifications'
fullPath: '/settings/notifications'
preLoaderRoute: typeof AuthenticatedSettingsNotificationsLazyImport
parentRoute: typeof AuthenticatedSettingsRouteLazyImport
'/_authenticated/dashboard/settings': {
id: '/_authenticated/dashboard/settings'
path: '/dashboard/settings'
fullPath: '/dashboard/settings'
preLoaderRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/dashboard/': {
id: '/_authenticated/dashboard/'
@@ -428,20 +442,6 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedDashboardIndexImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/apps/': {
id: '/_authenticated/apps/'
path: '/apps'
fullPath: '/apps'
preLoaderRoute: typeof AuthenticatedAppsIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/chats/': {
id: '/_authenticated/chats/'
path: '/chats'
fullPath: '/chats'
preLoaderRoute: typeof AuthenticatedChatsIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/help-center/': {
id: '/_authenticated/help-center/'
path: '/help-center'
@@ -449,32 +449,88 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthenticatedHelpCenterIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/nba/': {
id: '/_authenticated/nba/'
path: '/nba'
fullPath: '/nba'
preLoaderRoute: typeof AuthenticatedNbaIndexLazyImport
'/_authenticated/dashboard/sales/coupons': {
id: '/_authenticated/dashboard/sales/coupons'
path: '/dashboard/sales/coupons'
fullPath: '/dashboard/sales/coupons'
preLoaderRoute: typeof AuthenticatedDashboardSalesCouponsLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/settings/': {
id: '/_authenticated/settings/'
'/_authenticated/dashboard/sales/discounts': {
id: '/_authenticated/dashboard/sales/discounts'
path: '/dashboard/sales/discounts'
fullPath: '/dashboard/sales/discounts'
preLoaderRoute: typeof AuthenticatedDashboardSalesDiscountsLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/dashboard/settings/account': {
id: '/_authenticated/dashboard/settings/account'
path: '/account'
fullPath: '/dashboard/settings/account'
preLoaderRoute: typeof AuthenticatedDashboardSettingsAccountLazyImport
parentRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
}
'/_authenticated/dashboard/settings/appearance': {
id: '/_authenticated/dashboard/settings/appearance'
path: '/appearance'
fullPath: '/dashboard/settings/appearance'
preLoaderRoute: typeof AuthenticatedDashboardSettingsAppearanceLazyImport
parentRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
}
'/_authenticated/dashboard/settings/display': {
id: '/_authenticated/dashboard/settings/display'
path: '/display'
fullPath: '/dashboard/settings/display'
preLoaderRoute: typeof AuthenticatedDashboardSettingsDisplayLazyImport
parentRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
}
'/_authenticated/dashboard/settings/notifications': {
id: '/_authenticated/dashboard/settings/notifications'
path: '/notifications'
fullPath: '/dashboard/settings/notifications'
preLoaderRoute: typeof AuthenticatedDashboardSettingsNotificationsLazyImport
parentRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
}
'/_authenticated/dashboard/chats/': {
id: '/_authenticated/dashboard/chats/'
path: '/dashboard/chats'
fullPath: '/dashboard/chats'
preLoaderRoute: typeof AuthenticatedDashboardChatsIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/dashboard/products/': {
id: '/_authenticated/dashboard/products/'
path: '/dashboard/products'
fullPath: '/dashboard/products'
preLoaderRoute: typeof AuthenticatedDashboardProductsIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/dashboard/sales/': {
id: '/_authenticated/dashboard/sales/'
path: '/dashboard/sales'
fullPath: '/dashboard/sales'
preLoaderRoute: typeof AuthenticatedDashboardSalesIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/dashboard/settings/': {
id: '/_authenticated/dashboard/settings/'
path: '/'
fullPath: '/settings/'
preLoaderRoute: typeof AuthenticatedSettingsIndexLazyImport
parentRoute: typeof AuthenticatedSettingsRouteLazyImport
fullPath: '/dashboard/settings/'
preLoaderRoute: typeof AuthenticatedDashboardSettingsIndexLazyImport
parentRoute: typeof AuthenticatedDashboardSettingsRouteLazyImport
}
'/_authenticated/tasks/': {
id: '/_authenticated/tasks/'
path: '/tasks'
fullPath: '/tasks'
preLoaderRoute: typeof AuthenticatedTasksIndexLazyImport
'/_authenticated/dashboard/tasks/': {
id: '/_authenticated/dashboard/tasks/'
path: '/dashboard/tasks'
fullPath: '/dashboard/tasks'
preLoaderRoute: typeof AuthenticatedDashboardTasksIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
'/_authenticated/users/': {
id: '/_authenticated/users/'
path: '/users'
fullPath: '/users'
preLoaderRoute: typeof AuthenticatedUsersIndexLazyImport
'/_authenticated/dashboard/users/': {
id: '/_authenticated/dashboard/users/'
path: '/dashboard/users'
fullPath: '/dashboard/users'
preLoaderRoute: typeof AuthenticatedDashboardUsersIndexLazyImport
parentRoute: typeof AuthenticatedRouteImport
}
}
@@ -482,53 +538,65 @@ declare module '@tanstack/react-router' {
// Create and export the route tree
interface AuthenticatedSettingsRouteLazyRouteChildren {
AuthenticatedSettingsAccountLazyRoute: typeof AuthenticatedSettingsAccountLazyRoute
AuthenticatedSettingsAppearanceLazyRoute: typeof AuthenticatedSettingsAppearanceLazyRoute
AuthenticatedSettingsDisplayLazyRoute: typeof AuthenticatedSettingsDisplayLazyRoute
AuthenticatedSettingsNotificationsLazyRoute: typeof AuthenticatedSettingsNotificationsLazyRoute
AuthenticatedSettingsIndexLazyRoute: typeof AuthenticatedSettingsIndexLazyRoute
interface AuthenticatedDashboardSettingsRouteLazyRouteChildren {
AuthenticatedDashboardSettingsAccountLazyRoute: typeof AuthenticatedDashboardSettingsAccountLazyRoute
AuthenticatedDashboardSettingsAppearanceLazyRoute: typeof AuthenticatedDashboardSettingsAppearanceLazyRoute
AuthenticatedDashboardSettingsDisplayLazyRoute: typeof AuthenticatedDashboardSettingsDisplayLazyRoute
AuthenticatedDashboardSettingsNotificationsLazyRoute: typeof AuthenticatedDashboardSettingsNotificationsLazyRoute
AuthenticatedDashboardSettingsIndexLazyRoute: typeof AuthenticatedDashboardSettingsIndexLazyRoute
}
const AuthenticatedSettingsRouteLazyRouteChildren: AuthenticatedSettingsRouteLazyRouteChildren =
const AuthenticatedDashboardSettingsRouteLazyRouteChildren: AuthenticatedDashboardSettingsRouteLazyRouteChildren =
{
AuthenticatedSettingsAccountLazyRoute:
AuthenticatedSettingsAccountLazyRoute,
AuthenticatedSettingsAppearanceLazyRoute:
AuthenticatedSettingsAppearanceLazyRoute,
AuthenticatedSettingsDisplayLazyRoute:
AuthenticatedSettingsDisplayLazyRoute,
AuthenticatedSettingsNotificationsLazyRoute:
AuthenticatedSettingsNotificationsLazyRoute,
AuthenticatedSettingsIndexLazyRoute: AuthenticatedSettingsIndexLazyRoute,
AuthenticatedDashboardSettingsAccountLazyRoute:
AuthenticatedDashboardSettingsAccountLazyRoute,
AuthenticatedDashboardSettingsAppearanceLazyRoute:
AuthenticatedDashboardSettingsAppearanceLazyRoute,
AuthenticatedDashboardSettingsDisplayLazyRoute:
AuthenticatedDashboardSettingsDisplayLazyRoute,
AuthenticatedDashboardSettingsNotificationsLazyRoute:
AuthenticatedDashboardSettingsNotificationsLazyRoute,
AuthenticatedDashboardSettingsIndexLazyRoute:
AuthenticatedDashboardSettingsIndexLazyRoute,
}
const AuthenticatedSettingsRouteLazyRouteWithChildren =
AuthenticatedSettingsRouteLazyRoute._addFileChildren(
AuthenticatedSettingsRouteLazyRouteChildren,
const AuthenticatedDashboardSettingsRouteLazyRouteWithChildren =
AuthenticatedDashboardSettingsRouteLazyRoute._addFileChildren(
AuthenticatedDashboardSettingsRouteLazyRouteChildren,
)
interface AuthenticatedRouteRouteChildren {
AuthenticatedSettingsRouteLazyRoute: typeof AuthenticatedSettingsRouteLazyRouteWithChildren
AuthenticatedDashboardSettingsRouteLazyRoute: typeof AuthenticatedDashboardSettingsRouteLazyRouteWithChildren
AuthenticatedDashboardIndexRoute: typeof AuthenticatedDashboardIndexRoute
AuthenticatedAppsIndexLazyRoute: typeof AuthenticatedAppsIndexLazyRoute
AuthenticatedChatsIndexLazyRoute: typeof AuthenticatedChatsIndexLazyRoute
AuthenticatedHelpCenterIndexLazyRoute: typeof AuthenticatedHelpCenterIndexLazyRoute
AuthenticatedNbaIndexLazyRoute: typeof AuthenticatedNbaIndexLazyRoute
AuthenticatedTasksIndexLazyRoute: typeof AuthenticatedTasksIndexLazyRoute
AuthenticatedUsersIndexLazyRoute: typeof AuthenticatedUsersIndexLazyRoute
AuthenticatedDashboardSalesCouponsLazyRoute: typeof AuthenticatedDashboardSalesCouponsLazyRoute
AuthenticatedDashboardSalesDiscountsLazyRoute: typeof AuthenticatedDashboardSalesDiscountsLazyRoute
AuthenticatedDashboardChatsIndexLazyRoute: typeof AuthenticatedDashboardChatsIndexLazyRoute
AuthenticatedDashboardProductsIndexLazyRoute: typeof AuthenticatedDashboardProductsIndexLazyRoute
AuthenticatedDashboardSalesIndexLazyRoute: typeof AuthenticatedDashboardSalesIndexLazyRoute
AuthenticatedDashboardTasksIndexLazyRoute: typeof AuthenticatedDashboardTasksIndexLazyRoute
AuthenticatedDashboardUsersIndexLazyRoute: typeof AuthenticatedDashboardUsersIndexLazyRoute
}
const AuthenticatedRouteRouteChildren: AuthenticatedRouteRouteChildren = {
AuthenticatedSettingsRouteLazyRoute:
AuthenticatedSettingsRouteLazyRouteWithChildren,
AuthenticatedDashboardSettingsRouteLazyRoute:
AuthenticatedDashboardSettingsRouteLazyRouteWithChildren,
AuthenticatedDashboardIndexRoute: AuthenticatedDashboardIndexRoute,
AuthenticatedAppsIndexLazyRoute: AuthenticatedAppsIndexLazyRoute,
AuthenticatedChatsIndexLazyRoute: AuthenticatedChatsIndexLazyRoute,
AuthenticatedHelpCenterIndexLazyRoute: AuthenticatedHelpCenterIndexLazyRoute,
AuthenticatedNbaIndexLazyRoute: AuthenticatedNbaIndexLazyRoute,
AuthenticatedTasksIndexLazyRoute: AuthenticatedTasksIndexLazyRoute,
AuthenticatedUsersIndexLazyRoute: AuthenticatedUsersIndexLazyRoute,
AuthenticatedDashboardSalesCouponsLazyRoute:
AuthenticatedDashboardSalesCouponsLazyRoute,
AuthenticatedDashboardSalesDiscountsLazyRoute:
AuthenticatedDashboardSalesDiscountsLazyRoute,
AuthenticatedDashboardChatsIndexLazyRoute:
AuthenticatedDashboardChatsIndexLazyRoute,
AuthenticatedDashboardProductsIndexLazyRoute:
AuthenticatedDashboardProductsIndexLazyRoute,
AuthenticatedDashboardSalesIndexLazyRoute:
AuthenticatedDashboardSalesIndexLazyRoute,
AuthenticatedDashboardTasksIndexLazyRoute:
AuthenticatedDashboardTasksIndexLazyRoute,
AuthenticatedDashboardUsersIndexLazyRoute:
AuthenticatedDashboardUsersIndexLazyRoute,
}
const AuthenticatedRouteRouteWithChildren =
@@ -540,7 +608,6 @@ export interface FileRoutesByFullPath {
'/500': typeof errors500LazyRoute
'/otp': typeof authOtpRoute
'/sign-in': typeof authSignInRoute
'/settings': typeof AuthenticatedSettingsRouteLazyRouteWithChildren
'/forgot-password': typeof authForgotPasswordLazyRoute
'/sign-in-2': typeof authSignIn2LazyRoute
'/sign-up': typeof authSignUpLazyRoute
@@ -548,18 +615,21 @@ export interface FileRoutesByFullPath {
'/403': typeof errors403LazyRoute
'/404': typeof errors404LazyRoute
'/503': typeof errors503LazyRoute
'/settings/account': typeof AuthenticatedSettingsAccountLazyRoute
'/settings/appearance': typeof AuthenticatedSettingsAppearanceLazyRoute
'/settings/display': typeof AuthenticatedSettingsDisplayLazyRoute
'/settings/notifications': typeof AuthenticatedSettingsNotificationsLazyRoute
'/dashboard/settings': typeof AuthenticatedDashboardSettingsRouteLazyRouteWithChildren
'/dashboard': typeof AuthenticatedDashboardIndexRoute
'/apps': typeof AuthenticatedAppsIndexLazyRoute
'/chats': typeof AuthenticatedChatsIndexLazyRoute
'/help-center': typeof AuthenticatedHelpCenterIndexLazyRoute
'/nba': typeof AuthenticatedNbaIndexLazyRoute
'/settings/': typeof AuthenticatedSettingsIndexLazyRoute
'/tasks': typeof AuthenticatedTasksIndexLazyRoute
'/users': typeof AuthenticatedUsersIndexLazyRoute
'/dashboard/sales/coupons': typeof AuthenticatedDashboardSalesCouponsLazyRoute
'/dashboard/sales/discounts': typeof AuthenticatedDashboardSalesDiscountsLazyRoute
'/dashboard/settings/account': typeof AuthenticatedDashboardSettingsAccountLazyRoute
'/dashboard/settings/appearance': typeof AuthenticatedDashboardSettingsAppearanceLazyRoute
'/dashboard/settings/display': typeof AuthenticatedDashboardSettingsDisplayLazyRoute
'/dashboard/settings/notifications': typeof AuthenticatedDashboardSettingsNotificationsLazyRoute
'/dashboard/chats': typeof AuthenticatedDashboardChatsIndexLazyRoute
'/dashboard/products': typeof AuthenticatedDashboardProductsIndexLazyRoute
'/dashboard/sales': typeof AuthenticatedDashboardSalesIndexLazyRoute
'/dashboard/settings/': typeof AuthenticatedDashboardSettingsIndexLazyRoute
'/dashboard/tasks': typeof AuthenticatedDashboardTasksIndexLazyRoute
'/dashboard/users': typeof AuthenticatedDashboardUsersIndexLazyRoute
}
export interface FileRoutesByTo {
@@ -575,18 +645,20 @@ export interface FileRoutesByTo {
'/403': typeof errors403LazyRoute
'/404': typeof errors404LazyRoute
'/503': typeof errors503LazyRoute
'/settings/account': typeof AuthenticatedSettingsAccountLazyRoute
'/settings/appearance': typeof AuthenticatedSettingsAppearanceLazyRoute
'/settings/display': typeof AuthenticatedSettingsDisplayLazyRoute
'/settings/notifications': typeof AuthenticatedSettingsNotificationsLazyRoute
'/dashboard': typeof AuthenticatedDashboardIndexRoute
'/apps': typeof AuthenticatedAppsIndexLazyRoute
'/chats': typeof AuthenticatedChatsIndexLazyRoute
'/help-center': typeof AuthenticatedHelpCenterIndexLazyRoute
'/nba': typeof AuthenticatedNbaIndexLazyRoute
'/settings': typeof AuthenticatedSettingsIndexLazyRoute
'/tasks': typeof AuthenticatedTasksIndexLazyRoute
'/users': typeof AuthenticatedUsersIndexLazyRoute
'/dashboard/sales/coupons': typeof AuthenticatedDashboardSalesCouponsLazyRoute
'/dashboard/sales/discounts': typeof AuthenticatedDashboardSalesDiscountsLazyRoute
'/dashboard/settings/account': typeof AuthenticatedDashboardSettingsAccountLazyRoute
'/dashboard/settings/appearance': typeof AuthenticatedDashboardSettingsAppearanceLazyRoute
'/dashboard/settings/display': typeof AuthenticatedDashboardSettingsDisplayLazyRoute
'/dashboard/settings/notifications': typeof AuthenticatedDashboardSettingsNotificationsLazyRoute
'/dashboard/chats': typeof AuthenticatedDashboardChatsIndexLazyRoute
'/dashboard/products': typeof AuthenticatedDashboardProductsIndexLazyRoute
'/dashboard/sales': typeof AuthenticatedDashboardSalesIndexLazyRoute
'/dashboard/settings': typeof AuthenticatedDashboardSettingsIndexLazyRoute
'/dashboard/tasks': typeof AuthenticatedDashboardTasksIndexLazyRoute
'/dashboard/users': typeof AuthenticatedDashboardUsersIndexLazyRoute
}
export interface FileRoutesById {
@@ -596,7 +668,6 @@ export interface FileRoutesById {
'/(auth)/500': typeof auth500Route
'/(auth)/otp': typeof authOtpRoute
'/(auth)/sign-in': typeof authSignInRoute
'/_authenticated/settings': typeof AuthenticatedSettingsRouteLazyRouteWithChildren
'/(auth)/forgot-password': typeof authForgotPasswordLazyRoute
'/(auth)/sign-in-2': typeof authSignIn2LazyRoute
'/(auth)/sign-up': typeof authSignUpLazyRoute
@@ -605,18 +676,21 @@ export interface FileRoutesById {
'/(errors)/404': typeof errors404LazyRoute
'/(errors)/500': typeof errors500LazyRoute
'/(errors)/503': typeof errors503LazyRoute
'/_authenticated/settings/account': typeof AuthenticatedSettingsAccountLazyRoute
'/_authenticated/settings/appearance': typeof AuthenticatedSettingsAppearanceLazyRoute
'/_authenticated/settings/display': typeof AuthenticatedSettingsDisplayLazyRoute
'/_authenticated/settings/notifications': typeof AuthenticatedSettingsNotificationsLazyRoute
'/_authenticated/dashboard/settings': typeof AuthenticatedDashboardSettingsRouteLazyRouteWithChildren
'/_authenticated/dashboard/': typeof AuthenticatedDashboardIndexRoute
'/_authenticated/apps/': typeof AuthenticatedAppsIndexLazyRoute
'/_authenticated/chats/': typeof AuthenticatedChatsIndexLazyRoute
'/_authenticated/help-center/': typeof AuthenticatedHelpCenterIndexLazyRoute
'/_authenticated/nba/': typeof AuthenticatedNbaIndexLazyRoute
'/_authenticated/settings/': typeof AuthenticatedSettingsIndexLazyRoute
'/_authenticated/tasks/': typeof AuthenticatedTasksIndexLazyRoute
'/_authenticated/users/': typeof AuthenticatedUsersIndexLazyRoute
'/_authenticated/dashboard/sales/coupons': typeof AuthenticatedDashboardSalesCouponsLazyRoute
'/_authenticated/dashboard/sales/discounts': typeof AuthenticatedDashboardSalesDiscountsLazyRoute
'/_authenticated/dashboard/settings/account': typeof AuthenticatedDashboardSettingsAccountLazyRoute
'/_authenticated/dashboard/settings/appearance': typeof AuthenticatedDashboardSettingsAppearanceLazyRoute
'/_authenticated/dashboard/settings/display': typeof AuthenticatedDashboardSettingsDisplayLazyRoute
'/_authenticated/dashboard/settings/notifications': typeof AuthenticatedDashboardSettingsNotificationsLazyRoute
'/_authenticated/dashboard/chats/': typeof AuthenticatedDashboardChatsIndexLazyRoute
'/_authenticated/dashboard/products/': typeof AuthenticatedDashboardProductsIndexLazyRoute
'/_authenticated/dashboard/sales/': typeof AuthenticatedDashboardSalesIndexLazyRoute
'/_authenticated/dashboard/settings/': typeof AuthenticatedDashboardSettingsIndexLazyRoute
'/_authenticated/dashboard/tasks/': typeof AuthenticatedDashboardTasksIndexLazyRoute
'/_authenticated/dashboard/users/': typeof AuthenticatedDashboardUsersIndexLazyRoute
}
export interface FileRouteTypes {
@@ -627,7 +701,6 @@ export interface FileRouteTypes {
| '/500'
| '/otp'
| '/sign-in'
| '/settings'
| '/forgot-password'
| '/sign-in-2'
| '/sign-up'
@@ -635,18 +708,21 @@ export interface FileRouteTypes {
| '/403'
| '/404'
| '/503'
| '/settings/account'
| '/settings/appearance'
| '/settings/display'
| '/settings/notifications'
| '/dashboard/settings'
| '/dashboard'
| '/apps'
| '/chats'
| '/help-center'
| '/nba'
| '/settings/'
| '/tasks'
| '/users'
| '/dashboard/sales/coupons'
| '/dashboard/sales/discounts'
| '/dashboard/settings/account'
| '/dashboard/settings/appearance'
| '/dashboard/settings/display'
| '/dashboard/settings/notifications'
| '/dashboard/chats'
| '/dashboard/products'
| '/dashboard/sales'
| '/dashboard/settings/'
| '/dashboard/tasks'
| '/dashboard/users'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
@@ -661,18 +737,20 @@ export interface FileRouteTypes {
| '/403'
| '/404'
| '/503'
| '/settings/account'
| '/settings/appearance'
| '/settings/display'
| '/settings/notifications'
| '/dashboard'
| '/apps'
| '/chats'
| '/help-center'
| '/nba'
| '/settings'
| '/tasks'
| '/users'
| '/dashboard/sales/coupons'
| '/dashboard/sales/discounts'
| '/dashboard/settings/account'
| '/dashboard/settings/appearance'
| '/dashboard/settings/display'
| '/dashboard/settings/notifications'
| '/dashboard/chats'
| '/dashboard/products'
| '/dashboard/sales'
| '/dashboard/settings'
| '/dashboard/tasks'
| '/dashboard/users'
id:
| '__root__'
| '/'
@@ -680,7 +758,6 @@ export interface FileRouteTypes {
| '/(auth)/500'
| '/(auth)/otp'
| '/(auth)/sign-in'
| '/_authenticated/settings'
| '/(auth)/forgot-password'
| '/(auth)/sign-in-2'
| '/(auth)/sign-up'
@@ -689,18 +766,21 @@ export interface FileRouteTypes {
| '/(errors)/404'
| '/(errors)/500'
| '/(errors)/503'
| '/_authenticated/settings/account'
| '/_authenticated/settings/appearance'
| '/_authenticated/settings/display'
| '/_authenticated/settings/notifications'
| '/_authenticated/dashboard/settings'
| '/_authenticated/dashboard/'
| '/_authenticated/apps/'
| '/_authenticated/chats/'
| '/_authenticated/help-center/'
| '/_authenticated/nba/'
| '/_authenticated/settings/'
| '/_authenticated/tasks/'
| '/_authenticated/users/'
| '/_authenticated/dashboard/sales/coupons'
| '/_authenticated/dashboard/sales/discounts'
| '/_authenticated/dashboard/settings/account'
| '/_authenticated/dashboard/settings/appearance'
| '/_authenticated/dashboard/settings/display'
| '/_authenticated/dashboard/settings/notifications'
| '/_authenticated/dashboard/chats/'
| '/_authenticated/dashboard/products/'
| '/_authenticated/dashboard/sales/'
| '/_authenticated/dashboard/settings/'
| '/_authenticated/dashboard/tasks/'
| '/_authenticated/dashboard/users/'
fileRoutesById: FileRoutesById
}
@@ -767,14 +847,16 @@ export const routeTree = rootRoute
"/_authenticated": {
"filePath": "_authenticated/route.tsx",
"children": [
"/_authenticated/settings",
"/_authenticated/dashboard/settings",
"/_authenticated/dashboard/",
"/_authenticated/apps/",
"/_authenticated/chats/",
"/_authenticated/help-center/",
"/_authenticated/nba/",
"/_authenticated/tasks/",
"/_authenticated/users/"
"/_authenticated/dashboard/sales/coupons",
"/_authenticated/dashboard/sales/discounts",
"/_authenticated/dashboard/chats/",
"/_authenticated/dashboard/products/",
"/_authenticated/dashboard/sales/",
"/_authenticated/dashboard/tasks/",
"/_authenticated/dashboard/users/"
]
},
"/(auth)/500": {
@@ -786,17 +868,6 @@ export const routeTree = rootRoute
"/(auth)/sign-in": {
"filePath": "(auth)/sign-in.tsx"
},
"/_authenticated/settings": {
"filePath": "_authenticated/settings/route.lazy.tsx",
"parent": "/_authenticated",
"children": [
"/_authenticated/settings/account",
"/_authenticated/settings/appearance",
"/_authenticated/settings/display",
"/_authenticated/settings/notifications",
"/_authenticated/settings/"
]
},
"/(auth)/forgot-password": {
"filePath": "(auth)/forgot-password.lazy.tsx"
},
@@ -821,52 +892,71 @@ export const routeTree = rootRoute
"/(errors)/503": {
"filePath": "(errors)/503.lazy.tsx"
},
"/_authenticated/settings/account": {
"filePath": "_authenticated/settings/account.lazy.tsx",
"parent": "/_authenticated/settings"
},
"/_authenticated/settings/appearance": {
"filePath": "_authenticated/settings/appearance.lazy.tsx",
"parent": "/_authenticated/settings"
},
"/_authenticated/settings/display": {
"filePath": "_authenticated/settings/display.lazy.tsx",
"parent": "/_authenticated/settings"
},
"/_authenticated/settings/notifications": {
"filePath": "_authenticated/settings/notifications.lazy.tsx",
"parent": "/_authenticated/settings"
"/_authenticated/dashboard/settings": {
"filePath": "_authenticated/dashboard/settings/route.lazy.tsx",
"parent": "/_authenticated",
"children": [
"/_authenticated/dashboard/settings/account",
"/_authenticated/dashboard/settings/appearance",
"/_authenticated/dashboard/settings/display",
"/_authenticated/dashboard/settings/notifications",
"/_authenticated/dashboard/settings/"
]
},
"/_authenticated/dashboard/": {
"filePath": "_authenticated/dashboard/index.tsx",
"parent": "/_authenticated"
},
"/_authenticated/apps/": {
"filePath": "_authenticated/apps/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/chats/": {
"filePath": "_authenticated/chats/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/help-center/": {
"filePath": "_authenticated/help-center/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/nba/": {
"filePath": "_authenticated/nba/index.lazy.tsx",
"/_authenticated/dashboard/sales/coupons": {
"filePath": "_authenticated/dashboard/sales/coupons.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/settings/": {
"filePath": "_authenticated/settings/index.lazy.tsx",
"parent": "/_authenticated/settings"
},
"/_authenticated/tasks/": {
"filePath": "_authenticated/tasks/index.lazy.tsx",
"/_authenticated/dashboard/sales/discounts": {
"filePath": "_authenticated/dashboard/sales/discounts.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/users/": {
"filePath": "_authenticated/users/index.lazy.tsx",
"/_authenticated/dashboard/settings/account": {
"filePath": "_authenticated/dashboard/settings/account.lazy.tsx",
"parent": "/_authenticated/dashboard/settings"
},
"/_authenticated/dashboard/settings/appearance": {
"filePath": "_authenticated/dashboard/settings/appearance.lazy.tsx",
"parent": "/_authenticated/dashboard/settings"
},
"/_authenticated/dashboard/settings/display": {
"filePath": "_authenticated/dashboard/settings/display.lazy.tsx",
"parent": "/_authenticated/dashboard/settings"
},
"/_authenticated/dashboard/settings/notifications": {
"filePath": "_authenticated/dashboard/settings/notifications.lazy.tsx",
"parent": "/_authenticated/dashboard/settings"
},
"/_authenticated/dashboard/chats/": {
"filePath": "_authenticated/dashboard/chats/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/dashboard/products/": {
"filePath": "_authenticated/dashboard/products/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/dashboard/sales/": {
"filePath": "_authenticated/dashboard/sales/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/dashboard/settings/": {
"filePath": "_authenticated/dashboard/settings/index.lazy.tsx",
"parent": "/_authenticated/dashboard/settings"
},
"/_authenticated/dashboard/tasks/": {
"filePath": "_authenticated/dashboard/tasks/index.lazy.tsx",
"parent": "/_authenticated"
},
"/_authenticated/dashboard/users/": {
"filePath": "_authenticated/dashboard/users/index.lazy.tsx",
"parent": "/_authenticated"
}
}
+10 -2
View File
@@ -1,6 +1,14 @@
import { createFileRoute } from "@tanstack/react-router";
import { createFileRoute, redirect } from "@tanstack/react-router";
import SignIn from "@/pages/auth/sign-in";
import { isLoggedIn } from "@/hooks/useAuth";
export const Route = createFileRoute("/(auth)/sign-in")({
component: SignIn
component: SignIn,
beforeLoad: async() => {
if(isLoggedIn()) {
throw redirect({
to:"/dashboard"
})
}
}
});
@@ -1,6 +0,0 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Apps from "@/pages/apps";
export const Route = createLazyFileRoute("/_authenticated/apps/")({
component: Apps
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Chats from "@/pages/chats";
export const Route = createLazyFileRoute("/_authenticated/chats/")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/chats/")({
component: Chats
});
@@ -0,0 +1,6 @@
import Products from '@/pages/products'
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute('/_authenticated/dashboard/products/')({
component: Products,
})
@@ -0,0 +1,11 @@
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute(
'/_authenticated/dashboard/sales/coupons',
)({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_authenticated/dashboard/discounts/coupons"!</div>
}
@@ -0,0 +1,11 @@
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute(
'/_authenticated/dashboard/sales/discounts',
)({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_authenticated/dashboard/discounts/discounts"!</div>
}
@@ -0,0 +1,11 @@
import { createLazyFileRoute } from '@tanstack/react-router'
export const Route = createLazyFileRoute(
'/_authenticated/dashboard/sales/',
)({
component: RouteComponent,
})
function RouteComponent() {
return <div>Hello "/_authenticated/dashboard/discounts/"!</div>
}
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import SettingsAccount from "@/pages/settings/account";
export const Route = createLazyFileRoute("/_authenticated/settings/account")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/settings/account")({
component: SettingsAccount
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import SettingsAppearance from "@/pages/settings/appearance";
export const Route = createLazyFileRoute("/_authenticated/settings/appearance")(
export const Route = createLazyFileRoute("/_authenticated/dashboard/settings/appearance")(
{ component: SettingsAppearance }
);
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import SettingsDisplay from "@/pages/settings/display";
export const Route = createLazyFileRoute("/_authenticated/settings/display")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/settings/display")({
component: SettingsDisplay
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import SettingsProfile from "@/pages/settings/profile";
export const Route = createLazyFileRoute("/_authenticated/settings/")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/settings/")({
component: SettingsProfile
});
@@ -2,7 +2,7 @@ import { createLazyFileRoute } from "@tanstack/react-router";
import SettingsNotifications from "@/pages/settings/notifications";
export const Route = createLazyFileRoute(
"/_authenticated/settings/notifications"
"/_authenticated/dashboard/settings/notifications"
)({
component: SettingsNotifications
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Settings from "@/pages/settings";
export const Route = createLazyFileRoute("/_authenticated/settings")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/settings")({
component: Settings
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Tasks from "@/pages/tasks";
export const Route = createLazyFileRoute("/_authenticated/tasks/")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/tasks/")({
component: Tasks
});
@@ -1,6 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Users from "@/pages/users";
export const Route = createLazyFileRoute("/_authenticated/users/")({
export const Route = createLazyFileRoute("/_authenticated/dashboard/users/")({
component: Users
});
@@ -1,6 +0,0 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import Nba from "@/pages/nba";
export const Route = createLazyFileRoute("/_authenticated/nba/")({
component: Nba
});
+3 -2
View File
@@ -5,12 +5,13 @@ import { SearchProvider } from "@/context/search-context";
import { SidebarProvider } from "@/components/ui/sidebar";
import { AppSidebar } from "@/components/layout/app-sidebar";
import SkipToMain from "@/components/skip-to-main";
import { isLoggedIn } from "@/hooks/useAuth";
export const Route = createFileRoute("/_authenticated")({
beforeLoad: async ({ location }) => {
if (false) {
if(!isLoggedIn()) {
throw redirect({
to: "/401",
to: "/sign-in",
search: {
redirect: location.href
}