Compare commits

...

7 Commits

Author SHA1 Message Date
fabio 13a198da82 refactor: remove test role YAML configuration call from main function 2026-03-24 20:13:33 +01:00
fabio e917953d6c feat: add role management with roles and permissions configuration 2026-03-24 20:12:35 +01:00
fabio e69e1623b5 feat: add tooltip component and related position engine
- Introduced a new tooltip component (QTooltip) in logo-DdmK5n0b.js for enhanced UI interactions.
- Added position engine logic in position-engine-BHgB6lrx.js to manage tooltip positioning dynamically.
- Implemented selection utility in selection-DrSF90ET.js to handle text selection across different browsers.
- Created a use-quasar hook in use-quasar-B5tVCAcV.js for improved integration with Quasar framework.
2026-03-19 19:13:39 +01:00
fabio 3646b406bb Refactor code structure for improved readability and maintainability 2026-03-19 19:07:45 +01:00
fabio d716da1b69 aggiunto mappa 2026-03-19 18:58:33 +01:00
fabio b62661003c Add new services.html file to the project 2026-03-19 18:50:10 +01:00
fabio 71bb9ea5c3 feat: add authentication pages for login, password recovery, and signup
- Created LoginPage.vue for user login functionality with email and password fields.
- Implemented RecoverPasswordPage.vue to allow users to request a password recovery email.
- Developed SignupPage.vue for new user registration, including form validation and success state.
2026-03-18 19:23:35 +01:00
203 changed files with 6421 additions and 326 deletions

View File

@ -6,9 +6,9 @@
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceFolder}/cmd/server",
"cwd": "${workspaceFolder}",
"envFile": "${workspaceFolder}/.env",
"program": "${workspaceFolder}/backend/cmd/server",
"cwd": "${workspaceFolder}/backend",
"envFile": "${workspaceFolder}/backend/.env",
"args": []
},
{
@ -17,9 +17,9 @@
"request": "launch",
"mode": "debug",
"noDebug": true,
"program": "${workspaceFolder}/cmd/server",
"cwd": "${workspaceFolder}",
"envFile": "${workspaceFolder}/.env",
"program": "${workspaceFolder}/backend/cmd/server",
"cwd": "${workspaceFolder}/backend",
"envFile": "${workspaceFolder}/backend/.env",
"args": []
},
{
@ -29,7 +29,7 @@
"mode": "remote",
"host": "127.0.0.1",
"port": 2345,
"cwd": "${workspaceFolder}"
"cwd": "${workspaceFolder}/backend"
}
]
}

View File

@ -4,7 +4,7 @@
//
// This file was generated by github.com/millevolte/ts-rpc
//
// Mar 15, 2026 16:33:29 UTC
// Mar 17, 2026 18:16:42 UTC
//
export interface ApiRestResponse {
@ -185,6 +185,30 @@ export default class Api {
}
}
async PUT(
url: string,
data: unknown,
timeout?: number,
): Promise<{
data: unknown;
error: string | null;
}> {
try {
const upload = url.includes("/upload/");
const result = await this.request(
"PUT",
this.apiUrl + url,
data,
timeout,
upload,
);
return this.processResult(result);
} catch (error: unknown) {
return this.processError(error);
}
}
async GET(
url: string,
timeout?: number,
@ -205,6 +229,26 @@ export default class Api {
}
}
async DELETE(
url: string,
timeout?: number,
): Promise<{
data: unknown;
error: string | null;
}> {
try {
const result = await this.request(
"DELETE",
this.apiUrl + url,
null,
timeout,
);
return this.processResult(result);
} catch (error: unknown) {
return this.processError(error);
}
}
async UPLOAD(
url: string,
data: unknown,
@ -237,62 +281,218 @@ export type Nullable<T> = T | null;
export type Record<K extends string | number | symbol, T> = { [P in K]: T };
//
// package controllers
// package routes
//
export interface LoginRequest {
username: string;
password: string;
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=models.UserProfile
// internal/http/routes/user_routes.go Line: 13
export const getUser = async (
uuid: string,
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
return (await api.GET(`/users/${uuid}`)) as {
data: UserProfile;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=routes.[]MailDebugItem
// internal/http/routes/system_routes.go Line: 48
export const mailDebug = async (): Promise<{
data: MailDebugItem[];
error: Nullable<string>;
}> => {
return (await api.GET("/maildebug")) as {
data: MailDebugItem[];
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=controllers.LoginRequest; response=auth.TokenPair
// internal/http/routes/auth_routes.go Line: 22
export const login = async (
data: LoginRequest,
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
return (await api.POST("/auth/login", data)) as {
data: TokenPair;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=models.UserCreateInput; response=models.UserShort
// internal/http/routes/auth_routes.go Line: 31
export const register = async (
data: UserCreateInput,
): Promise<{ data: UserShort; error: Nullable<string> }> => {
return (await api.POST("/auth/register", data)) as {
data: UserShort;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
// internal/http/routes/system_routes.go Line: 37
export const metrics = async (): Promise<{
data: string;
error: Nullable<string>;
}> => {
return (await api.GET("/metrics")) as {
data: string;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=controllers.UpdateUserRequest; response=models.UserProfile
// internal/http/routes/user_routes.go Line: 19
export const updateUser = async (
data: UpdateUserRequest,
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
return (await api.PUT("/users/:uuid", data)) as {
data: UserProfile;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 40
export const validToken = async (
data: string,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/valid", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
// internal/http/routes/system_routes.go Line: 34
export const health = async (): Promise<{
data: string;
error: Nullable<string>;
}> => {
return (await api.GET("/health")) as {
data: string;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=controllers.SimpleResponse
// internal/http/routes/user_routes.go Line: 22
export const deleteUser = async (
uuid: string,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.DELETE(`/users/${uuid}`)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=controllers.ResetPasswordRequest; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 37
export const resetPassword = async (
data: ResetPasswordRequest,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/reset", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=models.UserCreateInput; response=models.UserProfile
// internal/http/routes/user_routes.go Line: 16
export const createUser = async (
data: UserCreateInput,
): Promise<{ data: UserProfile; error: Nullable<string> }> => {
return (await api.POST("/users", data)) as {
data: UserProfile;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=controllers.RefreshRequest; response=auth.TokenPair
// internal/http/routes/auth_routes.go Line: 25
export const refresh = async (
data: RefreshRequest,
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
return (await api.POST("/auth/refresh", data)) as {
data: TokenPair;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=models.UserShort
// internal/http/routes/auth_routes.go Line: 28
export const me = async (): Promise<{
data: UserShort;
error: Nullable<string>;
}> => {
return (await api.GET("/auth/me")) as {
data: UserShort;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=controllers.ListUsersRequest; response=models.[]UserShort
// internal/http/routes/admin_routes.go Line: 12
export const listUsers = async (
data: ListUsersRequest,
): Promise<{ data: UserShort[]; error: Nullable<string> }> => {
return (await api.POST("/admin/users", data)) as {
data: UserShort[];
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=controllers.BlockUserRequest; response=models.UserShort
// internal/http/routes/admin_routes.go Line: 15
export const blockUser = async (
data: BlockUserRequest,
): Promise<{ data: UserShort; error: Nullable<string> }> => {
return (await api.PUT("/admin/users/:uuid/block", data)) as {
data: UserShort;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=controllers.ForgotPasswordRequest; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 34
export const forgotPassword = async (
data: ForgotPasswordRequest,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/forgot", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
export interface FormRequest {
req: string;
count: number;
}
export interface RefreshRequest {
refresh_token: string;
export interface FormResponse {
test: string;
}
export interface SimpleResponse {
message: string;
}
export interface ForgotPasswordRequest {
email: string;
}
export interface ResetPasswordRequest {
token: string;
password: string;
}
export interface ListUsersRequest {
page: number;
pageSize: number;
export interface MailDebugItem {
name: string;
content: string;
}
//
// package models
//
export interface UserPreferencesShort {
useIdle: boolean;
idleTimeout: number;
useIdlePassword: boolean;
idlePin: string;
useDirectLogin: boolean;
useQuadcodeLogin: boolean;
sendNoticesMail: boolean;
language: string;
}
export interface UserShort {
email: string;
name: string;
roles: UserRoles;
status: UserStatus;
uuid: string;
details: Nullable<UserDetailsShort>;
preferences: Nullable<UserPreferencesShort>;
avatar: Nullable<string>;
}
export interface UserCreateInput {
name: string;
email: string;
@ -316,14 +516,36 @@ export interface UserDetailsShort {
phone: string;
}
export interface UserShort {
email: string;
name: string;
roles: UserRoles;
status: UserStatus;
uuid: string;
details: Nullable<UserDetailsShort>;
preferences: Nullable<UserPreferencesShort>;
avatar: Nullable<string>;
}
export interface UserPreferencesShort {
useIdle: boolean;
idleTimeout: number;
useIdlePassword: boolean;
idlePin: string;
useDirectLogin: boolean;
useQuadcodeLogin: boolean;
sendNoticesMail: boolean;
language: string;
}
export type UsersShort = UserShort[];
export type UserRoles = string[];
export type UserStatus = (typeof EnumUserStatus)[keyof typeof EnumUserStatus];
export type UserTypes = string[];
export type UsersShort = UserShort[];
export const EnumUserStatus = {
UserStatusPending: "pending",
UserStatusActive: "active",
@ -331,146 +553,50 @@ export const EnumUserStatus = {
} as const;
//
// package routes
// package controllers
//
// Typescript: TSEndpoint= path=/auth/password/valid; name=validToken; method=POST; request=string; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 40
export const validToken = async (
data: string,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/valid", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/maildebug; name=mailDebug; method=GET; response=routes.[]MailDebugItem
// internal/http/routes/system_routes.go Line: 48
export const mailDebug = async (): Promise<{
data: MailDebugItem[];
error: Nullable<string>;
}> => {
return (await api.GET("/maildebug")) as {
data: MailDebugItem[];
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=controllers.ListUsersRequest; response=models.[]UserShort
// internal/http/routes/admin_routes.go Line: 12
export const listUsers = async (
data: ListUsersRequest,
): Promise<{ data: UserShort[]; error: Nullable<string> }> => {
return (await api.POST("/admin/users", data)) as {
data: UserShort[];
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/register; name=register; method=POST; request=models.UserCreateInput; response=models.UserShort
// internal/http/routes/auth_routes.go Line: 31
export const register = async (
data: UserCreateInput,
): Promise<{ data: UserShort; error: Nullable<string> }> => {
return (await api.POST("/auth/register", data)) as {
data: UserShort;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET; response=string
// internal/http/routes/system_routes.go Line: 37
export const metrics = async (): Promise<{
data: string;
error: Nullable<string>;
}> => {
return (await api.GET("/metrics")) as {
data: string;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/login; name=login; method=POST; request=controllers.LoginRequest; response=auth.TokenPair
// internal/http/routes/auth_routes.go Line: 22
export const login = async (
data: LoginRequest,
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
return (await api.POST("/auth/login", data)) as {
data: TokenPair;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST; request=controllers.RefreshRequest; response=auth.TokenPair
// internal/http/routes/auth_routes.go Line: 25
export const refresh = async (
data: RefreshRequest,
): Promise<{ data: TokenPair; error: Nullable<string> }> => {
return (await api.POST("/auth/refresh", data)) as {
data: TokenPair;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST; request=controllers.ForgotPasswordRequest; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 34
export const forgotPassword = async (
data: ForgotPasswordRequest,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/forgot", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST; request=controllers.ResetPasswordRequest; response=controllers.SimpleResponse
// internal/http/routes/auth_routes.go Line: 37
export const resetPassword = async (
data: ResetPasswordRequest,
): Promise<{ data: SimpleResponse; error: Nullable<string> }> => {
return (await api.POST("/auth/password/reset", data)) as {
data: SimpleResponse;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/health; name=health; method=GET; response=string
// internal/http/routes/system_routes.go Line: 34
export const health = async (): Promise<{
data: string;
error: Nullable<string>;
}> => {
return (await api.GET("/health")) as {
data: string;
error: Nullable<string>;
};
};
// Typescript: TSEndpoint= path=/auth/me; name=me; method=GET; response=models.UserShort
// internal/http/routes/auth_routes.go Line: 28
export const me = async (): Promise<{
data: UserShort;
error: Nullable<string>;
}> => {
return (await api.GET("/auth/me")) as {
data: UserShort;
error: Nullable<string>;
};
};
export interface FormRequest {
req: string;
count: number;
export interface ResetPasswordRequest {
token: string;
password: string;
}
export interface FormResponse {
test: string;
export interface RefreshRequest {
refresh_token: string;
}
export interface MailDebugItem {
export interface SimpleResponse {
message: string;
}
export interface UpdateUserRequest {
name: string;
content: string;
email: string;
password: string;
roles: models.UserRoles;
status: models.UserStatus;
types: models.UserTypes;
avatar: Nullable<string>;
details: Nullable<models.UserDetailsShort>;
preferences: Nullable<models.UserPreferencesShort>;
}
export interface BlockUserRequest {
action: string;
}
export interface ForgotPasswordRequest {
email: string;
}
export interface ListUsersRequest {
page: number;
pageSize: number;
}
export interface LoginRequest {
username: string;
password: string;
}
//

Binary file not shown.

View File

View File

@ -0,0 +1,11 @@
role: admin
permissions: 0
roles:
- role: manager
permissions: 0
roles:
- role: user
permissions: 0
roles:
- role: guest
permissions: 0

Binary file not shown.

View File

@ -0,0 +1,45 @@
MIME-Version: 1.0
From: noreply@example.local
To: fabio@prada.ch
Subject: [Fiber Starter] Recupero password
Content-Type: multipart/alternative; boundary="mixed-1773775376128527000"
--mixed-1773775376128527000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ciao Fabio,
abbiamo ricevuto una richiesta di reset password per l'account fabio@prada.ch.
Token reset:
LKPZn3nsJuJYtFyxPgFGVH_XKuS9qu4nBz-di442wk4
Link reset:
http://localhost:9000/#reset-password?token=LKPZn3nsJuJYtFyxPgFGVH_XKuS9qu4nBz-di442wk4
Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.
--mixed-1773775376128527000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Recupero password</title>
</head>
<body style="font-family: Arial, sans-serif; color: #1f2937; line-height: 1.5;">
<h1 style="margin-bottom: 16px;">Recupero password</h1>
<p>Ciao Fabio,</p>
<p>abbiamo ricevuto una richiesta di reset password per l'account <strong>fabio@prada.ch</strong>.</p>
<p>Usa questo token per completare il reset:</p>
<p style="font-size: 20px; font-weight: bold;">LKPZn3nsJuJYtFyxPgFGVH_XKuS9qu4nBz-di442wk4</p>
<p>Oppure apri questo link:</p>
<p><a href="http://localhost:9000/#reset-password?token=LKPZn3nsJuJYtFyxPgFGVH_XKuS9qu4nBz-di442wk4">http://localhost:9000/#reset-password?token=LKPZn3nsJuJYtFyxPgFGVH_XKuS9qu4nBz-di442wk4</a></p>
<p>Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.</p>
</body>
</html>
--mixed-1773775376128527000--

View File

@ -0,0 +1,45 @@
MIME-Version: 1.0
From: noreply@example.local
To: fabio@prada.ch
Subject: [Fiber Starter] Recupero password
Content-Type: multipart/alternative; boundary="mixed-1773775470525236000"
--mixed-1773775470525236000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ciao Fabio,
abbiamo ricevuto una richiesta di reset password per l'account fabio@prada.ch.
Token reset:
GDy0RQJZyF1PEQvIDIzc1Ua01K_lxevYiH_H7hL8k9U
Link reset:
http://localhost:9000/#reset-password?token=GDy0RQJZyF1PEQvIDIzc1Ua01K_lxevYiH_H7hL8k9U
Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.
--mixed-1773775470525236000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Recupero password</title>
</head>
<body style="font-family: Arial, sans-serif; color: #1f2937; line-height: 1.5;">
<h1 style="margin-bottom: 16px;">Recupero password</h1>
<p>Ciao Fabio,</p>
<p>abbiamo ricevuto una richiesta di reset password per l'account <strong>fabio@prada.ch</strong>.</p>
<p>Usa questo token per completare il reset:</p>
<p style="font-size: 20px; font-weight: bold;">GDy0RQJZyF1PEQvIDIzc1Ua01K_lxevYiH_H7hL8k9U</p>
<p>Oppure apri questo link:</p>
<p><a href="http://localhost:9000/#reset-password?token=GDy0RQJZyF1PEQvIDIzc1Ua01K_lxevYiH_H7hL8k9U">http://localhost:9000/#reset-password?token=GDy0RQJZyF1PEQvIDIzc1Ua01K_lxevYiH_H7hL8k9U</a></p>
<p>Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.</p>
</body>
</html>
--mixed-1773775470525236000--

View File

@ -0,0 +1,45 @@
MIME-Version: 1.0
From: noreply@example.local
To: fabio@prada.ch
Subject: [Fiber Starter] Recupero password
Content-Type: multipart/alternative; boundary="mixed-1773775492932473000"
--mixed-1773775492932473000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ciao Fabio,
abbiamo ricevuto una richiesta di reset password per l'account fabio@prada.ch.
Token reset:
jv_pfTFywcT5wZD3yRKA1_Ls1SW5JMmmUiNxrO75Lik
Link reset:
http://localhost:9000/#reset-password?token=jv_pfTFywcT5wZD3yRKA1_Ls1SW5JMmmUiNxrO75Lik
Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.
--mixed-1773775492932473000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Recupero password</title>
</head>
<body style="font-family: Arial, sans-serif; color: #1f2937; line-height: 1.5;">
<h1 style="margin-bottom: 16px;">Recupero password</h1>
<p>Ciao Fabio,</p>
<p>abbiamo ricevuto una richiesta di reset password per l'account <strong>fabio@prada.ch</strong>.</p>
<p>Usa questo token per completare il reset:</p>
<p style="font-size: 20px; font-weight: bold;">jv_pfTFywcT5wZD3yRKA1_Ls1SW5JMmmUiNxrO75Lik</p>
<p>Oppure apri questo link:</p>
<p><a href="http://localhost:9000/#reset-password?token=jv_pfTFywcT5wZD3yRKA1_Ls1SW5JMmmUiNxrO75Lik">http://localhost:9000/#reset-password?token=jv_pfTFywcT5wZD3yRKA1_Ls1SW5JMmmUiNxrO75Lik</a></p>
<p>Il token scade tra 30 minuti. Se non hai richiesto il reset, ignora questa email.</p>
</body>
</html>
--mixed-1773775492932473000--

View File

@ -0,0 +1,35 @@
MIME-Version: 1.0
From: noreply@example.local
To: pippone@test.comm
Subject: [Fiber Starter] Registrazione completata
Content-Type: multipart/alternative; boundary="mixed-1773775705727296000"
--mixed-1773775705727296000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ciao Pippone Pepponi,
la registrazione per l'account pippone@test.comm su Fiber Starter e stata completata correttamente.
Se non hai richiesto tu questa registrazione, contatta subito il supporto.
--mixed-1773775705727296000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Registrazione completata</title>
</head>
<body style="font-family: Arial, sans-serif; color: #1f2937; line-height: 1.5;">
<h1 style="margin-bottom: 16px;">Benvenuto su Fiber Starter</h1>
<p>Ciao Pippone Pepponi,</p>
<p>la registrazione per l'account <strong>pippone@test.comm</strong> e stata completata correttamente.</p>
<p>Se non hai richiesto tu questa registrazione, contatta subito il supporto.</p>
</body>
</html>
--mixed-1773775705727296000--

View File

@ -0,0 +1,35 @@
MIME-Version: 1.0
From: noreply@example.local
To: pippo@erpippi.com
Subject: [Fiber Starter] Registrazione completata
Content-Type: multipart/alternative; boundary="mixed-1773775888993141000"
--mixed-1773775888993141000
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Ciao Pippo Er Pippi,
la registrazione per l'account pippo@erpippi.com su Fiber Starter e stata completata correttamente.
Se non hai richiesto tu questa registrazione, contatta subito il supporto.
--mixed-1773775888993141000
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Registrazione completata</title>
</head>
<body style="font-family: Arial, sans-serif; color: #1f2937; line-height: 1.5;">
<h1 style="margin-bottom: 16px;">Benvenuto su Fiber Starter</h1>
<p>Ciao Pippo Er Pippi,</p>
<p>la registrazione per l'account <strong>pippo@erpippi.com</strong> e stata completata correttamente.</p>
<p>Se non hai richiesto tu questa registrazione, contatta subito il supporto.</p>
</body>
</html>
--mixed-1773775888993141000--

View File

@ -0,0 +1,21 @@
package auth
type Permission int
type Role struct {
Name string
Permissions Permission
}
const (
AdminPermission Permission = 0xff - (1<<iota - 1)
ManagerPermission
UserPermission
GuestPermission
)
var Roles = []Role{
{"admin", AdminPermission},
{"manager", ManagerPermission},
{"user", UserPermission},
{"guest", GuestPermission},
}

View File

@ -1,7 +1,11 @@
package controllers
import (
"errors"
"time"
"github.com/gofiber/fiber/v3"
"gorm.io/gorm"
"server/internal/models"
)
@ -18,6 +22,11 @@ type ListUsersRequest struct {
PageSize int `json:"pageSize" validate:"omitempty,min=1,max=100"`
}
// Typescript: interface
type BlockUserRequest struct {
Action string `json:"action" validate:"required,oneof=block unblock"`
}
// ListUsers returns a paginated list of users (requires admin permissions).
func (ac *AdminController) ListUsers(c fiber.Ctx) error {
var req ListUsersRequest
@ -63,3 +72,48 @@ func (ac *AdminController) ListUsers(c fiber.Ctx) error {
"error": nil,
})
}
// BlockUser blocks or unblocks a user account by UUID.
func (ac *AdminController) BlockUser(c fiber.Ctx) error {
var req BlockUserRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validateStruct(&req); err != nil {
return err
}
db, err := dbFromCtx(c)
if err != nil {
return err
}
uuid := c.Params("uuid")
if uuid == "" {
return fiber.NewError(fiber.StatusBadRequest, "invalid user uuid")
}
var user models.User
if err := db.Preload("Details").Preload("Preferences").Where("uuid = ?", uuid).First(&user).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, "user not found")
}
return fiber.NewError(fiber.StatusInternalServerError, "failed to load user")
}
switch req.Action {
case "block":
user.Status = models.UserStatusDisabled
case "unblock":
user.Status = models.UserStatusActive
default:
return fiber.NewError(fiber.StatusBadRequest, "invalid action")
}
user.UpdatedAt = time.Now().UTC()
if err := db.Save(&user).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to update user status")
}
return c.JSON(success(models.ToUserShort(&user)))
}

View File

@ -32,3 +32,19 @@ func toUserDetails(d *models.UserDetailsShort) *models.UserDetails {
Phone: d.Phone,
}
}
func toUserPreferences(p *models.UserPreferencesShort) *models.UserPreferences {
if p == nil {
return nil
}
return &models.UserPreferences{
UseIdle: p.UseIdle,
IdleTimeout: p.IdleTimeout,
UseIdlePassword: p.UseIdlePassword,
IdlePin: p.IdlePin,
UseDirectLogin: p.UseDirectLogin,
UseQuadcodeLogin: p.UseQuadcodeLogin,
SendNoticesMail: p.SendNoticesMail,
Language: p.Language,
}
}

View File

@ -0,0 +1,306 @@
package controllers
import (
"errors"
"strconv"
"time"
"github.com/gofiber/fiber/v3"
"github.com/google/uuid"
"gorm.io/gorm"
"server/internal/auth"
"server/internal/models"
)
type UserController struct{}
func NewUserController() *UserController {
return &UserController{}
}
// Typescript: interface
type UpdateUserRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"omitempty,min=8,max=128"`
Roles models.UserRoles `json:"roles"`
Status models.UserStatus `json:"status"`
Types models.UserTypes `json:"types"`
Avatar *string `json:"avatar"`
Details *models.UserDetailsShort `json:"details"`
Preferences *models.UserPreferencesShort `json:"preferences"`
}
// GetUser returns a single user by UUID.
func (uc *UserController) GetUser(c fiber.Ctx) error {
user, err := loadUserByUUID(c)
if err != nil {
return err
}
return c.JSON(success(models.ToUserProfile(user)))
}
// CreateUser creates a user together with optional details and preferences.
func (uc *UserController) CreateUser(c fiber.Ctx) error {
var req models.UserCreateInput
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validateStruct(&req); err != nil {
return err
}
db, err := dbFromCtx(c)
if err != nil {
return err
}
var existing models.User
if err := db.Where("email = ?", req.Email).First(&existing).Error; err == nil {
return fiber.NewError(fiber.StatusConflict, "user already exists")
} else if !errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusInternalServerError, "failed to check user")
}
hashedPassword, err := auth.HashPassword(req.Password)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to secure password")
}
now := time.Now().UTC()
user := models.User{
Email: req.Email,
Name: req.Name,
Password: hashedPassword,
Roles: func() models.UserRoles {
if len(req.Roles) == 0 {
return models.UserRoles{"user"}
}
return req.Roles
}(),
Status: func() models.UserStatus {
if req.Status == "" {
return models.UserStatusPending
}
return req.Status
}(),
Types: func() models.UserTypes {
if len(req.Types) == 0 {
return models.UserTypes{"internal"}
}
return req.Types
}(),
Avatar: req.Avatar,
UUID: uuid.NewString(),
Details: toUserDetails(req.Details),
Preferences: toUserPreferences(req.Preferences),
CreatedAt: now,
UpdatedAt: now,
}
if err := db.Create(&user).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to create user")
}
if err := db.Preload("Details").Preload("Preferences").First(&user, user.ID).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to reload user")
}
return c.Status(fiber.StatusCreated).JSON(success(models.ToUserProfile(&user)))
}
// UpdateUser replaces user fields and synchronizes details/preferences.
func (uc *UserController) UpdateUser(c fiber.Ctx) error {
var req UpdateUserRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid payload")
}
if err := validateStruct(&req); err != nil {
return err
}
db, err := dbFromCtx(c)
if err != nil {
return err
}
user, err := loadUserByUUID(c)
if err != nil {
return err
}
if req.Email != user.Email {
var existing models.User
if err := db.Select("id").Where("email = ?", req.Email).First(&existing).Error; err == nil && existing.ID != user.ID {
return fiber.NewError(fiber.StatusConflict, "user already exists")
} else if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusInternalServerError, "failed to check user")
}
}
now := time.Now().UTC()
user.Name = req.Name
user.Email = req.Email
user.Avatar = req.Avatar
user.UpdatedAt = now
if req.Status != "" {
user.Status = req.Status
}
if len(req.Roles) > 0 {
user.Roles = req.Roles
}
if len(req.Types) > 0 {
user.Types = req.Types
}
if err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Save(user).Error; err != nil {
return err
}
if err := syncUserDetails(tx, user.ID, req.Details); err != nil {
return err
}
if err := syncUserPreferences(tx, user.ID, req.Preferences); err != nil {
return err
}
return nil
}); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to update user")
}
if err := db.Preload("Details").Preload("Preferences").First(user, user.ID).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to reload user")
}
return c.JSON(success(models.ToUserProfile(user)))
}
// DeleteUser removes a user and linked details/preferences through cascading delete rules.
func (uc *UserController) DeleteUser(c fiber.Ctx) error {
db, err := dbFromCtx(c)
if err != nil {
return err
}
user, err := loadUserByID(c)
if err != nil {
return err
}
if err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("user_id = ?", user.ID).Delete(&models.UserDetails{}).Error; err != nil {
return err
}
if err := tx.Where("user_id = ?", user.ID).Delete(&models.UserPreferences{}).Error; err != nil {
return err
}
return tx.Delete(user).Error
}); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "failed to delete user")
}
return c.JSON(success(SimpleResponse{Message: "user deleted"}))
}
func loadUserByID(c fiber.Ctx) (*models.User, error) {
id, err := strconv.Atoi(c.Params("id"))
if err != nil || id <= 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "invalid user id")
}
db, err := dbFromCtx(c)
if err != nil {
return nil, err
}
var user models.User
if err := db.Preload("Details").Preload("Preferences").First(&user, id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "user not found")
}
return nil, fiber.NewError(fiber.StatusInternalServerError, "failed to load user")
}
return &user, nil
}
func loadUserByUUID(c fiber.Ctx) (*models.User, error) {
uuid := c.Params("uuid")
if uuid == "" {
return nil, fiber.NewError(fiber.StatusBadRequest, "invalid user uuid")
}
db, err := dbFromCtx(c)
if err != nil {
return nil, err
}
var user models.User
if err := db.Preload("Details").Preload("Preferences").First(&user, "uuid = ?", uuid).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "user not found")
}
return nil, fiber.NewError(fiber.StatusInternalServerError, "failed to load user")
}
return &user, nil
}
func syncUserDetails(tx *gorm.DB, userID int, input *models.UserDetailsShort) error {
if input == nil {
return tx.Where("user_id = ?", userID).Delete(&models.UserDetails{}).Error
}
var details models.UserDetails
if err := tx.Where("user_id = ?", userID).First(&details).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
details = models.UserDetails{UserID: userID}
} else {
return err
}
}
details.Title = input.Title
details.FirstName = input.FirstName
details.LastName = input.LastName
details.Address = input.Address
details.City = input.City
details.ZipCode = input.ZipCode
details.Country = input.Country
details.Phone = input.Phone
if details.ID == 0 {
return tx.Create(&details).Error
}
return tx.Save(&details).Error
}
func syncUserPreferences(tx *gorm.DB, userID int, input *models.UserPreferencesShort) error {
if input == nil {
return tx.Where("user_id = ?", userID).Delete(&models.UserPreferences{}).Error
}
var preferences models.UserPreferences
if err := tx.Where("user_id = ?", userID).First(&preferences).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
preferences = models.UserPreferences{UserID: userID}
} else {
return err
}
}
preferences.UseIdle = input.UseIdle
preferences.IdleTimeout = input.IdleTimeout
preferences.UseIdlePassword = input.UseIdlePassword
preferences.IdlePin = input.IdlePin
preferences.UseDirectLogin = input.UseDirectLogin
preferences.UseQuadcodeLogin = input.UseQuadcodeLogin
preferences.SendNoticesMail = input.SendNoticesMail
preferences.Language = input.Language
if preferences.ID == 0 {
return tx.Create(&preferences).Error
}
return tx.Save(&preferences).Error
}

View File

@ -11,4 +11,7 @@ func registerAdminRoutes(app *fiber.App) {
// Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST; request=controllers.ListUsersRequest; response=models.[]UserShort
app.Post("/admin/users", adminController.ListUsers)
// Typescript: TSEndpoint= path=/admin/users/:uuid/block; name=blockUser; method=PUT; request=controllers.BlockUserRequest; response=models.UserShort
app.Put("/admin/users/:uuid/block", adminController.BlockUser)
}

View File

@ -21,5 +21,6 @@ type FormResponse struct {
func Register(app *fiber.App, authService *auth.Service, mailService *mail.Service) {
registerSystemRoutes(app)
registerAuthRoutes(app, authService, mailService)
registerUserRoutes(app, authService)
registerAdminRoutes(app)
}

View File

@ -0,0 +1,24 @@
package routes
import (
"server/internal/auth"
"server/internal/http/controllers"
"github.com/gofiber/fiber/v3"
)
func registerUserRoutes(app *fiber.App, authService *auth.Service) {
userController := controllers.NewUserController()
// Typescript: TSEndpoint= path=/users/:uuid; name=getUser; method=GET; response=models.UserProfile
app.Get("/users/:uuid", authService.Middleware(), userController.GetUser)
// Typescript: TSEndpoint= path=/users; name=createUser; method=POST; request=models.UserCreateInput; response=models.UserProfile
app.Post("/users", authService.Middleware(), userController.CreateUser)
// Typescript: TSEndpoint= path=/users/:uuid; name=updateUser; method=PUT; request=controllers.UpdateUserRequest; response=models.UserProfile
app.Put("/users/:uuid", authService.Middleware(), userController.UpdateUser)
// Typescript: TSEndpoint= path=/users/:uuid; name=deleteUser; method=DELETE; response=controllers.SimpleResponse
app.Delete("/users/:uuid", authService.Middleware(), userController.DeleteUser)
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.about-page[data-v-75f77401]{background:linear-gradient(180deg,#f6fbf8,#fff 36%,#eef5ff);color:#163047}.page-shell[data-v-75f77401]{width:min(1180px,100% - 32px);margin:0 auto}.hero-section[data-v-75f77401]{padding:72px 0 56px}.hero-copy[data-v-75f77401]{padding-right:20px}.eyebrow[data-v-75f77401]{display:inline-flex;align-items:center;padding:10px 16px;margin-bottom:22px;border-radius:999px;background:#0d94881f;color:#0f766e;font-size:.9rem;font-weight:800}.hero-title[data-v-75f77401]{margin:0 0 18px;font-size:clamp(2.8rem,5vw,4.6rem);line-height:1;font-weight:800;letter-spacing:-.04em}.hero-text[data-v-75f77401]{max-width:560px;margin:0 0 26px;font-size:1.08rem;line-height:1.7;color:#55687c}.hero-actions[data-v-75f77401]{display:flex;flex-wrap:wrap;gap:14px;margin-bottom:30px}.stats-row[data-v-75f77401]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px}.stat-card[data-v-75f77401]{padding:20px;border-radius:24px;background:#ffffffe0;box-shadow:0 24px 60px #16304714}.stat-value[data-v-75f77401]{font-size:1.8rem;font-weight:800}.stat-label[data-v-75f77401]{margin-top:8px;color:#647789;line-height:1.5}.hero-visual[data-v-75f77401]{position:relative;min-height:620px}.hero-visual[data-v-75f77401]:before{content:"";position:absolute;top:40px;right:18px;bottom:32px;left:56px;border-radius:40px;background:linear-gradient(145deg,#dff7ee,#dbeafe)}.hero-image-main[data-v-75f77401],.hero-image-secondary[data-v-75f77401]{position:absolute;overflow:hidden;border-radius:34px;box-shadow:0 28px 70px #16304729}.hero-image-main[data-v-75f77401]{top:0;right:0;width:min(82%,460px)}.hero-image-secondary[data-v-75f77401]{left:0;bottom:0;width:min(54%,300px);border:8px solid rgba(255,255,255,.95)}.hero-image-main img[data-v-75f77401],.hero-image-secondary img[data-v-75f77401]{display:block;width:100%;height:auto}.floating-summary[data-v-75f77401]{position:absolute;left:28px;top:48px;padding:18px 20px;border-radius:22px;background:#fffffff0;box-shadow:0 18px 50px #16304724}.floating-summary-value[data-v-75f77401]{font-size:1.6rem;font-weight:800}.floating-summary-label[data-v-75f77401]{margin-top:6px;color:#647789}.values-section[data-v-75f77401],.journey-section[data-v-75f77401],.team-section[data-v-75f77401]{padding:56px 0}.journey-section[data-v-75f77401]{background:#ffffff9e}.section-heading[data-v-75f77401]{max-width:700px;margin-bottom:30px}.align-center[data-v-75f77401]{margin-left:auto;margin-right:auto;text-align:center}.section-kicker[data-v-75f77401]{margin-bottom:10px;color:#0f766e;font-size:.85rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.section-title[data-v-75f77401]{margin:0 0 14px;font-size:clamp(2rem,4vw,3.2rem);line-height:1.05;font-weight:800;letter-spacing:-.03em}.section-text[data-v-75f77401]{margin:0;color:#607284;line-height:1.7;font-size:1.02rem}.value-card[data-v-75f77401],.step-card[data-v-75f77401],.team-card[data-v-75f77401]{height:100%;border-radius:28px;background:#ffffffe0;box-shadow:0 24px 70px #16304714}.value-card[data-v-75f77401]{padding:28px}.value-icon[data-v-75f77401]{width:58px;height:58px;margin-bottom:18px}.value-title[data-v-75f77401],.step-title[data-v-75f77401]{margin:0 0 12px;font-size:1.3rem;font-weight:800}.value-text[data-v-75f77401],.step-text[data-v-75f77401]{margin:0;color:#647789;line-height:1.65}.step-card[data-v-75f77401]{overflow:hidden}.step-image[data-v-75f77401],.team-image[data-v-75f77401]{display:block;width:100%;height:220px;object-fit:cover}.step-number[data-v-75f77401]{padding:22px 24px 0;color:#0f766e;font-size:.9rem;font-weight:800;letter-spacing:.08em}.step-title[data-v-75f77401],.step-text[data-v-75f77401]{padding-left:24px;padding-right:24px}.step-text[data-v-75f77401]{padding-bottom:24px}.team-content[data-v-75f77401]{padding:22px}.team-name[data-v-75f77401]{font-size:1.16rem;font-weight:800}.team-role[data-v-75f77401]{margin-top:6px;color:#647789}@media(max-width:1023px){.hero-copy[data-v-75f77401]{padding-right:0}.stats-row[data-v-75f77401]{grid-template-columns:1fr}.hero-visual[data-v-75f77401]{min-height:540px;margin-top:16px}}@media(max-width:599px){.page-shell[data-v-75f77401]{width:min(100% - 24px,1180px)}.hero-section[data-v-75f77401],.values-section[data-v-75f77401],.journey-section[data-v-75f77401],.team-section[data-v-75f77401]{padding:40px 0}.hero-title[data-v-75f77401]{font-size:2.5rem}.hero-visual[data-v-75f77401]{min-height:420px}.hero-visual[data-v-75f77401]:before{top:28px;right:0;bottom:20px;left:18px;border-radius:30px}.hero-image-main[data-v-75f77401]{width:84%}.hero-image-secondary[data-v-75f77401]{width:46%;border-width:6px}.floating-summary[data-v-75f77401]{left:12px;top:22px;padding:14px 16px}}

View File

@ -0,0 +1 @@
import{a as v,u as Q,g as b,h as k,i as g,j as e,k as a,Q as w,n as o,p as u,t as n,m as x,y as i,D}from"./index-DAvBaevK.js";import{Q as L,a as V,b as C,c as I}from"./QLayout-DZVoSyXn.js";import{Q as T}from"./QToolbar-DdNWxglI.js";import{b as r,Q as f,a as l}from"./format-DaKpMo2W.js";import{Q as h}from"./QResizeObserver-CenQZ1Fm.js";import{Q as y}from"./QDrawer-1VLwP6kh.js";import"./touch-BjYP5sR0.js";import"./selection-DrSF90ET.js";const F=v({__name:"AdminLayout",setup(B){const{t}=Q(),d=D(!1);function m(){d.value=!d.value}return(p,s)=>{const _=b("router-view");return k(),g(I,{view:"lHh Lpr lFf"},{default:e(()=>[a(L,{elevated:""},{default:e(()=>[a(T,null,{default:e(()=>[a(w,{flat:"",dense:"",round:"",icon:"menu","aria-label":o(t)("app.menu"),onClick:m},null,8,["aria-label"]),a(V,null,{default:e(()=>[u(n(o(t)("app.title"))+" Admin",1)]),_:1}),x("div",null,"Quasar v"+n(p.$q.version),1)]),_:1})]),_:1}),a(y,{modelValue:d.value,"onUpdate:modelValue":s[0]||(s[0]=c=>d.value=c),"show-if-above":"",bordered:""},{default:e(()=>[a(h,null,{default:e(()=>[a(r,{header:""},{default:e(()=>[u(n(o(t)("app.links")),1)]),_:1}),a(f,{clickable:"",to:"/",exact:""},{default:e(()=>[a(l,{avatar:""},{default:e(()=>[a(i,{name:"home"})]),_:1}),a(l,null,{default:e(()=>[a(r,null,{default:e(()=>[u(n(o(t)("app.home")),1)]),_:1})]),_:1})]),_:1}),a(f,{clickable:"",to:"/dev/api/endpoints",exact:""},{default:e(()=>[a(l,{avatar:""},{default:e(()=>[a(i,{name:"api"})]),_:1}),a(l,null,{default:e(()=>[a(r,null,{default:e(()=>[u(n(o(t)("dev.apiEndpointsTester")),1)]),_:1})]),_:1})]),_:1}),a(f,{clickable:"",to:"/dev/api/mail-debug",exact:""},{default:e(()=>[a(l,{avatar:""},{default:e(()=>[a(i,{name:"mail"})]),_:1}),a(l,null,{default:e(()=>[a(r,null,{default:e(()=>[u(n(o(t)("dev.mailDebug")),1)]),_:1})]),_:1})]),_:1}),a(f,{clickable:"",to:"/admin/users",exact:""},{default:e(()=>[a(l,{avatar:""},{default:e(()=>[a(i,{name:"manage_accounts"})]),_:1}),a(l,null,{default:e(()=>[a(r,null,{default:e(()=>[...s[1]||(s[1]=[u("Users",-1)])]),_:1})]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"]),a(C,null,{default:e(()=>[a(_)]),_:1})]),_:1})}}});export{F as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{a8 as s,aK as a,aW as d,aX as c}from"./index-DAvBaevK.js";function p(e){if(e===!1)return 0;if(e===!0||e===void 0)return 1;const t=parseInt(e,10);return isNaN(t)?0:t}const u=s({name:"close-popup",beforeMount(e,{value:t}){const o={depth:p(t),handler(r){o.depth!==0&&setTimeout(()=>{const n=d(e);n!==void 0&&c(n,r,o.depth)})},handlerKey(r){a(r,13)===!0&&o.handler(r)}};e.__qclosepopup=o,e.addEventListener("click",o.handler),e.addEventListener("keyup",o.handlerKey)},updated(e,{value:t,oldValue:o}){t!==o&&(e.__qclosepopup.depth=p(t))},beforeUnmount(e){const t=e.__qclosepopup;e.removeEventListener("click",t.handler),e.removeEventListener("keyup",t.handlerKey),delete e.__qclosepopup}});export{u as C};

View File

@ -0,0 +1 @@
import{a as h,h as i,i as b,j as l,k as o,m as e,s as d,G as m,H as u,F as r,t as c,Q as p,p as v,I as _,J as n,K as k}from"./index-DAvBaevK.js";import{Q as x}from"./logo-DdmK5n0b.js";import{Q as y}from"./QForm-CgLsd63I.js";import{Q as V}from"./QPage-B68JuyjH.js";import{H as w,p as C,l as I,m as Q,f as U,i as E,w as F,a as H}from"./HomeHeader-oAwoUp8W.js";import{_ as P}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./position-engine-BHgB6lrx.js";import"./selection-DrSF90ET.js";import"./QToolbar-DdNWxglI.js";const B={class:"contact-section"},S={class:"page-shell"},W={class:"contact-layout"},z={class:"contact-info-panel"},q={class:"contact-info-list"},N=["src","alt"],R={class:"contact-card-title"},T={class:"contact-card-text"},A={class:"social-row"},G={class:"social-links"},L=["src","alt"],M={class:"form-grid"},j={class:"reach-section"},D={class:"page-shell"},J="https://maps.google.com/maps?q=403%20Port%20Washington%20Road%2C%20Canada&z=14&output=embed",K=h({__name:"ContactUsPage",setup(O){const s=k({name:"",email:"",phone:"",message:""}),f=[{title:"Contact details",text:"+01-787-582-568",icon:C},{title:"Address",text:"403, Port Washington Road, Canada",icon:I},{title:"Email us",text:"info@domain.com",icon:Q}],g=[{icon:U,label:"Facebook"},{icon:E,label:"Instagram"},{icon:F,label:"WhatsApp"}];return(X,t)=>(i(),b(V,{class:"contact-page"},{default:l(()=>[o(w),e("section",B,[e("div",S,[e("div",W,[e("div",z,[t[6]||(t[6]=e("div",{class:"section-kicker"},"Contact us",-1)),t[7]||(t[7]=e("h1",{class:"section-title"},"Reach out for questions, appointments, or support",-1)),t[8]||(t[8]=e("p",{class:"section-text"}," We take the time to understand your individual needs and goals, creating customized treatment plans to help you achieve optimal health and peace of mind. ",-1)),e("div",q,[(i(),d(m,null,u(f,a=>o(r,{key:a.title,flat:"",class:"contact-info-card"},{default:l(()=>[e("img",{class:"contact-icon",src:a.icon,alt:a.title},null,8,N),e("div",null,[e("div",R,c(a.title),1),e("div",T,c(a.text),1)])]),_:2},1024)),64))]),e("div",A,[t[5]||(t[5]=e("span",{class:"social-label"},"Follow us:",-1)),e("div",G,[(i(),d(m,null,u(g,a=>o(p,{key:a.label,round:"",flat:"",dense:"",class:"social-btn","aria-label":a.label},{default:l(()=>[o(x,null,{default:l(()=>[v(c(a.label),1)]),_:2},1024),e("img",{class:"social-icon",src:a.icon,alt:a.label},null,8,L)]),_:2},1032,["aria-label"])),64))])])]),o(r,{flat:"",class:"contact-form-card"},{default:l(()=>[t[9]||(t[9]=e("div",{class:"form-kicker"},"Contact form",-1)),t[10]||(t[10]=e("h2",{class:"form-title"},"Send us a message",-1)),t[11]||(t[11]=e("p",{class:"form-text"}," Share your question and our team will get back to you with the most relevant next step. ",-1)),o(y,{class:"contact-form",onSubmit:t[4]||(t[4]=_(()=>{},["prevent"]))},{default:l(()=>[o(n,{modelValue:s.name,"onUpdate:modelValue":t[0]||(t[0]=a=>s.name=a),outlined:"",label:"Full name",placeholder:"Enter your name"},null,8,["modelValue"]),e("div",M,[o(n,{modelValue:s.email,"onUpdate:modelValue":t[1]||(t[1]=a=>s.email=a),outlined:"",type:"email",label:"Email",placeholder:"Enter your email"},null,8,["modelValue"]),o(n,{modelValue:s.phone,"onUpdate:modelValue":t[2]||(t[2]=a=>s.phone=a),outlined:"",label:"Phone",placeholder:"Enter your number"},null,8,["modelValue"])]),o(n,{modelValue:s.message,"onUpdate:modelValue":t[3]||(t[3]=a=>s.message=a),outlined:"",autogrow:"",type:"textarea",label:"Message",placeholder:"Write message..."},null,8,["modelValue"]),o(p,{unelevated:"",rounded:"","no-caps":"",color:"primary",label:"Submit now",class:"submit-btn"})]),_:1})]),_:1})])])]),e("section",j,[e("div",D,[t[12]||(t[12]=e("div",{class:"reach-heading"},[e("div",{class:"section-kicker"},"How to reach us"),e("h2",{class:"section-title center"},"Get in touch with us"),e("p",{class:"section-text center"}," The goal of our clinic is to deliver compassionate care and exceptional medical services, including general consultations, specialized treatments, and preventive care. ")],-1)),o(r,{flat:"",class:"map-card"},{default:l(()=>[e("iframe",{class:"map-frame",src:J,title:"Clinic location map",loading:"lazy",referrerpolicy:"no-referrer-when-downgrade"})]),_:1})])]),o(H)]),_:1}))}}),ne=P(K,[["__scopeId","data-v-c049bad3"]]);export{ne as default};

View File

@ -0,0 +1 @@
.contact-page[data-v-c049bad3]{background:linear-gradient(180deg,#f6fbf8,#fff 34%,#eef5ff);color:#163047}.page-shell[data-v-c049bad3]{width:min(1180px,100% - 32px);margin:0 auto}.contact-section[data-v-c049bad3],.reach-section[data-v-c049bad3]{padding:64px 0}.contact-layout[data-v-c049bad3]{display:grid;grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);gap:24px}.contact-info-panel[data-v-c049bad3],.contact-form-card[data-v-c049bad3],.map-card[data-v-c049bad3]{border-radius:32px;background:#ffffffe6;box-shadow:0 24px 70px #16304714}.contact-info-panel[data-v-c049bad3]{padding:34px;background:linear-gradient(145deg,#dff7ee,#dbeafe)}.section-kicker[data-v-c049bad3],.form-kicker[data-v-c049bad3]{margin-bottom:10px;color:#0f766e;font-size:.85rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.section-title[data-v-c049bad3],.form-title[data-v-c049bad3]{margin:0 0 14px;font-size:clamp(2rem,4vw,3.2rem);line-height:1.05;font-weight:800;letter-spacing:-.03em}.section-text[data-v-c049bad3],.form-text[data-v-c049bad3],.map-text[data-v-c049bad3]{margin:0;color:#607284;line-height:1.7;font-size:1.02rem}.contact-info-list[data-v-c049bad3]{display:grid;gap:14px;margin-top:28px}.contact-info-card[data-v-c049bad3]{display:flex;align-items:center;gap:16px;padding:18px 20px;border-radius:22px;background:#ffffffb8}.contact-icon[data-v-c049bad3]{width:54px;height:54px;flex:0 0 auto}.contact-card-title[data-v-c049bad3]{font-weight:800;margin-bottom:4px}.contact-card-text[data-v-c049bad3]{color:#5f7386}.social-row[data-v-c049bad3]{display:flex;align-items:center;flex-wrap:wrap;gap:12px;margin-top:24px}.social-label[data-v-c049bad3]{font-weight:700}.social-links[data-v-c049bad3]{display:flex;gap:6px}.social-btn[data-v-c049bad3]{color:#163047}.social-icon[data-v-c049bad3]{display:block;width:22px;height:22px}.contact-form-card[data-v-c049bad3]{padding:34px}.contact-form[data-v-c049bad3]{display:grid;gap:18px;margin-top:24px}.form-grid[data-v-c049bad3]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.submit-btn[data-v-c049bad3]{justify-self:start;min-width:180px}.reach-heading[data-v-c049bad3]{max-width:760px;margin:0 auto 30px}.center[data-v-c049bad3]{text-align:center}.map-card[data-v-c049bad3]{overflow:hidden;padding:18px}.map-frame[data-v-c049bad3]{display:block;width:100%;height:550px;border:0;border-radius:24px;filter:grayscale(1);transition:filter .2s ease}.map-frame[data-v-c049bad3]:hover{filter:grayscale(0)}@media(max-width:1023px){.contact-layout[data-v-c049bad3]{grid-template-columns:1fr}}@media(max-width:599px){.page-shell[data-v-c049bad3]{width:min(100% - 24px,1180px)}.contact-section[data-v-c049bad3],.reach-section[data-v-c049bad3]{padding:40px 0}.contact-info-panel[data-v-c049bad3],.contact-form-card[data-v-c049bad3]{padding:24px}.form-grid[data-v-c049bad3]{grid-template-columns:1fr}.section-title[data-v-c049bad3],.form-title[data-v-c049bad3]{font-size:2.4rem}}

View File

@ -0,0 +1 @@
import{a as v,u as Q,g as b,h as k,i as w,j as a,k as e,Q as g,n as t,p as n,t as o,m as D,y as d,D as h}from"./index-DAvBaevK.js";import{Q as x,a as L,b as V,c as C}from"./QLayout-DZVoSyXn.js";import{Q as I}from"./QToolbar-DdNWxglI.js";import{b as s,Q as i,a as u}from"./format-DaKpMo2W.js";import{Q as T}from"./QResizeObserver-CenQZ1Fm.js";import{Q as y}from"./QDrawer-1VLwP6kh.js";import"./touch-BjYP5sR0.js";import"./selection-DrSF90ET.js";const P=v({__name:"DevLayout",setup(B){const{t:l}=Q(),r=h(!1);function m(){r.value=!r.value}return(p,f)=>{const _=b("router-view");return k(),w(C,{view:"lHh Lpr lFf"},{default:a(()=>[e(x,{elevated:""},{default:a(()=>[e(I,null,{default:a(()=>[e(g,{flat:"",dense:"",round:"",icon:"menu","aria-label":t(l)("app.menu"),onClick:m},null,8,["aria-label"]),e(L,null,{default:a(()=>[n(o(t(l)("app.title")),1)]),_:1}),D("div",null,"Quasar v"+o(p.$q.version),1)]),_:1})]),_:1}),e(y,{modelValue:r.value,"onUpdate:modelValue":f[0]||(f[0]=c=>r.value=c),"show-if-above":"",bordered:""},{default:a(()=>[e(T,null,{default:a(()=>[e(s,{header:""},{default:a(()=>[n(o(t(l)("app.links")),1)]),_:1}),e(i,{clickable:"",to:"/",exact:""},{default:a(()=>[e(u,{avatar:""},{default:a(()=>[e(d,{name:"home"})]),_:1}),e(u,null,{default:a(()=>[e(s,null,{default:a(()=>[n(o(t(l)("app.home")),1)]),_:1})]),_:1})]),_:1}),e(i,{clickable:"",to:"/dev/api/endpoints",exact:""},{default:a(()=>[e(u,{avatar:""},{default:a(()=>[e(d,{name:"api"})]),_:1}),e(u,null,{default:a(()=>[e(s,null,{default:a(()=>[n(o(t(l)("dev.apiEndpointsTester")),1)]),_:1})]),_:1})]),_:1}),e(i,{clickable:"",to:"/dev/api/mail-debug",exact:""},{default:a(()=>[e(u,{avatar:""},{default:a(()=>[e(d,{name:"mail"})]),_:1}),e(u,null,{default:a(()=>[e(s,null,{default:a(()=>[n(o(t(l)("dev.mailDebug")),1)]),_:1})]),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"]),e(V,null,{default:a(()=>[e(_)]),_:1})]),_:1})}}});export{P as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.doctor-detail-page[data-v-ccd287cb]{background:linear-gradient(180deg,#f6fbf8,#fff 36%,#eef5ff);color:#163047}.page-shell[data-v-ccd287cb]{width:min(1180px,100% - 32px);margin:0 auto}.profile-section[data-v-ccd287cb]{padding:100px 0}.sidebar-card[data-v-ccd287cb],.content-card[data-v-ccd287cb],.contact-card[data-v-ccd287cb],.content-section[data-v-ccd287cb]{border-radius:46px;background:#fff;box-shadow:6px 4px 168px #0000001a}.sidebar-card[data-v-ccd287cb]{overflow:hidden;position:sticky;top:30px}.sidebar-image-wrap[data-v-ccd287cb]{overflow:hidden}.sidebar-image[data-v-ccd287cb]{display:block;width:100%;aspect-ratio:1/1.15;object-fit:cover}.sidebar-body[data-v-ccd287cb]{display:grid;gap:14px;padding:40px;background:#f2fbf7}.sidebar-row[data-v-ccd287cb]{display:flex;align-items:flex-start;padding-bottom:14px;border-bottom:1px solid rgba(22,48,71,.08)}.sidebar-row[data-v-ccd287cb]:last-child{padding-bottom:0;border-bottom:0}.sidebar-label[data-v-ccd287cb]{color:#0f766e;font-size:20px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;width:45%;flex:0 0 45%}.sidebar-value[data-v-ccd287cb]{font-weight:700}.sidebar-footer[data-v-ccd287cb]{display:flex;align-items:center;gap:20px;padding:15px 40px;background:#163047}.sidebar-follow[data-v-ccd287cb]{font-size:20px;font-weight:600;color:#fff}.social-links[data-v-ccd287cb]{display:flex;gap:6px}.social-btn[data-v-ccd287cb]{color:#fff;border:1px solid rgba(255,255,255,.8);background:transparent}.social-icon[data-v-ccd287cb]{display:block;width:18px;height:18px;filter:brightness(0) invert(1)}.content-stack[data-v-ccd287cb]{display:grid;gap:24px}.content-section[data-v-ccd287cb],.content-card[data-v-ccd287cb],.contact-card[data-v-ccd287cb]{padding:0;box-shadow:none;background:transparent}.section-kicker[data-v-ccd287cb]{color:#0f766e;font-size:.85rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}.section-title[data-v-ccd287cb],.card-title[data-v-ccd287cb]{margin:0 0 14px;font-weight:800;letter-spacing:-.03em}.section-title[data-v-ccd287cb]{font-size:clamp(2rem,4vw,2.875rem);line-height:1.06}.section-title.small[data-v-ccd287cb]{font-size:clamp(1.8rem,3vw,2.875rem)}.card-title[data-v-ccd287cb]{font-size:clamp(1.8rem,3vw,2.875rem);margin-bottom:20px}.section-text[data-v-ccd287cb],.timeline-text[data-v-ccd287cb],.expertise-item span[data-v-ccd287cb]{margin:0;color:#607284;line-height:1.72}.timeline-item+.timeline-item[data-v-ccd287cb]{margin-top:30px}.timeline-title[data-v-ccd287cb]{margin-bottom:15px;font-weight:800;font-size:20px}.skill-item+.skill-item[data-v-ccd287cb]{margin-top:30px}.skill-head[data-v-ccd287cb]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px;font-weight:700}.skill-bar[data-v-ccd287cb]{background:#f2fbf7}.expertise-list[data-v-ccd287cb]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:15px 20px;margin-top:20px}.expertise-item[data-v-ccd287cb]{display:flex;align-items:flex-start;gap:10px}.contact-form[data-v-ccd287cb]{display:grid;gap:18px;margin-top:0}.contact-card[data-v-ccd287cb]{padding:40px;background:#f2fbf7;box-shadow:none}.form-grid[data-v-ccd287cb]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:18px}.submit-btn[data-v-ccd287cb]{justify-self:start;min-width:180px}@media(max-width:599px){.page-shell[data-v-ccd287cb]{width:min(100% - 24px,1180px)}.profile-section[data-v-ccd287cb]{padding:40px 0}.sidebar-card[data-v-ccd287cb],.contact-card[data-v-ccd287cb]{border-radius:26px}.sidebar-image[data-v-ccd287cb]{aspect-ratio:1/1.1}.sidebar-body[data-v-ccd287cb]{padding:20px}.sidebar-label[data-v-ccd287cb]{font-size:18px}.sidebar-footer[data-v-ccd287cb]{padding:10px 20px}.sidebar-follow[data-v-ccd287cb]{font-size:18px}.section-title[data-v-ccd287cb],.section-title.small[data-v-ccd287cb],.card-title[data-v-ccd287cb]{font-size:26px}.timeline-item+.timeline-item[data-v-ccd287cb]{margin-top:20px}.skill-item+.skill-item[data-v-ccd287cb]{margin-top:20px}.expertise-list[data-v-ccd287cb],.form-grid[data-v-ccd287cb]{grid-template-columns:1fr}.contact-card[data-v-ccd287cb]{padding:20px}}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.doctors-page[data-v-8073e649]{background:linear-gradient(180deg,#f6fbf8,#fff 36%,#eef5ff);color:#163047}.page-shell[data-v-8073e649]{width:min(1180px,100% - 32px);margin:0 auto}.hero-section[data-v-8073e649]{padding:72px 0 36px}.hero-panel[data-v-8073e649]{max-width:760px;padding:38px;border-radius:36px;background:linear-gradient(135deg,#dff7ee,#dbeafe);box-shadow:0 24px 70px #16304714}.section-kicker[data-v-8073e649]{margin-bottom:10px;color:#0f766e;font-size:.85rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.hero-title[data-v-8073e649]{margin:0 0 14px;font-size:clamp(2.4rem,4.5vw,4rem);line-height:1.02;font-weight:800;letter-spacing:-.03em}.hero-text[data-v-8073e649]{margin:0;color:#607284;line-height:1.7;font-size:1.02rem}.team-section[data-v-8073e649]{padding:24px 0 64px}.doctor-card[data-v-8073e649]{overflow:hidden;height:100%;border-radius:28px;background:#ffffffe6;box-shadow:0 24px 70px #16304714}.doctor-link[data-v-8073e649]{display:block;padding:0;border-radius:0}.doctor-image-wrap[data-v-8073e649]{overflow:hidden}.doctor-image[data-v-8073e649]{display:block;width:100%;height:320px;object-fit:cover}.doctor-body[data-v-8073e649]{padding:18px 18px 22px}.social-links[data-v-8073e649]{display:flex;gap:6px;margin-bottom:16px}.social-btn[data-v-8073e649]{color:#163047;background:#0f766e14}.social-icon[data-v-8073e649]{display:block;width:18px;height:18px}.doctor-name[data-v-8073e649]{margin:0 0 6px;font-size:1.18rem;font-weight:800}.doctor-name-link[data-v-8073e649]{color:inherit;text-decoration:none}.doctor-specialty[data-v-8073e649]{margin:0;color:#607284;text-transform:capitalize}@media(max-width:599px){.page-shell[data-v-8073e649]{width:min(100% - 24px,1180px)}.hero-section[data-v-8073e649]{padding:40px 0 24px}.team-section[data-v-8073e649]{padding:16px 0 40px}.hero-panel[data-v-8073e649]{padding:24px}}

View File

@ -0,0 +1 @@
import{a as k,g as v,h as l,i as D,j as s,k as a,m as e,s as r,G as n,H as m,F as w,Q as d,p,t as i}from"./index-DAvBaevK.js";import{Q}from"./logo-DdmK5n0b.js";import{Q as x}from"./QPage-B68JuyjH.js";import{H as C,i as H,f as I,w as B,a as F}from"./HomeHeader-oAwoUp8W.js";import{t as _}from"./team-1-CMaNLVo5.js";import{t as h,a as g,b as u}from"./team-4-BDlfXLz_.js";import{_ as N}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./position-engine-BHgB6lrx.js";import"./selection-DrSF90ET.js";import"./QToolbar-DdNWxglI.js";const O={class:"team-section"},P={class:"page-shell"},A={class:"row q-col-gutter-lg"},J={class:"doctor-image-wrap"},L=["src","alt"],M={class:"doctor-body"},S={class:"social-links"},U=["src","alt"],V={class:"doctor-content"},W={class:"doctor-name"},E={class:"doctor-specialty"},T=k({__name:"DoctorsPage",setup(j){const f=[{icon:H,label:"Instagram"},{icon:I,label:"Facebook"},{icon:B,label:"WhatsApp"}],y=[{name:"Dr. Esther Howard",specialty:"Ophthalmology",image:_},{name:"Dr. Jenny Wilson",specialty:"Anesthesiology",image:h},{name:"Dr. Kristin Watson",specialty:"Infectious Disease",image:g},{name:"Dr. Arlene McCoy",specialty:"Cardiology",image:u},{name:"Dr. Michael Johnson",specialty:"Orthopedics",image:_},{name:"Dr. Sarah Lee",specialty:"Pediatrics",image:h},{name:"Dr. James Smith",specialty:"Neurology",image:g},{name:"Dr. Rachel Davis",specialty:"Dermatology",image:u}];return(q,c)=>{const b=v("router-link");return l(),D(x,{class:"doctors-page"},{default:s(()=>[a(C),c[0]||(c[0]=e("section",{class:"hero-section"},[e("div",{class:"page-shell"},[e("div",{class:"hero-panel"},[e("div",{class:"section-kicker"},"Our doctors"),e("h1",{class:"hero-title"},"Meet the specialists behind our standard of care"),e("p",{class:"hero-text"}," Our medical team brings together diverse specialties with one shared goal: delivering care that is precise, collaborative, and genuinely human. ")])])],-1)),e("section",O,[e("div",P,[e("div",A,[(l(),r(n,null,m(y,t=>e("div",{key:t.name,class:"col-12 col-sm-6 col-lg-3"},[a(w,{flat:"",class:"doctor-card"},{default:s(()=>[a(d,{class:"doctor-link",flat:"","no-caps":"",to:"/doctordetails"},{default:s(()=>[e("div",J,[e("img",{class:"doctor-image",src:t.image,alt:t.name},null,8,L)])]),_:2},1024),e("div",M,[e("div",S,[(l(),r(n,null,m(f,o=>a(d,{key:o.label,round:"",flat:"",dense:"",class:"social-btn","aria-label":o.label},{default:s(()=>[a(Q,null,{default:s(()=>[p(i(o.label),1)]),_:2},1024),e("img",{class:"social-icon",src:o.icon,alt:o.label},null,8,U)]),_:2},1032,["aria-label"])),64))]),e("div",V,[e("h3",W,[a(b,{class:"doctor-name-link",to:"/doctordetails"},{default:s(()=>[p(i(t.name),1)]),_:2},1024)]),e("p",E,i(t.specialty),1)])])]),_:2},1024)])),64))])])]),a(F)]),_:1})}}}),se=N(T,[["__scopeId","data-v-8073e649"]]);export{se as default};

View File

@ -0,0 +1 @@
import{a as n,u as l,h as a,s as r,m as e,t as c,n as s,k as i,Q as u}from"./index-DAvBaevK.js";const d={class:"fullscreen bg-blue text-white text-center q-pa-md flex flex-center"},p={class:"text-h2",style:{opacity:"0.4"}},x=n({__name:"ErrorNotFound",setup(m){const{t}=l();return(_,o)=>(a(),r("div",d,[e("div",null,[o[0]||(o[0]=e("div",{style:{"font-size":"30vh"}},"404",-1)),e("div",p,c(s(t)("error.notFound")),1),i(u,{class:"q-mt-xl",color:"white","text-color":"blue",unelevated:"",to:"/",label:s(t)("error.goHome"),"no-caps":""},null,8,["label"])])]))}});export{x as default};

View File

@ -1 +0,0 @@
import{Q as o}from"./QBtn-AYMizH8c.js";import{a as s,o as l,k as r,h as t,f as n}from"./index-QUdrNkKl.js";import"./render-B4qP-w0Q.js";const a={class:"fullscreen bg-blue text-white text-center q-pa-md flex flex-center"},f=s({__name:"ErrorNotFound",setup(i){return(c,e)=>(l(),r("div",a,[t("div",null,[e[0]||(e[0]=t("div",{style:{"font-size":"30vh"}},"404",-1)),e[1]||(e[1]=t("div",{class:"text-h2",style:{opacity:"0.4"}},"Oops. Nothing here...",-1)),n(o,{class:"q-mt-xl",color:"white","text-color":"blue",unelevated:"",to:"/",label:"Go Home","no-caps":""})])]))}});export{f as default};

View File

@ -0,0 +1 @@
.home-footer[data-v-5238fbeb]{padding:0 0 36px}.page-shell[data-v-5238fbeb]{width:min(1180px,100% - 32px);margin:0 auto}.footer-card[data-v-5238fbeb]{padding:56px 44px 28px;border-radius:46px;background:#163047;color:#eef8ff;box-shadow:0 24px 70px #16304729}.footer-brand[data-v-5238fbeb]{max-width:360px}.footer-logo[data-v-5238fbeb]{display:block;width:150px;max-width:100%;margin-bottom:22px}.footer-description[data-v-5238fbeb]{margin:0;color:#eef8ffc2;line-height:1.75}.footer-group[data-v-5238fbeb]{height:100%}.footer-title[data-v-5238fbeb]{margin:0 0 18px;font-size:1.15rem;font-weight:800;color:#fff}.footer-links[data-v-5238fbeb]{display:grid;gap:12px}.footer-link[data-v-5238fbeb]{color:#eef8ffc2;text-decoration:none;transition:color .2s ease}.footer-link[data-v-5238fbeb]:hover{color:#7ce0c3}.footer-contact-list[data-v-5238fbeb]{display:grid;gap:16px}.footer-contact-item[data-v-5238fbeb]{display:flex;align-items:flex-start;gap:12px}.footer-contact-icon[data-v-5238fbeb]{width:20px;height:20px;margin-top:2px;filter:brightness(0) invert(1)}.footer-contact-text[data-v-5238fbeb]{color:#eef8ffc2;line-height:1.6}.footer-social-band[data-v-5238fbeb]{display:flex;align-items:center;gap:20px;margin:34px 0 26px}.footer-line[data-v-5238fbeb]{flex:1;height:1px;background:#eef8ff24}.footer-social-links[data-v-5238fbeb]{display:flex;gap:8px}.social-btn[data-v-5238fbeb]{color:#fff;border:1px solid rgba(255,255,255,.18);background:#ffffff0a}.social-icon[data-v-5238fbeb]{display:block;width:18px;height:18px;filter:brightness(0) invert(1)}.footer-meta[data-v-5238fbeb]{display:flex;align-items:center;justify-content:space-between;gap:16px}.footer-copyright[data-v-5238fbeb]{color:#eef8ffad}.footer-legal[data-v-5238fbeb]{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:18px}.footer-legal-link[data-v-5238fbeb]{color:#eef8ffc2;text-decoration:none}.footer-legal-link[data-v-5238fbeb]:hover{color:#7ce0c3}@media(max-width:599px){.page-shell[data-v-5238fbeb]{width:min(100% - 24px,1180px)}.footer-card[data-v-5238fbeb]{padding:32px 22px 22px;border-radius:26px}.footer-social-band[data-v-5238fbeb]{gap:12px}.footer-meta[data-v-5238fbeb]{align-items:flex-start;flex-direction:column}.footer-legal[data-v-5238fbeb]{justify-content:flex-start}}.page-shell[data-v-326e0fe8]{width:min(1180px,100% - 32px);margin:0 auto}.topbar-section[data-v-326e0fe8]{background:#163047;color:#eff8ff}.topbar-row[data-v-326e0fe8]{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 0}.topbar-group[data-v-326e0fe8]{display:flex;align-items:center;flex-wrap:wrap;gap:18px}.topbar-group-end[data-v-326e0fe8]{justify-content:flex-end}.topbar-item[data-v-326e0fe8]{display:inline-flex;align-items:center;gap:8px;font-size:.92rem}.topbar-item strong[data-v-326e0fe8]{font-weight:700}.social-links[data-v-326e0fe8]{display:flex;gap:4px}.social-btn[data-v-326e0fe8]{color:#fff}.social-icon[data-v-326e0fe8]{display:block;width:32px;height:32px}.header-section[data-v-326e0fe8]{position:sticky;top:0;z-index:10;-webkit-backdrop-filter:blur(14px);backdrop-filter:blur(14px);background:#ffffffe6;border-bottom:1px solid rgba(22,48,71,.08)}.header-toolbar[data-v-326e0fe8]{min-height:88px;padding:0}.desktop-nav[data-v-326e0fe8]{display:flex;align-items:center;gap:4px;margin-right:12px}.nav-btn[data-v-326e0fe8]{color:#163047;font-weight:600}@media(max-width:599px){.page-shell[data-v-326e0fe8]{width:min(100% - 24px,1180px)}.topbar-row[data-v-326e0fe8]{padding:10px 0}.topbar-row[data-v-326e0fe8],.topbar-group[data-v-326e0fe8],.topbar-group-end[data-v-326e0fe8]{justify-content:center}.header-toolbar[data-v-326e0fe8]{min-height:76px}}

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
.my-card[data-v-ab3d870b]{width:100%;max-width:250px}

View File

@ -1 +0,0 @@
import{Q as e}from"./QPage-gf8hzrox.js";import{a as o,o as t,e as a}from"./index-QUdrNkKl.js";import"./render-B4qP-w0Q.js";const _=o({__name:"IndexPage",setup(r){return(s,n)=>(t(),a(e,{class:"row items-center justify-evenly"}))}});export{_ as default};

View File

@ -0,0 +1 @@
import{Q as e}from"./QPage-B68JuyjH.js";import{a,h as t,i as o}from"./index-DAvBaevK.js";const p=a({__name:"IndexPage",setup(r){return(s,n)=>(t(),o(e,{class:"row items-center justify-evenly"}))}});export{p as default};

View File

@ -0,0 +1 @@
.index-page[data-v-c2a126e0]{background:linear-gradient(180deg,#f4fbf8,#fff 38%,#eef7ff);color:#163047}.page-shell[data-v-c2a126e0]{width:min(1180px,100% - 32px);margin:0 auto}.nav-btn[data-v-c2a126e0]{color:#163047;font-weight:600}.appointment-btn[data-v-c2a126e0]{min-width:180px}.hero-section[data-v-c2a126e0]{padding:56px 0 72px}.hero-copy[data-v-c2a126e0]{padding-right:20px}.eyebrow[data-v-c2a126e0]{display:inline-flex;align-items:center;max-width:560px;padding:12px 18px;margin-bottom:24px;border:1px solid rgba(15,118,110,.14);border-radius:18px;background:linear-gradient(135deg,#0d948829,#3b82f61f);color:#0f766e;font-size:.98rem;font-weight:800;letter-spacing:.01em;line-height:1.4;text-transform:none;box-shadow:0 14px 30px #0f766e14}.hero-title[data-v-c2a126e0]{margin:0 0 20px;font-size:clamp(2.8rem,6vw,4.8rem);line-height:.98;font-weight:800;letter-spacing:-.04em}.hero-text[data-v-c2a126e0]{max-width:560px;margin:0 0 28px;font-size:1.08rem;line-height:1.7;color:#526579}.hero-actions[data-v-c2a126e0]{display:flex;flex-wrap:wrap;gap:14px;margin-bottom:28px}.rating-card[data-v-c2a126e0]{display:inline-flex;align-items:center;flex-wrap:wrap;gap:14px;padding:18px 20px;border-radius:24px;background:#ffffffdb;box-shadow:0 24px 70px #29486c1f}.rating-copy[data-v-c2a126e0]{display:flex;align-items:baseline;gap:10px}.rating-label[data-v-c2a126e0]{font-weight:700}.rating-score[data-v-c2a126e0]{font-size:1.25rem;font-weight:800}.rating-stars[data-v-c2a126e0]{display:flex;gap:2px}.rating-caption[data-v-c2a126e0]{color:#6b7c8d}.hero-visual[data-v-c2a126e0]{position:relative;padding:22px 20px 44px}.hero-visual[data-v-c2a126e0]:before{content:"";position:absolute;z-index:0}.hero-image-wrap[data-v-c2a126e0]{position:relative;z-index:1;overflow:hidden;border-radius:36px;box-shadow:0 30px 80px #16304729}.hero-image[data-v-c2a126e0]{display:block;width:100%;height:auto}.floating-card[data-v-c2a126e0]{position:absolute;z-index:2;border-radius:24px;background:#fffffff0;box-shadow:0 20px 55px #16304729}.doctors-card[data-v-c2a126e0]{left:-4px;bottom:18px;padding:18px}.doctor-avatars[data-v-c2a126e0]{display:flex;margin-bottom:10px}.doctor-avatar[data-v-c2a126e0]{border:3px solid #fff;margin-left:-12px}.doctor-avatar[data-v-c2a126e0]:first-child{margin-left:0}.floating-title[data-v-c2a126e0]{font-size:.96rem;color:#526579}.clients-card[data-v-c2a126e0]{top:8px;right:0;display:flex;align-items:center;gap:14px;padding:16px 18px}.clients-icon[data-v-c2a126e0]{width:52px;height:52px}.clients-count[data-v-c2a126e0]{font-size:1.5rem;font-weight:800;line-height:1}.clients-label[data-v-c2a126e0]{margin-top:4px;color:#526579}@media(max-width:1023px){.hero-copy[data-v-c2a126e0]{padding-right:0}.hero-visual[data-v-c2a126e0]{margin-top:20px}}@media(max-width:599px){.page-shell[data-v-c2a126e0]{width:min(100% - 24px,1180px)}.hero-section[data-v-c2a126e0]{padding:32px 0 48px}.hero-title[data-v-c2a126e0]{font-size:2.6rem}.eyebrow[data-v-c2a126e0]{font-size:.92rem;padding:10px 14px}.rating-card[data-v-c2a126e0]{width:100%}.hero-visual[data-v-c2a126e0]{padding:10px 0 86px}.hero-visual[data-v-c2a126e0]:before{top:26px;right:0;bottom:0;left:12px;border-radius:28px}.doctors-card[data-v-c2a126e0]{left:8px;bottom:0}.clients-card[data-v-c2a126e0]{top:auto;right:8px;bottom:104px}}

View File

@ -0,0 +1 @@
import{h as i,i as o,j as s,m as e,k as a,F as r,a3 as d,Q as n}from"./index-DAvBaevK.js";import{Q as l}from"./QPage-B68JuyjH.js";import{_ as c}from"./_plugin-vue_export-helper-DlAUqK2U.js";const m={},u={class:"admin-index-shell"},p={class:"col-12 col-md-auto"};function f(x,t){return i(),o(l,{class:"admin-index-page"},{default:s(()=>[e("div",u,[t[1]||(t[1]=e("p",{class:"eyebrow"},"Admin",-1)),t[2]||(t[2]=e("h1",null,"Control Center",-1)),t[3]||(t[3]=e("p",{class:"subtitle"},"Accesso rapido agli strumenti di amministrazione del backend.",-1)),a(r,{flat:"",bordered:"",class:"admin-entry-card"},{default:s(()=>[a(d,{class:"row items-center justify-between q-col-gutter-md"},{default:s(()=>[t[0]||(t[0]=e("div",{class:"col-12 col-md"},[e("div",{class:"text-overline text-primary"},"Gestione utenti"),e("div",{class:"text-h6"},"Users"),e("div",{class:"text-body2 text-grey-7"}," Crea, modifica ed elimina utenti con dettagli e preferenze. ")],-1)),e("div",p,[a(n,{color:"primary",icon:"manage_accounts",label:"Apri pagina utenti",to:"/admin/users"})])]),_:1})]),_:1})])]),_:1})}const v=c(m,[["render",f],["__scopeId","data-v-bdd1e17c"]]);export{v as default};

View File

@ -0,0 +1 @@
.admin-index-page[data-v-bdd1e17c]{background:radial-gradient(circle at top left,rgba(33,150,243,.14),transparent 30%),linear-gradient(180deg,#f7fbff,#eef3f8)}.admin-index-shell[data-v-bdd1e17c]{max-width:960px;margin:0 auto;padding:32px 20px 48px}.eyebrow[data-v-bdd1e17c]{margin:0 0 10px;color:#1565c0;font-size:.8rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase}h1[data-v-bdd1e17c]{margin:0;font-size:clamp(2rem,4vw,3.3rem);line-height:1}.subtitle[data-v-bdd1e17c]{max-width:640px;margin:14px 0 28px;color:#546273;font-size:1rem}.admin-entry-card[data-v-bdd1e17c]{border-radius:24px;background:#ffffffe0;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{a as i,h as t,i as c,j as r,k as a,m as s,Q as l,F as d,s as p,G as m,H as u,y as _,n as g}from"./index-DAvBaevK.js";import{Q as h}from"./QPage-B68JuyjH.js";import{H as v,a as b}from"./HomeHeader-oAwoUp8W.js";import{_ as f}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./logo-DdmK5n0b.js";import"./position-engine-BHgB6lrx.js";import"./selection-DrSF90ET.js";import"./QToolbar-DdNWxglI.js";const k="/assets/hero-img-D6ekzwy-.png",y={class:"hero-section"},x={class:"page-shell"},w={class:"row items-center q-col-gutter-xl"},B={class:"col-12 col-lg-6"},H={class:"hero-copy"},Q={class:"hero-actions"},C={class:"rating-stars","aria-label":"5 star rating"},I={class:"col-12 col-lg-6"},U={class:"hero-visual"},A={class:"hero-image-wrap"},E=["src"],F=i({__name:"IndexPage",setup(P){const n=[{label:"Home",link:"/"},{label:"About Us",link:"/about"},{label:"Services",link:"/services"},{label:"Doctors",link:"/doctors"},{label:"Contact Us",link:"/contact"}];return(q,e)=>(t(),c(h,{class:"index-page"},{default:r(()=>[a(v),s("section",y,[s("div",x,[s("div",w,[s("div",B,[s("div",H,[e[2]||(e[2]=s("div",{class:"eyebrow"},"Care that feels human, expertise you can trust",-1)),e[3]||(e[3]=s("h1",{class:"hero-title"},"Expert medical care you can rely on",-1)),e[4]||(e[4]=s("p",{class:"hero-text"}," Experience healthcare you can trust. Our dedicated team provides compassionate, high-quality care. ",-1)),s("div",Q,[a(l,{unelevated:"",rounded:"","no-caps":"",color:"primary",label:"Book an appointment"}),a(l,{outline:"",rounded:"","no-caps":"",color:"primary",label:"About us",to:n.find(o=>o.label==="About Us")?.link},null,8,["to"])]),a(d,{flat:"",class:"rating-card"},{default:r(()=>[e[0]||(e[0]=s("div",{class:"rating-copy"},[s("span",{class:"rating-label"},"Google Rating"),s("span",{class:"rating-score"},"5.0")],-1)),s("div",C,[(t(),p(m,null,u(5,o=>a(_,{key:o,name:"star",color:"warning"})),64))]),e[1]||(e[1]=s("div",{class:"rating-caption"},"based on 500 reviews",-1))]),_:1})])]),s("div",I,[s("div",U,[s("div",A,[s("img",{class:"hero-image",src:g(k),alt:"Medical team"},null,8,E)])])])])])]),a(b)]),_:1}))}}),O=f(F,[["__scopeId","data-v-c2a126e0"]]);export{O as default};

View File

@ -0,0 +1 @@
.auth-page[data-v-e726952b]{background:linear-gradient(180deg,#f7fafc,#e9f0f7)}.auth-shell[data-v-e726952b]{max-width:520px;margin:0 auto;padding:40px 20px}.auth-card[data-v-e726952b]{border-radius:24px}.auth-form[data-v-e726952b]{display:grid;gap:14px}.auth-links[data-v-e726952b]{display:flex;justify-content:space-between;gap:12px}

View File

@ -0,0 +1 @@
import{a as y,b as _,g as b,h as Q,i as x,j as s,m as n,k as e,F as V,a3 as u,v as p,I as k,J as f,y as C,Q as P,p as c,D as v,K as h}from"./index-DAvBaevK.js";import{Q as B}from"./QForm-CgLsd63I.js";import{Q as I}from"./QPage-B68JuyjH.js";import{u as L}from"./use-quasar-B5tVCAcV.js";import{l as S}from"./api-RGUeM09o.js";import{_ as A}from"./_plugin-vue_export-helper-DlAUqK2U.js";const E={class:"auth-shell"},N=y({__name:"LoginPage",setup(F){const g=_(),d=L(),i=v(!1),r=v(!1),o=h({username:"",password:""});async function w(){i.value=!0;try{const t=await S({username:o.username.trim(),password:o.password});if(t.error)throw new Error(t.error);d.notify({type:"positive",message:"Login effettuato."}),await g.push("/")}catch(t){d.notify({type:"negative",message:t instanceof Error?t.message:String(t)})}finally{i.value=!1}}return(t,a)=>{const m=b("router-link");return Q(),x(I,{class:"auth-page"},{default:s(()=>[n("div",E,[e(V,{flat:"",bordered:"",class:"auth-card"},{default:s(()=>[e(u,null,{default:s(()=>[...a[3]||(a[3]=[n("div",{class:"text-overline text-primary"},"Accesso",-1),n("div",{class:"text-h4"},"Login",-1),n("div",{class:"text-body2 text-grey-7"},"Accedi con email e password.",-1)])]),_:1}),e(p),e(u,null,{default:s(()=>[e(B,{class:"auth-form",onSubmit:k(w,["prevent"])},{default:s(()=>[e(f,{modelValue:o.username,"onUpdate:modelValue":a[0]||(a[0]=l=>o.username=l),outlined:"",type:"email",label:"Email",autocomplete:"username"},null,8,["modelValue"]),e(f,{modelValue:o.password,"onUpdate:modelValue":a[2]||(a[2]=l=>o.password=l),outlined:"",type:r.value?"text":"password",label:"Password",autocomplete:"current-password"},{append:s(()=>[e(C,{name:r.value?"visibility_off":"visibility",class:"cursor-pointer",onClick:a[1]||(a[1]=l=>r.value=!r.value)},null,8,["name"])]),_:1},8,["modelValue","type"]),e(P,{color:"primary",label:"Accedi",type:"submit",loading:i.value},null,8,["loading"])]),_:1})]),_:1}),e(p),e(u,{class:"auth-links"},{default:s(()=>[e(m,{to:"/recoverpassword"},{default:s(()=>[...a[4]||(a[4]=[c("Password dimenticata?",-1)])]),_:1}),e(m,{to:"/signup"},{default:s(()=>[...a[5]||(a[5]=[c("Crea account",-1)])]),_:1})]),_:1})]),_:1})])]),_:1})}}}),K=A(N,[["__scopeId","data-v-e726952b"]]);export{K as default};

View File

@ -0,0 +1 @@
import{a as V,o as A,h as r,i as H,j as v,m as t,p as f,k as n,F,a3 as w,Q as z,v as P,s as m,t as g,z as x,D as b,E as _}from"./index-DAvBaevK.js";import{a as Z}from"./QSelect-Bmx_AjWr.js";import{Q as j}from"./QPage-B68JuyjH.js";import{u as I}from"./use-quasar-B5tVCAcV.js";import{e as R}from"./api-RGUeM09o.js";import{_ as q}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./format-DaKpMo2W.js";import"./position-engine-BHgB6lrx.js";import"./selection-DrSF90ET.js";const O={class:"mail-debug-shell"},U={key:0,class:"error-box"},G={key:1,class:"empty-state"},J={key:2,class:"preview-grid"},K={class:"meta-column"},W={key:0,class:"meta-line"},X={key:1,class:"meta-line"},Y={class:"preview-column"},ee=["srcdoc"],ae=V({__name:"MailDebugPage",setup(le){const M=I(),p=b(!1),o=b([]),s=b(null),u=b(""),$=_(()=>o.value.map((a,e)=>({label:N(a.name||`Mail ${e+1}`).displayName,value:e}))),i=_(()=>s.value===null?null:o.value[s.value]??null),c=_(()=>i.value?N(i.value.name):{displayName:"",email:null,localDate:null}),S=_(()=>C(i.value?.content??""));function C(a){const e='<base target="_blank" rel="noopener noreferrer">';return/<base\s/i.test(a)?a:/<head[^>]*>/i.test(a)?a.replace(/<head[^>]*>/i,l=>`${l}${e}`):`${e}${a}`}function N(a){const e=a.replace(/\.eml$/i,""),l=e.match(/^(\d{10,20})_(.+)$/);let d=e,y=null;l?.[1]&&l[2]&&(y=l[1],d=l[2]);const k=d.replace(/_at_/gi,"@"),h=k.match(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/),E=(y?L(y):null)??Q(e);return{displayName:h?.[0]??k,email:h?h[0]:null,localDate:E}}function L(a){const e=Number(a);if(!Number.isFinite(e))return null;let l=e;a.length>=19?l=Math.floor(e/1e6):a.length>=16?l=Math.floor(e/1e3):a.length<=10&&(l=e*1e3);const d=new Date(l);return Number.isNaN(d.getTime())?null:d.toLocaleString()}function Q(a){const e=a.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?)/);if(e)return D(e[0]);const l=a.match(/(\d{4}-\d{2}-\d{2}[ _]\d{2}[-:]\d{2}[-:]\d{2})/);return l?D(l[0]):null}function D(a){const e=a.replace(" ","T").replace(/(T\d{2})-(\d{2})-(\d{2})$/,"$1:$2:$3"),l=new Date(e);return Number.isNaN(l.getTime())?a:l.toLocaleString()}async function T(){p.value=!0,u.value="";try{const a=await R();if(a.error){u.value=a.error,o.value=[],s.value=null;return}o.value=Array.isArray(a.data)?a.data:[],s.value=o.value.length>0?0:null}catch(a){u.value=a instanceof Error?a.message:String(a),o.value=[],s.value=null}finally{p.value=!1}}async function B(){if(i.value)try{await navigator.clipboard.writeText(i.value.content),M.notify({type:"positive",message:"HTML copiato negli appunti",position:"top-right"})}catch{M.notify({type:"negative",message:"Copia non riuscita",position:"top-right"})}}return A(async()=>{await T()}),(a,e)=>(r(),H(j,{class:"mail-debug-page"},{default:v(()=>[t("div",O,[e[5]||(e[5]=t("header",{class:"mail-debug-header"},[t("p",{class:"eyebrow"},"Developer tools"),t("h1",null,"Mail Debug"),t("p",{class:"subtitle"},[f(" Seleziona una mail da "),t("strong",null,"/maildebug"),f(" e visualizza l'HTML renderizzato. ")])],-1)),n(F,{flat:"",bordered:"",class:"mail-debug-card"},{default:v(()=>[n(w,{class:"controls"},{default:v(()=>[n(z,{color:"primary",icon:"refresh",label:"Aggiorna lista",loading:p.value,onClick:T},null,8,["loading"]),n(Z,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=l=>s.value=l),options:$.value,"option-label":"label","option-value":"value","emit-value":"","map-options":"",outlined:"",dense:"",label:"Seleziona mail",class:"mail-select",disable:p.value||o.value.length===0},null,8,["modelValue","options","disable"])]),_:1}),n(P),n(w,null,{default:v(()=>[u.value?(r(),m("div",U,g(u.value),1)):i.value?(r(),m("div",J,[t("div",K,[e[3]||(e[3]=t("p",{class:"meta-label"},"Nome mail",-1)),t("h2",null,g(c.value.displayName),1),c.value.email?(r(),m("p",W,[e[1]||(e[1]=t("strong",null,"Email:",-1)),f(" "+g(c.value.email),1)])):x("",!0),c.value.localDate?(r(),m("p",X,[e[2]||(e[2]=t("strong",null,"Data locale:",-1)),f(" "+g(c.value.localDate),1)])):x("",!0),n(z,{flat:"",color:"secondary",icon:"content_copy",label:"Copia HTML",onClick:B})]),t("div",Y,[e[4]||(e[4]=t("p",{class:"meta-label"},"Render HTML",-1)),t("iframe",{class:"preview-frame",srcdoc:S.value,sandbox:"allow-popups allow-popups-to-escape-sandbox",title:"Mail HTML preview"},null,8,ee)])])):(r(),m("div",G,"Nessuna mail selezionata."))]),_:1})]),_:1})])]),_:1}))}}),ve=q(ae,[["__scopeId","data-v-1b5b3a76"]]);export{ve as default};

View File

@ -1 +0,0 @@
import{Q as k}from"./QBtn-AYMizH8c.js";import{Q as A}from"./QSelect-QjDUAbKc.js";import{Q as E,a as x}from"./QCard-D_vcm7k9.js";import{Q as H,e as Z}from"./api-rhge6pbe.js";import{Q as F}from"./QPage-gf8hzrox.js";import{M as P,a3 as q,a as j,x as I,o as r,e as R,w as f,h as t,g as v,f as n,k as m,t as g,Z as z,q as b,p as y}from"./index-QUdrNkKl.js";import{_ as K}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./render-B4qP-w0Q.js";import"./use-key-composition-TTwP9QMZ.js";import"./use-dark-BRt0_t6X.js";import"./QItem-F5bzVaJB.js";import"./format-GjIIeqP4.js";import"./use-prevent-scroll-eZQDeoK_.js";import"./QDialog-BcbjPBVh.js";import"./use-timeout-Jkrq6Sig.js";function O(){return P(q)}const U={class:"mail-debug-shell"},G={key:0,class:"error-box"},J={key:1,class:"empty-state"},W={key:2,class:"preview-grid"},X={class:"meta-column"},Y={key:0,class:"meta-line"},ee={key:1,class:"meta-line"},ae={class:"preview-column"},le=["srcdoc"],te=j({__name:"MailDebugPage",setup(oe){const M=O(),p=b(!1),o=b([]),s=b(null),u=b(""),Q=y(()=>o.value.map((a,e)=>({label:N(a.name||`Mail ${e+1}`).displayName,value:e}))),i=y(()=>s.value===null?null:o.value[s.value]??null),c=y(()=>i.value?N(i.value.name):{displayName:"",email:null,localDate:null}),$=y(()=>S(i.value?.content??""));function S(a){const e='<base target="_blank" rel="noopener noreferrer">';return/<base\s/i.test(a)?a:/<head[^>]*>/i.test(a)?a.replace(/<head[^>]*>/i,l=>`${l}${e}`):`${e}${a}`}function N(a){const e=a.replace(/\.eml$/i,""),l=e.match(/^(\d{10,20})_(.+)$/);let d=e,_=null;l?.[1]&&l[2]&&(_=l[1],d=l[2]);const w=d.replace(/_at_/gi,"@"),h=w.match(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/),V=(_?C(_):null)??L(e);return{displayName:h?.[0]??w,email:h?h[0]:null,localDate:V}}function C(a){const e=Number(a);if(!Number.isFinite(e))return null;let l=e;a.length>=19?l=Math.floor(e/1e6):a.length>=16?l=Math.floor(e/1e3):a.length<=10&&(l=e*1e3);const d=new Date(l);return Number.isNaN(d.getTime())?null:d.toLocaleString()}function L(a){const e=a.match(/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?)/);if(e)return D(e[0]);const l=a.match(/(\d{4}-\d{2}-\d{2}[ _]\d{2}[-:]\d{2}[-:]\d{2})/);return l?D(l[0]):null}function D(a){const e=a.replace(" ","T").replace(/(T\d{2})-(\d{2})-(\d{2})$/,"$1:$2:$3"),l=new Date(e);return Number.isNaN(l.getTime())?a:l.toLocaleString()}async function T(){p.value=!0,u.value="";try{const a=await Z();if(a.error){u.value=a.error,o.value=[],s.value=null;return}o.value=Array.isArray(a.data)?a.data:[],s.value=o.value.length>0?0:null}catch(a){u.value=a instanceof Error?a.message:String(a),o.value=[],s.value=null}finally{p.value=!1}}async function B(){if(i.value)try{await navigator.clipboard.writeText(i.value.content),M.notify({type:"positive",message:"HTML copiato negli appunti",position:"top-right"})}catch{M.notify({type:"negative",message:"Copia non riuscita",position:"top-right"})}}return I(async()=>{await T()}),(a,e)=>(r(),R(F,{class:"mail-debug-page"},{default:f(()=>[t("div",U,[e[5]||(e[5]=t("header",{class:"mail-debug-header"},[t("p",{class:"eyebrow"},"Developer tools"),t("h1",null,"Mail Debug"),t("p",{class:"subtitle"},[v(" Seleziona una mail da "),t("strong",null,"/maildebug"),v(" e visualizza l'HTML renderizzato. ")])],-1)),n(E,{flat:"",bordered:"",class:"mail-debug-card"},{default:f(()=>[n(x,{class:"controls"},{default:f(()=>[n(k,{color:"primary",icon:"refresh",label:"Aggiorna lista",loading:p.value,onClick:T},null,8,["loading"]),n(A,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=l=>s.value=l),options:Q.value,"option-label":"label","option-value":"value","emit-value":"","map-options":"",outlined:"",dense:"",label:"Seleziona mail",class:"mail-select",disable:p.value||o.value.length===0},null,8,["modelValue","options","disable"])]),_:1}),n(H),n(x,null,{default:f(()=>[u.value?(r(),m("div",G,g(u.value),1)):i.value?(r(),m("div",W,[t("div",X,[e[3]||(e[3]=t("p",{class:"meta-label"},"Nome mail",-1)),t("h2",null,g(c.value.displayName),1),c.value.email?(r(),m("p",Y,[e[1]||(e[1]=t("strong",null,"Email:",-1)),v(" "+g(c.value.email),1)])):z("",!0),c.value.localDate?(r(),m("p",ee,[e[2]||(e[2]=t("strong",null,"Data locale:",-1)),v(" "+g(c.value.localDate),1)])):z("",!0),n(k,{flat:"",color:"secondary",icon:"content_copy",label:"Copia HTML",onClick:B})]),t("div",ae,[e[4]||(e[4]=t("p",{class:"meta-label"},"Render HTML",-1)),t("iframe",{class:"preview-frame",srcdoc:$.value,sandbox:"allow-popups allow-popups-to-escape-sandbox",title:"Mail HTML preview"},null,8,le)])])):(r(),m("div",J,"Nessuna mail selezionata."))]),_:1})]),_:1})])]),_:1}))}}),Ne=K(te,[["__scopeId","data-v-1b5b3a76"]]);export{Ne as default};

View File

@ -0,0 +1 @@
.lang-fallback[data-v-1941e633]{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:22px;padding:0 4px;border:1px solid currentColor;border-radius:4px;font-size:10px;line-height:1;font-weight:700}.border[data-v-1941e633]{border:1px solid #fff;border-radius:4px}.q-select i.q-icon[data-v-1941e633]{color:#fff!important}.user-avatar[data-v-1941e633]{background:linear-gradient(135deg,#0d47a1,#26a69a);color:#fff;font-size:.78rem;font-weight:700}.brand-logo-tb[data-v-1941e633]{height:42px;width:auto}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
.lang-fallback[data-v-92823159]{display:inline-flex;align-items:center;justify-content:center;min-width:32px;height:22px;padding:0 4px;border:1px solid currentColor;border-radius:4px;font-size:10px;line-height:1;font-weight:700}.border[data-v-92823159]{border:1px solid #fff;border-radius:4px}.q-select i.q-icon[data-v-92823159]{color:#fff!important}

View File

@ -0,0 +1 @@
import{L as i,M as r,ax as u,E as l}from"./index-DAvBaevK.js";const d=["top","middle","bottom"],c=i({name:"QBadge",props:{color:String,textColor:String,floating:Boolean,transparent:Boolean,multiLine:Boolean,outline:Boolean,rounded:Boolean,label:[Number,String],align:{type:String,validator:e=>d.includes(e)}},setup(e,{slots:a}){const n=l(()=>e.align!==void 0?{verticalAlign:e.align}:null),o=l(()=>{const t=e.outline===!0&&e.color||e.textColor;return`q-badge flex inline items-center no-wrap q-badge--${e.multiLine===!0?"multi":"single"}-line`+(e.outline===!0?" q-badge--outline":e.color!==void 0?` bg-${e.color}`:"")+(t!==void 0?` text-${t}`:"")+(e.floating===!0?" q-badge--floating":"")+(e.rounded===!0?" q-badge--rounded":"")+(e.transparent===!0?" q-badge--transparent":"")});return()=>r("div",{class:o.value,style:n.value,role:"status","aria-label":e.label},u(a.default,e.label!==void 0?[e.label]:[]))}});export{c as Q};

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
import{s as t,y as o,p as s,A as c}from"./index-QUdrNkKl.js";import{h as n}from"./render-B4qP-w0Q.js";import{u as l,a as i}from"./use-dark-BRt0_t6X.js";const p=t({name:"QCardSection",props:{tag:{type:String,default:"div"},horizontal:Boolean},setup(a,{slots:r}){const e=s(()=>`q-card__section q-card__section--${a.horizontal===!0?"horiz row no-wrap":"vert"}`);return()=>o(a.tag,{class:e.value},n(r.default))}}),g=t({name:"QCard",props:{...l,tag:{type:String,default:"div"},square:Boolean,flat:Boolean,bordered:Boolean},setup(a,{slots:r}){const{proxy:{$q:e}}=c(),d=i(a,e),u=s(()=>"q-card"+(d.value===!0?" q-card--dark q-dark":"")+(a.bordered===!0?" q-card--bordered":"")+(a.square===!0?" q-card--square no-border-radius":"")+(a.flat===!0?" q-card--flat no-shadow":""));return()=>o(a.tag,{class:u.value},n(r.default))}});export{g as Q,p as a};

View File

@ -1 +0,0 @@
import{d as r,e}from"./QBtn-AYMizH8c.js";import{s as c,y as n,p as i}from"./index-QUdrNkKl.js";import{h as l}from"./render-B4qP-w0Q.js";const d=c({name:"QCardActions",props:{...r,vertical:Boolean},setup(s,{slots:a}){const o=e(s),t=i(()=>`q-card__actions ${o.value} q-card__actions--${s.vertical===!0?"vert column":"horiz row"}`);return()=>n("div",{class:t.value},l(a.default))}});export{d as Q};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{L as E,aA as P,az as A,o as q,M as V,a1 as B,$ as I,D as R,aT as D,a2 as S,a4 as Q,aU as $,ap as j,aV as M}from"./index-DAvBaevK.js";const k=E({name:"QForm",props:{autofocus:Boolean,noErrorFocus:Boolean,noResetFocus:Boolean,greedy:Boolean,onSubmit:Function},emits:["reset","validationSuccess","validationError"],setup(r,{slots:F,emit:l}){const C=I(),u=R(null);let i=0;const s=[];function d(e){const a=typeof e=="boolean"?e:r.noErrorFocus!==!0,f=++i,x=(t,o)=>{l(`validation${t===!0?"Success":"Error"}`,o)},h=t=>{const o=t.validate();return typeof o.then=="function"?o.then(n=>({valid:n,comp:t}),n=>({valid:!1,comp:t,err:n})):Promise.resolve({valid:o,comp:t})};return(r.greedy===!0?Promise.all(s.map(h)).then(t=>t.filter(o=>o.valid!==!0)):s.reduce((t,o)=>t.then(()=>h(o).then(n=>{if(n.valid===!1)return Promise.reject(n)})),Promise.resolve()).catch(t=>[t])).then(t=>{if(t===void 0||t.length===0)return f===i&&x(!0),!0;if(f===i){const{comp:o,err:n}=t[0];if(n!==void 0&&console.error(n),x(!1,o),a===!0){const g=t.find(({comp:p})=>typeof p.focus=="function"&&D(p.$)===!1);g!==void 0&&g.comp.focus()}}return!1})}function v(){i++,s.forEach(e=>{typeof e.resetValidation=="function"&&e.resetValidation()})}function m(e){e!==void 0&&S(e);const a=i+1;d().then(f=>{a===i&&f===!0&&(r.onSubmit!==void 0?l("submit",e):e?.target!==void 0&&typeof e.target.submit=="function"&&e.target.submit())})}function b(e){e!==void 0&&S(e),l("reset"),Q(()=>{v(),r.autofocus===!0&&r.noResetFocus!==!0&&c()})}function c(){$(()=>{if(u.value===null)return;(u.value.querySelector("[autofocus][tabindex], [data-autofocus][tabindex]")||u.value.querySelector("[autofocus] [tabindex], [data-autofocus] [tabindex]")||u.value.querySelector("[autofocus], [data-autofocus]")||Array.prototype.find.call(u.value.querySelectorAll("[tabindex]"),a=>a.tabIndex!==-1))?.focus({preventScroll:!0})})}j(M,{bindComponent(e){s.push(e)},unbindComponent(e){const a=s.indexOf(e);a!==-1&&s.splice(a,1)}});let y=!1;return P(()=>{y=!0}),A(()=>{y===!0&&r.autofocus===!0&&c()}),q(()=>{r.autofocus===!0&&c()}),Object.assign(C.proxy,{validate:d,resetValidation:v,submit:m,reset:b,focus:c,getValidationComponents:()=>s}),()=>V("form",{class:"q-form",ref:u,onSubmit:m,onReset:b},B(F.default))}});export{k as Q};

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
import{s as v,y as r,p as a,A as w,q as f,_ as I,L as E}from"./index-QUdrNkKl.js";import{h as q,c as Q}from"./render-B4qP-w0Q.js";import{u as S,a as A}from"./use-dark-BRt0_t6X.js";import{g as K,h as R}from"./QBtn-AYMizH8c.js";const N=v({name:"QItemSection",props:{avatar:Boolean,thumbnail:Boolean,side:Boolean,top:Boolean,noWrap:Boolean},setup(e,{slots:n}){const l=a(()=>`q-item__section column q-item__section--${e.avatar===!0||e.side===!0||e.thumbnail===!0?"side":"main"}`+(e.top===!0?" q-item__section--top justify-start":" justify-center")+(e.avatar===!0?" q-item__section--avatar":"")+(e.thumbnail===!0?" q-item__section--thumbnail":"")+(e.noWrap===!0?" q-item__section--nowrap":""));return()=>r("div",{class:l.value},q(n.default))}}),P=v({name:"QItemLabel",props:{overline:Boolean,caption:Boolean,header:Boolean,lines:[Number,String]},setup(e,{slots:n}){const l=a(()=>parseInt(e.lines,10)),u=a(()=>"q-item__label"+(e.overline===!0?" q-item__label--overline text-overline":"")+(e.caption===!0?" q-item__label--caption text-caption":"")+(e.header===!0?" q-item__label--header":"")+(l.value===1?" ellipsis":"")),c=a(()=>e.lines!==void 0&&l.value>1?{overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical","-webkit-line-clamp":l.value}:null);return()=>r("div",{style:c.value,class:u.value},q(n.default))}}),O=v({name:"QItem",props:{...S,...K,tag:{type:String,default:"div"},active:{type:Boolean,default:null},clickable:Boolean,dense:Boolean,insetLevel:Number,tabindex:[String,Number],focused:Boolean,manualFocus:Boolean},emits:["click","keyup"],setup(e,{slots:n,emit:l}){const{proxy:{$q:u}}=w(),c=A(e,u),{hasLink:m,linkAttrs:k,linkClass:_,linkTag:h,navigateOnClick:y}=R(),s=f(null),o=f(null),d=a(()=>e.clickable===!0||m.value===!0||e.tag==="label"),i=a(()=>e.disable!==!0&&d.value===!0),g=a(()=>"q-item q-item-type row no-wrap"+(e.dense===!0?" q-item--dense":"")+(c.value===!0?" q-item--dark":"")+(m.value===!0&&e.active===null?_.value:e.active===!0?` q-item--active${e.activeClass!==void 0?` ${e.activeClass}`:""}`:"")+(e.disable===!0?" disabled":"")+(i.value===!0?" q-item--clickable q-link cursor-pointer "+(e.manualFocus===!0?"q-manual-focusable":"q-focusable q-hoverable")+(e.focused===!0?" q-manual-focusable--focused":""):"")),B=a(()=>e.insetLevel===void 0?null:{["padding"+(u.lang.rtl===!0?"Right":"Left")]:16+e.insetLevel*56+"px"});function x(t){i.value===!0&&(o.value!==null&&t.qAvoidFocus!==!0&&(t.qKeyEvent!==!0&&document.activeElement===s.value?o.value.focus():document.activeElement===o.value&&s.value.focus()),y(t))}function L(t){if(i.value===!0&&I(t,[13,32])===!0){E(t),t.qKeyEvent=!0;const b=new MouseEvent("click",t);b.qKeyEvent=!0,s.value.dispatchEvent(b)}l("keyup",t)}function C(){const t=Q(n.default,[]);return i.value===!0&&t.unshift(r("div",{class:"q-focus-helper",tabindex:-1,ref:o})),t}return()=>{const t={ref:s,class:g.value,style:B.value,role:"listitem",onClick:x,onKeyup:L};return i.value===!0?(t.tabindex=e.tabindex||"0",Object.assign(t,k.value)):d.value===!0&&(t["aria-disabled"]="true"),r(h.value,t,C())}}});export{O as Q,N as a,P as b};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{L as S,aR as b,ag as k,$ as h,an as x,M as t,ax as C,E as r,aS as B}from"./index-DAvBaevK.js";const w={xs:2,sm:4,md:6,lg:10,xl:14};function c(e,s,a){return{transform:s===!0?`translateX(${a.lang.rtl===!0?"-":""}100%) scale3d(${-e},1,1)`:`scale3d(${e},1,1)`}}const P=S({name:"QLinearProgress",props:{...k,...b,value:{type:Number,default:0},buffer:Number,color:String,trackColor:String,reverse:Boolean,stripe:Boolean,indeterminate:Boolean,query:Boolean,rounded:Boolean,animationSpeed:{type:[String,Number],default:2100},instantFeedback:Boolean},setup(e,{slots:s}){const{proxy:a}=h(),d=x(e,a.$q),u=B(e,w),l=r(()=>e.indeterminate===!0||e.query===!0),o=r(()=>e.reverse!==e.query),v=r(()=>({...u.value!==null?u.value:{},"--q-linear-progress-speed":`${e.animationSpeed}ms`})),m=r(()=>"q-linear-progress"+(e.color!==void 0?` text-${e.color}`:"")+(e.reverse===!0||e.query===!0?" q-linear-progress--reverse":"")+(e.rounded===!0?" rounded-borders":"")),g=r(()=>c(e.buffer!==void 0?e.buffer:1,o.value,a.$q)),n=r(()=>`with${e.instantFeedback===!0?"out":""}-transition`),f=r(()=>`q-linear-progress__track absolute-full q-linear-progress__track--${n.value} q-linear-progress__track--${d.value===!0?"dark":"light"}`+(e.trackColor!==void 0?` bg-${e.trackColor}`:"")),q=r(()=>c(l.value===!0?1:e.value,o.value,a.$q)),$=r(()=>`q-linear-progress__model absolute-full q-linear-progress__model--${n.value} q-linear-progress__model--${l.value===!0?"in":""}determinate`),y=r(()=>({width:`${e.value*100}%`})),_=r(()=>`q-linear-progress__stripe absolute-${e.reverse===!0?"right":"left"} q-linear-progress__stripe--${n.value}`);return()=>{const i=[t("div",{class:f.value,style:g.value}),t("div",{class:$.value,style:q.value})];return e.stripe===!0&&l.value===!1&&i.push(t("div",{class:_.value,style:y.value})),t("div",{class:m.value,style:v.value,role:"progressbar","aria-valuemin":0,"aria-valuemax":1,"aria-valuenow":e.indeterminate===!0?void 0:e.value},C(s.default,i))}}});export{P as Q};

View File

@ -0,0 +1 @@
import{L as g,$ as h,ah as r,ai as t,aj as p,aq as d,M as y,a1 as f,E as s}from"./index-DAvBaevK.js";const C=g({name:"QPage",props:{padding:Boolean,styleFn:Function},setup(n,{slots:i}){const{proxy:{$q:o}}=h(),e=r(p,t);if(e===t)return console.error("QPage needs to be a deep child of QLayout"),t;if(r(d,t)===t)return console.error("QPage needs to be child of QPageContainer"),t;const c=s(()=>{const a=(e.header.space===!0?e.header.size:0)+(e.footer.space===!0?e.footer.size:0);if(typeof n.styleFn=="function"){const l=e.isContainer.value===!0?e.containerHeight.value:o.screen.height;return n.styleFn(a,l)}return{minHeight:e.isContainer.value===!0?e.containerHeight.value-a+"px":o.screen.height===0?a!==0?`calc(100vh - ${a}px)`:"100vh":o.screen.height-a+"px"}}),u=s(()=>`q-page${n.padding===!0?" q-layout-padding":""}`);return()=>y("main",{class:u.value,style:c.value},f(i.default))}});export{C as Q};

View File

@ -1 +0,0 @@
import{s as p,A as g,M as r,N as t,O as h,V as d,y,p as s}from"./index-QUdrNkKl.js";import{h as f}from"./render-B4qP-w0Q.js";const Q=p({name:"QPage",props:{padding:Boolean,styleFn:Function},setup(a,{slots:i}){const{proxy:{$q:o}}=g(),e=r(h,t);if(e===t)return console.error("QPage needs to be a deep child of QLayout"),t;if(r(d,t)===t)return console.error("QPage needs to be child of QPageContainer"),t;const c=s(()=>{const n=(e.header.space===!0?e.header.size:0)+(e.footer.space===!0?e.footer.size:0);if(typeof a.styleFn=="function"){const l=e.isContainer.value===!0?e.containerHeight.value:o.screen.height;return a.styleFn(n,l)}return{minHeight:e.isContainer.value===!0?e.containerHeight.value-n+"px":o.screen.height===0?n!==0?`calc(100vh - ${n}px)`:"100vh":o.screen.height-n+"px"}}),u=s(()=>`q-page${a.padding===!0?" q-layout-padding":""}`);return()=>y("main",{class:u.value,style:c.value},f(i.default))}});export{Q};

View File

@ -0,0 +1 @@
import{L as p,ag as w,an as x,M as y,a1 as L,$ as z,E as v,D as k,au as D,o as f,W as b,ab as E,a4 as m,ar as g}from"./index-DAvBaevK.js";const O=["ul","ol"],Q=p({name:"QList",props:{...w,bordered:Boolean,dense:Boolean,separator:Boolean,padding:Boolean,tag:{type:String,default:"div"}},setup(e,{slots:u}){const s=z(),n=x(e,s.proxy.$q),r=v(()=>O.includes(e.tag)?null:"list"),o=v(()=>"q-list"+(e.bordered===!0?" q-list--bordered":"")+(e.dense===!0?" q-list--dense":"")+(e.separator===!0?" q-list--separator":"")+(n.value===!0?" q-list--dark":"")+(e.padding===!0?" q-list--padding":""));return()=>y(e.tag,{class:o.value,role:r.value},L(u.default))}});function B(){const e=k(!D.value);return e.value===!1&&f(()=>{e.value=!0}),{isHydrated:e}}const q=typeof ResizeObserver<"u",h=q===!0?{}:{style:"display:block;position:absolute;top:0;left:0;right:0;bottom:0;height:100%;width:100%;overflow:hidden;pointer-events:none;z-index:-1;",url:"about:blank"},R=p({name:"QResizeObserver",props:{debounce:{type:[String,Number],default:100}},emits:["resize"],setup(e,{emit:u}){let s=null,n,r={width:-1,height:-1};function o(t){t===!0||e.debounce===0||e.debounce==="0"?l():s===null&&(s=setTimeout(l,e.debounce))}function l(){if(s!==null&&(clearTimeout(s),s=null),n){const{offsetWidth:t,offsetHeight:i}=n;(t!==r.width||i!==r.height)&&(r={width:t,height:i},u("resize",r))}}const{proxy:d}=z();if(d.trigger=o,q===!0){let t;const i=c=>{n=d.$el.parentNode,n?(t=new ResizeObserver(o),t.observe(n),l()):c!==!0&&m(()=>{i(!0)})};return f(()=>{i()}),b(()=>{s!==null&&clearTimeout(s),t!==void 0&&(t.disconnect!==void 0?t.disconnect():n&&t.unobserve(n))}),E}else{let t=function(){s!==null&&(clearTimeout(s),s=null),a!==void 0&&(a.removeEventListener!==void 0&&a.removeEventListener("resize",o,g.passive),a=void 0)},i=function(){t(),n?.contentDocument&&(a=n.contentDocument.defaultView,a.addEventListener("resize",o,g.passive),l())};const{isHydrated:c}=B();let a;return f(()=>{m(()=>{n=d.$el,n&&i()})}),b(t),()=>{if(c.value===!0)return y("object",{class:"q--avoid-card-border",style:h.style,tabindex:-1,type:"text/html",data:h.url,"aria-hidden":"true",onLoad:i})}}}});export{Q,R as a};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
import{L as a,M as s,a1 as r,E as l}from"./index-DAvBaevK.js";const p=a({name:"QToolbar",props:{inset:Boolean},setup(o,{slots:e}){const t=l(()=>"q-toolbar row no-wrap items-center"+(o.inset===!0?" q-toolbar--inset":""));return()=>s("div",{class:t.value,role:"toolbar"},r(e.default))}});export{p as Q};

View File

@ -0,0 +1 @@
import{a as y,g as x,h as r,i as u,j as s,m as o,k as a,F as Q,a3 as d,v as c,I as k,J as w,Q as p,s as b,y as V,p as h,z as C,D as m}from"./index-DAvBaevK.js";import{Q as I}from"./QForm-CgLsd63I.js";import{Q as P}from"./QPage-B68JuyjH.js";import{u as z}from"./use-quasar-B5tVCAcV.js";import{f as B}from"./api-RGUeM09o.js";import{_ as E}from"./_plugin-vue_export-helper-DlAUqK2U.js";const S={class:"auth-shell"},N={key:1,class:"success-state"},R=y({__name:"RecoverPasswordPage",setup(F){const f=z(),l=m(!1),i=m(""),n=m(!1);async function v(){l.value=!0;try{const t=await B({email:i.value.trim()});if(t.error)throw new Error(t.error);n.value=!0}catch(t){f.notify({type:"negative",message:t instanceof Error?t.message:String(t)})}finally{l.value=!1}}return(t,e)=>{const g=x("router-link");return r(),u(P,{class:"auth-page"},{default:s(()=>[o("div",S,[a(Q,{flat:"",bordered:"",class:"auth-card"},{default:s(()=>[a(d,null,{default:s(()=>[...e[1]||(e[1]=[o("div",{class:"text-overline text-primary"},"Recupero",-1),o("div",{class:"text-h4"},"Recover password",-1),o("div",{class:"text-body2 text-grey-7"},"Invia la mail di recupero password.",-1)])]),_:1}),a(c),a(d,null,{default:s(()=>[n.value?(r(),b("div",N,[a(V,{name:"mark_email_read",size:"56px",color:"positive"}),e[2]||(e[2]=o("div",{class:"text-h6"},"Email inviata",-1)),e[3]||(e[3]=o("div",{class:"text-body2 text-grey-7"}," Se l'indirizzo esiste, riceverai un messaggio con le istruzioni per reimpostare la password. ",-1)),a(p,{color:"primary",label:"Home",to:"/"})])):(r(),u(I,{key:0,class:"auth-form",onSubmit:k(v,["prevent"])},{default:s(()=>[a(w,{modelValue:i.value,"onUpdate:modelValue":e[0]||(e[0]=_=>i.value=_),outlined:"",type:"email",label:"Email",autocomplete:"email"},null,8,["modelValue"]),a(p,{color:"primary",label:"Invia email",type:"submit",loading:l.value},null,8,["loading"])]),_:1}))]),_:1}),a(c),n.value?C("",!0):(r(),u(d,{key:0,class:"auth-links"},{default:s(()=>[a(g,{to:"/login"},{default:s(()=>[...e[4]||(e[4]=[h("Torna al login",-1)])]),_:1})]),_:1}))]),_:1})])]),_:1})}}}),M=E(R,[["__scopeId","data-v-d3af4c7f"]]);export{M as default};

View File

@ -0,0 +1 @@
.auth-page[data-v-d3af4c7f]{background:linear-gradient(180deg,#f7fafc,#e9f0f7)}.auth-shell[data-v-d3af4c7f]{max-width:520px;margin:0 auto;padding:40px 20px}.auth-card[data-v-d3af4c7f]{border-radius:24px}.auth-form[data-v-d3af4c7f]{display:grid;gap:14px}.auth-links[data-v-d3af4c7f]{display:flex;justify-content:flex-end}.success-state[data-v-d3af4c7f]{display:grid;justify-items:center;gap:12px;text-align:center;padding:12px 0}

View File

@ -0,0 +1 @@
import{a as R,e as h,D as t,h as f,i as I,j as n,m,k as s,F as A,a3 as w,v as B,J as g,y,s as k,t as _,z as b,a6 as S,Q as T,E as N}from"./index-DAvBaevK.js";import{Q as U}from"./QPage-B68JuyjH.js";import{a as E}from"./api-RGUeM09o.js";import{_ as F}from"./_plugin-vue_export-helper-DlAUqK2U.js";const L={class:"page-shell"},q={key:0,class:"msg msg-error"},D={key:1,class:"msg msg-success"},M=R({__name:"ResetPasswordPage",setup($){const V=h(),u=t(P()),r=t(""),d=t(""),p=t(!1),c=t(!1),v=t(!1),o=t(""),i=t(""),C=N(()=>u.value.trim().length>0?"Token caricato da URL, puoi comunque modificarlo.":"Inserisci il token ricevuto via email.");function P(){const e=V.query.token;return typeof e=="string"?e:Array.isArray(e)&&e.length>0?String(e[0]):""}function Q(){return o.value="",i.value="",u.value.trim()?r.value?r.value.length<8?(o.value="La password deve avere almeno 8 caratteri.",!1):r.value!==d.value?(o.value="Le password non coincidono.",!1):!0:(o.value="Inserisci una nuova password.",!1):(o.value="Token mancante.",!1)}async function x(){if(Q()){p.value=!0,o.value="",i.value="";try{const e=await E({token:u.value.trim(),password:r.value});if(e.error){o.value=e.error;return}i.value=e.data?.message||"Password aggiornata con successo.",r.value="",d.value=""}catch(e){o.value=e instanceof Error?e.message:String(e)}finally{p.value=!1}}}return(e,a)=>(f(),I(U,{class:"reset-password-page"},{default:n(()=>[m("div",L,[s(A,{flat:"",bordered:"",class:"reset-card"},{default:n(()=>[s(w,{class:"card-head"},{default:n(()=>[...a[5]||(a[5]=[m("p",{class:"eyebrow"},"Account security",-1),m("h1",null,"Reset Password",-1),m("p",{class:"subtitle"},"Imposta una nuova password usando il token ricevuto via email.",-1)])]),_:1}),s(B),s(w,{class:"card-body"},{default:n(()=>[s(g,{modelValue:u.value,"onUpdate:modelValue":a[0]||(a[0]=l=>u.value=l),label:"Token",outlined:"",autogrow:"",type:"textarea",hint:C.value},null,8,["modelValue","hint"]),s(g,{modelValue:r.value,"onUpdate:modelValue":a[2]||(a[2]=l=>r.value=l),label:"Nuova password",outlined:"",type:c.value?"text":"password"},{append:n(()=>[s(y,{name:c.value?"visibility_off":"visibility",class:"cursor-pointer",onClick:a[1]||(a[1]=l=>c.value=!c.value)},null,8,["name"])]),_:1},8,["modelValue","type"]),s(g,{modelValue:d.value,"onUpdate:modelValue":a[4]||(a[4]=l=>d.value=l),label:"Conferma password",outlined:"",type:v.value?"text":"password"},{append:n(()=>[s(y,{name:v.value?"visibility_off":"visibility",class:"cursor-pointer",onClick:a[3]||(a[3]=l=>v.value=!v.value)},null,8,["name"])]),_:1},8,["modelValue","type"]),o.value?(f(),k("div",q,_(o.value),1)):b("",!0),i.value?(f(),k("div",D,_(i.value),1)):b("",!0)]),_:1}),s(S,{align:"right",class:"card-actions"},{default:n(()=>[s(T,{color:"primary",icon:"lock_reset",label:"Aggiorna password",loading:p.value,onClick:x},null,8,["loading"])]),_:1})]),_:1})])]),_:1}))}}),G=F(M,[["__scopeId","data-v-7f13b293"]]);export{G as default};

View File

@ -1 +0,0 @@
import{Q as R,a as w}from"./QCard-D_vcm7k9.js";import{Q as h,r as I}from"./api-rhge6pbe.js";import{Q as f}from"./QInput-CEazYqyH.js";import{b as y,Q as A}from"./QBtn-AYMizH8c.js";import{Q as B}from"./QCardActions-DlFyQG4S.js";import{Q as S}from"./QPage-gf8hzrox.js";import{a as T,Y as N,q as t,o as g,e as U,w as n,h as m,f as s,k,t as _,Z as b,p as q}from"./index-QUdrNkKl.js";import{_ as L}from"./_plugin-vue_export-helper-DlAUqK2U.js";import"./render-B4qP-w0Q.js";import"./use-dark-BRt0_t6X.js";import"./use-key-composition-TTwP9QMZ.js";const E={class:"page-shell"},F={key:0,class:"msg msg-error"},M={key:1,class:"msg msg-success"},$=T({__name:"ResetPasswordPage",setup(D){const Q=N(),u=t(C()),r=t(""),d=t(""),p=t(!1),c=t(!1),v=t(!1),o=t(""),i=t(""),V=q(()=>u.value.trim().length>0?"Token caricato da URL, puoi comunque modificarlo.":"Inserisci il token ricevuto via email.");function C(){const e=Q.query.token;return typeof e=="string"?e:Array.isArray(e)&&e.length>0?String(e[0]):""}function P(){return o.value="",i.value="",u.value.trim()?r.value?r.value.length<8?(o.value="La password deve avere almeno 8 caratteri.",!1):r.value!==d.value?(o.value="Le password non coincidono.",!1):!0:(o.value="Inserisci una nuova password.",!1):(o.value="Token mancante.",!1)}async function x(){if(P()){p.value=!0,o.value="",i.value="";try{const e=await I({token:u.value.trim(),password:r.value});if(e.error){o.value=e.error;return}i.value=e.data?.message||"Password aggiornata con successo.",r.value="",d.value=""}catch(e){o.value=e instanceof Error?e.message:String(e)}finally{p.value=!1}}}return(e,a)=>(g(),U(S,{class:"reset-password-page"},{default:n(()=>[m("div",E,[s(R,{flat:"",bordered:"",class:"reset-card"},{default:n(()=>[s(w,{class:"card-head"},{default:n(()=>[...a[5]||(a[5]=[m("p",{class:"eyebrow"},"Account security",-1),m("h1",null,"Reset Password",-1),m("p",{class:"subtitle"},"Imposta una nuova password usando il token ricevuto via email.",-1)])]),_:1}),s(h),s(w,{class:"card-body"},{default:n(()=>[s(f,{modelValue:u.value,"onUpdate:modelValue":a[0]||(a[0]=l=>u.value=l),label:"Token",outlined:"",autogrow:"",type:"textarea",hint:V.value},null,8,["modelValue","hint"]),s(f,{modelValue:r.value,"onUpdate:modelValue":a[2]||(a[2]=l=>r.value=l),label:"Nuova password",outlined:"",type:c.value?"text":"password"},{append:n(()=>[s(y,{name:c.value?"visibility_off":"visibility",class:"cursor-pointer",onClick:a[1]||(a[1]=l=>c.value=!c.value)},null,8,["name"])]),_:1},8,["modelValue","type"]),s(f,{modelValue:d.value,"onUpdate:modelValue":a[4]||(a[4]=l=>d.value=l),label:"Conferma password",outlined:"",type:v.value?"text":"password"},{append:n(()=>[s(y,{name:v.value?"visibility_off":"visibility",class:"cursor-pointer",onClick:a[3]||(a[3]=l=>v.value=!v.value)},null,8,["name"])]),_:1},8,["modelValue","type"]),o.value?(g(),k("div",F,_(o.value),1)):b("",!0),i.value?(g(),k("div",M,_(i.value),1)):b("",!0)]),_:1}),s(B,{align:"right",class:"card-actions"},{default:n(()=>[s(A,{color:"primary",icon:"lock_reset",label:"Aggiorna password",loading:p.value,onClick:x},null,8,["loading"])]),_:1})]),_:1})])]),_:1}))}}),ee=L($,[["__scopeId","data-v-7f13b293"]]);export{ee as default};

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
.services-page[data-v-9d56fed6]{background:linear-gradient(180deg,#f6fbf8,#fff 34%,#eef5ff);color:#163047}.page-shell[data-v-9d56fed6]{width:min(1180px,100% - 32px);margin:0 auto}.hero-section[data-v-9d56fed6]{padding:72px 0 44px}.hero-panel[data-v-9d56fed6]{padding:42px;border-radius:36px;background:linear-gradient(135deg,#dff7ee,#dbeafe);box-shadow:0 28px 80px #16304714}.eyebrow[data-v-9d56fed6]{display:inline-flex;align-items:center;padding:10px 16px;margin-bottom:22px;border-radius:999px;background:#ffffffa8;color:#0f766e;font-size:.88rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.hero-title[data-v-9d56fed6]{margin:0 0 18px;font-size:clamp(2.8rem,5vw,4.4rem);line-height:1;font-weight:800;letter-spacing:-.04em}.hero-text[data-v-9d56fed6]{max-width:620px;margin:0;font-size:1.08rem;line-height:1.7;color:#55687c}.hero-summary[data-v-9d56fed6]{display:grid;gap:16px}.metric-card[data-v-9d56fed6]{padding:22px;border-radius:24px;background:#ffffffd1}.metric-value[data-v-9d56fed6]{font-size:1.8rem;font-weight:800}.metric-label[data-v-9d56fed6]{margin-top:8px;color:#617486;line-height:1.55}.services-section[data-v-9d56fed6],.workflow-section[data-v-9d56fed6],.cta-section[data-v-9d56fed6]{padding:56px 0}.section-heading[data-v-9d56fed6]{max-width:700px;margin-bottom:30px}.align-center[data-v-9d56fed6]{margin-left:auto;margin-right:auto;text-align:center}.section-kicker[data-v-9d56fed6]{margin-bottom:10px;color:#0f766e;font-size:.85rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em}.section-title[data-v-9d56fed6]{margin:0 0 14px;font-size:clamp(2rem,4vw,3.2rem);line-height:1.05;font-weight:800;letter-spacing:-.03em}.section-text[data-v-9d56fed6]{margin:0;color:#607284;line-height:1.7;font-size:1.02rem}.service-card[data-v-9d56fed6],.workflow-card[data-v-9d56fed6],.cta-card[data-v-9d56fed6]{border-radius:28px;background:#ffffffe0;box-shadow:0 24px 70px #16304714}.service-card[data-v-9d56fed6]{overflow:hidden;height:100%}.service-image[data-v-9d56fed6]{display:block;width:100%;height:240px;object-fit:cover}.service-content[data-v-9d56fed6]{padding:24px}.service-icon[data-v-9d56fed6]{width:60px;height:60px;margin-bottom:16px}.service-title[data-v-9d56fed6],.workflow-title[data-v-9d56fed6],.cta-title[data-v-9d56fed6]{margin:0 0 12px;font-weight:800}.service-title[data-v-9d56fed6]{font-size:1.32rem}.service-text[data-v-9d56fed6],.workflow-text[data-v-9d56fed6],.cta-text[data-v-9d56fed6]{margin:0;color:#647789;line-height:1.68}.service-points[data-v-9d56fed6]{display:grid;gap:10px;padding:0;margin:18px 0 0;list-style:none}.service-points li[data-v-9d56fed6]{display:flex;align-items:center;gap:10px}.workflow-section[data-v-9d56fed6]{background:#ffffff9e}.workflow-grid[data-v-9d56fed6]{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:16px}.workflow-card[data-v-9d56fed6]{padding:26px;height:100%}.workflow-number[data-v-9d56fed6]{margin-bottom:14px;color:#0f766e;font-size:.9rem;font-weight:800;letter-spacing:.08em}.workflow-title[data-v-9d56fed6]{font-size:1.24rem}.cta-card[data-v-9d56fed6]{overflow:hidden;padding:38px}.cta-copy[data-v-9d56fed6]{max-width:580px}.cta-title[data-v-9d56fed6]{font-size:clamp(2rem,3.6vw,3rem);line-height:1.08;letter-spacing:-.03em}.cta-text[data-v-9d56fed6]{margin-bottom:24px}.cta-actions[data-v-9d56fed6]{display:flex;flex-wrap:wrap;gap:14px}.cta-visual[data-v-9d56fed6]{position:relative;min-height:360px}.cta-image-main[data-v-9d56fed6],.cta-image-secondary[data-v-9d56fed6]{position:absolute;display:block;max-width:100%}.cta-image-main[data-v-9d56fed6]{right:0;top:0;width:min(82%,320px)}.cta-image-secondary[data-v-9d56fed6]{left:0;bottom:0;width:min(58%,220px)}.cta-badge[data-v-9d56fed6]{position:absolute;left:22px;top:26px;display:flex;align-items:center;gap:14px;padding:16px 18px;border-radius:22px;background:#fffffff0;box-shadow:0 18px 50px #16304724}.cta-badge-icon[data-v-9d56fed6]{width:46px;height:46px}.cta-badge-title[data-v-9d56fed6]{font-weight:800}.cta-badge-text[data-v-9d56fed6]{margin-top:4px;color:#647789}@media(max-width:1023px){.workflow-grid[data-v-9d56fed6]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:599px){.page-shell[data-v-9d56fed6]{width:min(100% - 24px,1180px)}.hero-section[data-v-9d56fed6],.services-section[data-v-9d56fed6],.workflow-section[data-v-9d56fed6],.cta-section[data-v-9d56fed6]{padding:40px 0}.hero-panel[data-v-9d56fed6],.cta-card[data-v-9d56fed6]{padding:24px}.hero-title[data-v-9d56fed6]{font-size:2.5rem}.workflow-grid[data-v-9d56fed6]{grid-template-columns:1fr}.cta-visual[data-v-9d56fed6]{min-height:300px;margin-top:16px}.cta-badge[data-v-9d56fed6]{left:8px;top:8px}}

View File

@ -0,0 +1 @@
import{a as V,o as N,w as b,a4 as x,h as d,i as g,j as i,m as l,k as t,F as Q,a3 as w,v as k,I as C,J as n,a5 as _,Q as p,s as P,y as S,D as c,K as U}from"./index-DAvBaevK.js";import{Q as h}from"./QForm-CgLsd63I.js";import{Q as z}from"./QPage-B68JuyjH.js";import{u as E}from"./use-quasar-B5tVCAcV.js";import{E as B,r as I}from"./api-RGUeM09o.js";import{_ as R}from"./_plugin-vue_export-helper-DlAUqK2U.js";const T={class:"auth-shell auth-shell-wide"},F={class:"auth-actions"},L={key:1,class:"success-state"},$={class:"success-actions"},D=V({__name:"SignupPage",setup(M){const r=E(),m=c(!1),u=c(!1),f=c(),e=U({firstName:"",lastName:"",email:"",password:"",confirmPassword:"",acceptTerms:!1});N(async()=>{await y()}),b(u,async o=>{o||await y()});async function v(){if(!e.firstName.trim()||!e.lastName.trim()||!e.email.trim()){r.notify({type:"negative",message:"Compila tutti i campi obbligatori."});return}if(e.password.length<8){r.notify({type:"negative",message:"La password deve contenere almeno 8 caratteri."});return}if(e.password!==e.confirmPassword){r.notify({type:"negative",message:"Le password non coincidono."});return}if(!e.acceptTerms){r.notify({type:"negative",message:"Devi accettare le condizioni."});return}m.value=!0;try{const o={name:`${e.firstName.trim()} ${e.lastName.trim()}`.trim(),email:e.email.trim(),password:e.password,roles:["user"],status:B.UserStatusPending,types:["internal"],avatar:null,details:{title:"",firstName:e.firstName.trim(),lastName:e.lastName.trim(),address:"",city:"",zipCode:"",country:"",phone:""},preferences:null},a=await I(o);if(a.error)throw new Error(a.error);u.value=!0}catch(o){r.notify({type:"negative",message:o instanceof Error?o.message:String(o)})}finally{m.value=!1}}async function y(){await x(),f.value?.focus?.()}return(o,a)=>(d(),g(z,{class:"auth-page"},{default:i(()=>[l("div",T,[t(Q,{flat:"",bordered:"",class:"auth-card"},{default:i(()=>[t(w,null,{default:i(()=>[...a[6]||(a[6]=[l("div",{class:"text-overline text-primary"},"Registrazione",-1),l("div",{class:"text-h4"},"Sign up",-1),l("div",{class:"text-body2 text-grey-7"},"Crea un nuovo utente.",-1)])]),_:1}),t(k),t(w,null,{default:i(()=>[u.value?(d(),P("div",L,[t(S,{name:"task_alt",size:"56px",color:"positive"}),a[7]||(a[7]=l("div",{class:"text-h6"},"Registrazione completata",-1)),a[8]||(a[8]=l("div",{class:"text-body2 text-grey-7"}," Il tuo account e stato creato con successo. ",-1)),l("div",$,[t(p,{flat:"",color:"primary",label:"Home",to:"/"}),t(p,{color:"primary",label:"Login",to:"/login"})])])):(d(),g(h,{key:0,class:"auth-form",autocomplete:"off",onSubmit:C(v,["prevent"])},{default:i(()=>[t(n,{ref_key:"firstNameRef",ref:f,modelValue:e.firstName,"onUpdate:modelValue":a[0]||(a[0]=s=>e.firstName=s),outlined:"",label:"Nome",autocomplete:"off"},null,8,["modelValue"]),t(n,{modelValue:e.lastName,"onUpdate:modelValue":a[1]||(a[1]=s=>e.lastName=s),outlined:"",label:"Cognome",autocomplete:"off"},null,8,["modelValue"]),t(n,{modelValue:e.email,"onUpdate:modelValue":a[2]||(a[2]=s=>e.email=s),outlined:"",type:"email",label:"Email",autocomplete:"off"},null,8,["modelValue"]),t(n,{modelValue:e.password,"onUpdate:modelValue":a[3]||(a[3]=s=>e.password=s),outlined:"",type:"password",label:"Password",autocomplete:"new-password"},null,8,["modelValue"]),t(n,{modelValue:e.confirmPassword,"onUpdate:modelValue":a[4]||(a[4]=s=>e.confirmPassword=s),outlined:"",type:"password",label:"Ripeti password",autocomplete:"new-password"},null,8,["modelValue"]),t(_,{modelValue:e.acceptTerms,"onUpdate:modelValue":a[5]||(a[5]=s=>e.acceptTerms=s),label:"Accetto le condizioni"},null,8,["modelValue"]),l("div",F,[t(p,{color:"primary",label:"Crea account",type:"submit",loading:m.value},null,8,["loading"])])]),_:1}))]),_:1})]),_:1})])]),_:1}))}}),G=R(D,[["__scopeId","data-v-72d36ea8"]]);export{G as default};

View File

@ -0,0 +1 @@
.auth-page[data-v-72d36ea8]{background:linear-gradient(180deg,#f7fafc,#e9f0f7)}.auth-shell[data-v-72d36ea8]{max-width:520px;margin:0 auto;padding:40px 20px}.auth-shell-wide[data-v-72d36ea8]{max-width:760px}.auth-card[data-v-72d36ea8]{border-radius:24px}.auth-form[data-v-72d36ea8]{display:grid;gap:14px}.auth-actions[data-v-72d36ea8]{display:flex;justify-content:flex-end}.success-state[data-v-72d36ea8]{display:grid;justify-items:center;gap:12px;text-align:center;padding:12px 0}.success-actions[data-v-72d36ea8]{display:flex;gap:12px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1 @@
function f(r){return typeof r=="object"&&r!==null&&Object.prototype.hasOwnProperty.call(r,"data")&&Object.prototype.hasOwnProperty.call(r,"error")}function w(r){return r instanceof DOMException&&r.name==="AbortError"?new Error("api.error.timeouterror"):r instanceof TypeError&&r.message==="Failed to fetch"?new Error("api.error.connectionerror"):r instanceof Error?r:new Error(String(r))}class d{apiUrl;localStorage;constructor(t){this.apiUrl=t,this.localStorage=window.localStorage}async request(t,e,s,o=7e3,i=!1){const u={"Cache-Control":"no-cache"};if(i||(u["Content-Type"]="application/json"),this.localStorage){const n=this.localStorage.getItem("Auth-Token");n&&(u["Auth-Token"]=n)}const h=new AbortController,y=setTimeout(()=>h.abort(),o),l={method:t,cache:"no-store",mode:"cors",credentials:"include",headers:u,signal:h.signal};i?l.body=s:s!=null&&(l.body=JSON.stringify(s));try{const n=await fetch(e,l);if(!n.ok)throw new Error("api.error."+n.statusText);if(this.localStorage){const p=n.headers.get("Auth-Token");p&&this.localStorage.setItem("Auth-Token",p)}const c=await n.json();if(!f(c))throw new Error("api.error.wrongdatatype");if(c.error)throw new Error(c.error);return c}catch(n){throw w(n)}finally{clearTimeout(y)}}processResult(t){return typeof t.data!="object"?{data:t.data,error:null}:(t.data||(t.data={}),{data:t.data,error:null})}processError(t){const e=w(t);return e.message==="api.error.timeouterror"?(Object.defineProperty(e,"__api_error__",{value:e.message,writable:!1}),{data:null,error:e.message}):e.message==="api.error.connectionerror"?(Object.defineProperty(e,"__api_error__",{value:e.message,writable:!1}),{data:null,error:e.message}):{data:null,error:e.message}}async POST(t,e,s){try{const o=t.includes("/upload/"),i=await this.request("POST",this.apiUrl+t,e,s,o);return this.processResult(i)}catch(o){return this.processError(o)}}async GET(t,e){try{const s=await this.request("GET",this.apiUrl+t,null,e);return this.processResult(s)}catch(s){return this.processError(s)}}async PUT(t,e,s){try{const o=await this.request("PUT",this.apiUrl+t,e,s);return this.processResult(o)}catch(o){return this.processError(o)}}async DELETE(t,e){try{const s=await this.request("DELETE",this.apiUrl+t,null,e);return this.processResult(s)}catch(s){return this.processError(s)}}async UPLOAD(t,e,s){try{const o=await this.request("POST",this.apiUrl+t,e,s,!0);return this.processResult(o)}catch(o){return this.processError(o)}}}const a=new d("http://localhost:3000"),g={UserStatusPending:"pending",UserStatusActive:"active",UserStatusDisabled:"disabled"},E=async()=>await a.GET("/maildebug"),T=async r=>await a.POST("/admin/users",r),m=async(r,t)=>await a.PUT(`/admin/users/${r}/block`,t),S=async r=>await a.POST("/auth/register",r),P=async()=>await a.GET("/metrics"),U=async r=>await a.POST("/auth/login",r),b=async r=>await a.POST("/auth/refresh",r),O=async r=>await a.POST("/auth/password/forgot",r),j=async r=>await a.POST("/auth/password/reset",r),A=async()=>await a.GET("/health"),_=async()=>await a.GET("/auth/me"),R=async r=>await a.GET(`/users/${r}`),k=async r=>await a.POST("/users",r),q=async(r,t)=>await a.PUT(`/users/${r}`,t);export{g as E,j as a,P as b,b as c,T as d,E as e,O as f,k as g,A as h,m as i,R as j,U as l,_ as m,S as r,q as u};

View File

@ -1 +0,0 @@
import{u as w,a as y}from"./use-dark-BRt0_t6X.js";import{s as T,y as S,A as E,p as h}from"./index-QUdrNkKl.js";const b={true:"inset",item:"item-inset","item-thumbnail":"item-thumbnail-inset"},f={xs:2,sm:4,md:8,lg:16,xl:24},A=T({name:"QSeparator",props:{...w,spaced:[Boolean,String],inset:[Boolean,String],vertical:Boolean,color:String,size:String},setup(r){const t=E(),e=y(r,t.proxy.$q),a=h(()=>r.vertical===!0?"vertical":"horizontal"),s=h(()=>` q-separator--${a.value}`),i=h(()=>r.inset!==!1?`${s.value}-${b[r.inset]}`:""),l=h(()=>`q-separator${s.value}${i.value}`+(r.color!==void 0?` bg-${r.color}`:"")+(e.value===!0?" q-separator--dark":"")),m=h(()=>{const c={};if(r.size!==void 0&&(c[r.vertical===!0?"width":"height"]=r.size),r.spaced!==!1){const u=r.spaced===!0?`${f.md}px`:r.spaced in f?`${f[r.spaced]}px`:r.spaced,o=r.vertical===!0?["Left","Right"]:["Top","Bottom"];c[`margin${o[0]}`]=c[`margin${o[1]}`]=u}return c});return()=>S("hr",{class:l.value,style:m.value,"aria-orientation":a.value})}});function v(r){return typeof r=="object"&&r!==null&&Object.prototype.hasOwnProperty.call(r,"data")&&Object.prototype.hasOwnProperty.call(r,"error")}function g(r){return r instanceof DOMException&&r.name==="AbortError"?new Error("api.error.timeouterror"):r instanceof TypeError&&r.message==="Failed to fetch"?new Error("api.error.connectionerror"):r instanceof Error?r:new Error(String(r))}class O{apiUrl;localStorage;constructor(t){this.apiUrl=t,this.localStorage=window.localStorage}async request(t,e,a,s=7e3,i=!1){const l={"Cache-Control":"no-cache"};if(i||(l["Content-Type"]="application/json"),this.localStorage){const o=this.localStorage.getItem("Auth-Token");o&&(l["Auth-Token"]=o)}const m=new AbortController,c=setTimeout(()=>m.abort(),s),u={method:t,cache:"no-store",mode:"cors",credentials:"include",headers:l,signal:m.signal};i?u.body=a:a!=null&&(u.body=JSON.stringify(a));try{const o=await fetch(e,u);if(!o.ok)throw new Error("api.error."+o.statusText);if(this.localStorage){const d=o.headers.get("Auth-Token");d&&this.localStorage.setItem("Auth-Token",d)}const p=await o.json();if(!v(p))throw new Error("api.error.wrongdatatype");if(p.error)throw new Error(p.error);return p}catch(o){throw g(o)}finally{clearTimeout(c)}}processResult(t){return typeof t.data!="object"?{data:t.data,error:null}:(t.data||(t.data={}),{data:t.data,error:null})}processError(t){const e=g(t);return e.message==="api.error.timeouterror"?(Object.defineProperty(e,"__api_error__",{value:e.message,writable:!1}),{data:null,error:e.message}):e.message==="api.error.connectionerror"?(Object.defineProperty(e,"__api_error__",{value:e.message,writable:!1}),{data:null,error:e.message}):{data:null,error:e.message}}async POST(t,e,a){try{const s=t.includes("/upload/"),i=await this.request("POST",this.apiUrl+t,e,a,s);return this.processResult(i)}catch(s){return this.processError(s)}}async GET(t,e){try{const a=await this.request("GET",this.apiUrl+t,null,e);return this.processResult(a)}catch(a){return this.processError(a)}}async UPLOAD(t,e,a){try{const s=await this.request("POST",this.apiUrl+t,e,a,!0);return this.processResult(s)}catch(s){return this.processError(s)}}}const n=new O("http://localhost:3000"),_=async()=>await n.GET("/maildebug"),j=async r=>await n.POST("/admin/users",r),k=async r=>await n.POST("/auth/register",r),q=async()=>await n.GET("/metrics"),x=async r=>await n.POST("/auth/login",r),C=async r=>await n.POST("/auth/refresh",r),z=async r=>await n.POST("/auth/password/forgot",r),D=async r=>await n.POST("/auth/password/reset",r),R=async()=>await n.GET("/health"),U=async()=>await n.GET("/auth/me");export{A as Q,C as a,j as b,U as c,k as d,_ as e,z as f,R as h,x as l,q as m,D as r};

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

View File

@ -0,0 +1 @@
import{L as v,M as c,a1 as q,E as u,bh as w,ag as I,$ as E,bi as Q,D as f,aK as S,a2 as K,ao as R,an as $}from"./index-DAvBaevK.js";const D=v({name:"QItemLabel",props:{overline:Boolean,caption:Boolean,header:Boolean,lines:[Number,String]},setup(e,{slots:a}){const n=u(()=>parseInt(e.lines,10)),i=u(()=>"q-item__label"+(e.overline===!0?" q-item__label--overline text-overline":"")+(e.caption===!0?" q-item__label--caption text-caption":"")+(e.header===!0?" q-item__label--header":"")+(n.value===1?" ellipsis":"")),l=u(()=>e.lines!==void 0&&n.value>1?{overflow:"hidden",display:"-webkit-box","-webkit-box-orient":"vertical","-webkit-line-clamp":n.value}:null);return()=>c("div",{style:l.value,class:i.value},q(a.default))}}),M=v({name:"QItemSection",props:{avatar:Boolean,thumbnail:Boolean,side:Boolean,top:Boolean,noWrap:Boolean},setup(e,{slots:a}){const n=u(()=>`q-item__section column q-item__section--${e.avatar===!0||e.side===!0||e.thumbnail===!0?"side":"main"}`+(e.top===!0?" q-item__section--top justify-start":" justify-center")+(e.avatar===!0?" q-item__section--avatar":"")+(e.thumbnail===!0?" q-item__section--thumbnail":"")+(e.noWrap===!0?" q-item__section--nowrap":""));return()=>c("div",{class:n.value},q(a.default))}}),j=v({name:"QItem",props:{...I,...w,tag:{type:String,default:"div"},active:{type:Boolean,default:null},clickable:Boolean,dense:Boolean,insetLevel:Number,tabindex:[String,Number],focused:Boolean,manualFocus:Boolean},emits:["click","keyup"],setup(e,{slots:a,emit:n}){const{proxy:{$q:i}}=E(),l=$(e,i),{hasLink:d,linkAttrs:k,linkClass:h,linkTag:_,navigateOnClick:y}=Q(),o=f(null),r=f(null),m=u(()=>e.clickable===!0||d.value===!0||e.tag==="label"),s=u(()=>e.disable!==!0&&m.value===!0),g=u(()=>"q-item q-item-type row no-wrap"+(e.dense===!0?" q-item--dense":"")+(l.value===!0?" q-item--dark":"")+(d.value===!0&&e.active===null?h.value:e.active===!0?` q-item--active${e.activeClass!==void 0?` ${e.activeClass}`:""}`:"")+(e.disable===!0?" disabled":"")+(s.value===!0?" q-item--clickable q-link cursor-pointer "+(e.manualFocus===!0?"q-manual-focusable":"q-focusable q-hoverable")+(e.focused===!0?" q-manual-focusable--focused":""):"")),B=u(()=>e.insetLevel===void 0?null:{["padding"+(i.lang.rtl===!0?"Right":"Left")]:16+e.insetLevel*56+"px"});function x(t){s.value===!0&&(r.value!==null&&t.qAvoidFocus!==!0&&(t.qKeyEvent!==!0&&document.activeElement===o.value?r.value.focus():document.activeElement===r.value&&o.value.focus()),y(t))}function L(t){if(s.value===!0&&S(t,[13,32])===!0){K(t),t.qKeyEvent=!0;const b=new MouseEvent("click",t);b.qKeyEvent=!0,o.value.dispatchEvent(b)}n("keyup",t)}function C(){const t=R(a.default,[]);return s.value===!0&&t.unshift(c("div",{class:"q-focus-helper",tabindex:-1,ref:r})),t}return()=>{const t={ref:o,class:g.value,style:B.value,role:"listitem",onClick:x,onKeyup:L};return s.value===!0?(t.tabindex=e.tabindex||"0",Object.assign(t,k.value)):m.value===!0&&(t["aria-disabled"]="true"),c(_.value,t,C())}}});function F(e,a,n){return n<=a?a:Math.min(n,Math.max(a,e))}function N(e,a,n){if(n<=a)return a;const i=n-a+1;let l=a+(e-a)%i;return l<a&&(l=i+l),l===0?0:l}export{j as Q,M as a,D as b,F as c,N as n};

View File

@ -1 +0,0 @@
import{ab as l}from"./index-QUdrNkKl.js";function r(){if(window.getSelection!==void 0){const t=window.getSelection();t.empty!==void 0?t.empty():t.removeAllRanges!==void 0&&(t.removeAllRanges(),l.is.mobile!==!0&&t.addRange(document.createRange()))}else document.selection!==void 0&&document.selection.empty()}function a(t,e,o){return o<=e?e:Math.min(o,Math.max(e,t))}function s(t,e,o){if(o<=e)return e;const i=o-e+1;let n=e+(t-e)%i;return n<e&&(n=i+n),n===0?0:n}export{a as b,r as c,s as n};

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 KiB

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
import{d as a,c as o,r as c,l as n}from"./index-QUdrNkKl.js";const t={failed:"Action failed",success:"Action was successful"},l={"en-US":t},d=a(({app:e})=>{const s=o({locale:c(n()),messages:l});e.use(s)});export{d as default};

View File

@ -0,0 +1,16 @@
<svg width="34" height="34" viewBox="0 0 34 34" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_91_185)">
<path d="M15.1816 20.9983C17.2177 18.9622 17.2177 15.6476 15.1816 13.6108C13.1441 11.5734 9.83028 11.5741 7.79415 13.6108C5.75311 15.6519 5.75245 18.9579 7.79415 20.9983C9.83294 23.0384 13.1406 23.0393 15.1816 20.9983ZM8.50538 14.3221C10.1546 12.6742 12.8284 12.6814 14.4703 14.3221C16.1148 15.9672 16.1148 18.6426 14.4703 20.287C12.8236 21.9338 10.1534 21.935 8.50538 20.287C6.85701 18.6387 6.85739 15.9701 8.50538 14.3221Z" fill="#4753BF"/>
<path d="M32.3436 9.46459C30.9643 8.72464 29.2106 9.1256 28.3061 10.4404L26.8921 12.4877L26.8423 4.98563C26.8423 3.63082 25.7424 2.43669 24.2705 2.43669C23.6869 2.44063 23.1479 2.64103 22.7177 2.97504V2.90758C22.6989 1.26318 21.18 0.047444 19.5453 0.437899C18.4312 0.698551 17.6178 1.76803 17.5949 2.99665C16.9813 2.52314 16.1816 2.36007 15.3983 2.55982C14.2745 2.84536 13.4899 3.89781 13.4899 5.12184L13.4991 6.78009C13.0033 6.40548 12.4021 6.22603 11.7734 6.27449C10.4334 6.36356 9.39081 7.53979 9.39933 8.95244L9.40322 9.52336C8.04762 9.88373 6.80251 10.5874 5.78486 11.6055C3.3101 14.0803 2.76435 17.7624 4.22608 20.7936C2.83512 21.5385 1.52754 22.4637 0.993499 22.9971C-0.333946 24.3245 -0.330071 26.4689 0.998082 27.7957C2.31045 29.108 4.4586 29.133 5.7973 27.7943C6.32683 27.2612 7.25243 25.9534 8.00149 24.5619C9.39829 25.2313 10.9404 25.5106 12.629 25.2708C12.9156 25.4751 13.2117 25.6613 13.5198 25.8215C12.7089 26.0908 12.1202 26.8494 12.1244 27.7485L12.1362 31.6151C12.1415 32.7311 13.0511 33.6355 14.1664 33.6355H14.1763L25.5037 33.5825C26.6229 33.5766 27.5293 32.6617 27.5241 31.5437L27.5123 27.6778C27.5123 27.6771 27.5123 27.6771 27.5123 27.6765C27.5077 26.7085 26.8211 25.9013 25.9108 25.7044C27.4451 24.6964 28.4676 22.9027 29.8241 20.5215L33.6056 13.7333C34.4542 12.205 33.8875 10.2801 32.3436 9.46459ZM10.4079 9.31788L10.4053 8.9459C10.4 8.07944 11.0438 7.33087 11.8441 7.27783C12.7147 7.21066 13.3947 7.87247 13.4899 8.55295C13.4899 8.55442 13.4903 8.55606 13.4903 8.55753L13.4979 9.50462C12.5082 9.25352 11.5315 9.16786 10.4079 9.31788ZM7.12023 24.0816C6.42209 25.379 5.55302 26.6135 5.08475 27.0844C4.15147 28.0177 2.63988 28.015 1.70933 27.0844C0.775765 26.1508 0.769616 24.6434 1.70474 23.7083C2.17759 23.2361 3.41407 22.3657 4.71277 21.6715C5.00617 22.1229 5.38476 22.6003 5.78879 23.0036C5.78924 23.0041 5.78973 23.0044 5.79018 23.0049C5.79063 23.0053 5.79096 23.0058 5.7914 23.0062C6.31211 23.527 7.05313 24.0385 7.12023 24.0816ZM6.51115 22.3025C6.50804 22.2994 6.50464 22.2969 6.50158 22.2939C3.78341 19.5736 3.70098 15.1132 6.49609 12.3167C9.27207 9.54065 13.7668 9.60461 16.479 12.3167C19.1514 14.9888 19.2369 19.2733 16.6835 22.063C13.8736 25.1211 9.23598 25.019 6.51115 22.3025ZM26.5063 27.6804L26.5181 31.5476C26.5208 32.1115 26.063 32.5732 25.4984 32.5765L14.171 32.6296C14.1697 32.6296 14.1678 32.6296 14.1665 32.6296C13.6039 32.6296 13.1448 32.1731 13.1422 31.6112L13.1304 27.7446C13.1278 27.18 13.5849 26.7183 14.1501 26.7157L25.4775 26.6626H25.4821C26.0446 26.6626 26.5031 27.1185 26.5063 27.6804ZM32.7267 13.2447C32.7261 13.2447 32.7261 13.2447 32.7261 13.2454C32.34 13.9385 34.1246 10.7347 28.9505 20.0238C26.8161 23.7699 25.7473 25.6364 22.3594 25.6207L17.0088 25.6541C16.9983 25.6541 16.9878 25.6541 16.978 25.6541C15.9347 25.6541 14.9333 25.4144 14.0289 24.9533C15.1629 24.5799 16.4018 23.8436 17.3851 22.7847C20.3632 19.5917 20.2405 14.6526 17.1921 11.6042C16.5138 10.9269 15.528 10.2398 14.5067 9.82873C14.5057 9.37907 14.4954 4.92862 14.4959 5.11924C14.4959 4.35823 14.9687 3.70659 15.6459 3.53434C16.617 3.28725 17.5198 3.96119 17.5963 4.92375L17.6512 11.8347C17.6532 12.1111 17.8785 12.3338 18.1542 12.3338H18.1582C18.4358 12.3318 18.6592 12.1046 18.6572 11.8269C18.5968 2.52504 18.6007 3.11458 18.6002 3.04708C18.6002 2.26184 19.094 1.5768 19.7777 1.417C20.7765 1.17458 21.7007 1.91686 21.7117 2.91544C21.7907 15.1115 21.7634 10.9051 21.7693 11.8151C21.7713 12.0914 21.9959 12.3141 22.2723 12.3141H22.2762C22.5539 12.3122 22.7773 12.0849 22.7753 11.8072L22.7233 5.01321C22.7233 5.01035 22.7249 5.00806 22.7249 5.00527C22.7249 4.1493 23.421 3.44789 24.2737 3.44265C25.1637 3.44265 25.8364 4.16513 25.8364 4.9889L25.8934 13.6076C23.132 13.8626 20.9625 16.1896 20.9625 19.0165C20.9625 19.2942 21.1878 19.5195 21.4655 19.5195C21.7431 19.5195 21.9684 19.2942 21.9684 19.0165C21.9684 16.5743 23.9548 14.588 26.397 14.588C26.3981 14.588 26.399 14.5873 26.4001 14.5873C26.594 14.5881 26.765 14.4421 26.8135 14.3712L29.1345 11.0108C29.7246 10.1542 30.946 9.85755 31.8714 10.3527C32.9153 10.9031 33.3027 12.2054 32.7267 13.2447Z" fill="#4753BF"/>
<path d="M16.627 29.1428H15.492C15.2144 29.1428 14.9891 29.3681 14.9891 29.6458C14.9891 29.9235 15.2144 30.1488 15.492 30.1488H16.627C16.9047 30.1488 17.13 29.9235 17.13 29.6458C17.13 29.3681 16.9047 29.1428 16.627 29.1428Z" fill="#4753BF"/>
<path d="M10.5632 14.9004C10.5632 14.6227 10.3379 14.3974 10.0602 14.3974C9.09486 14.3974 8.30896 15.1826 8.30896 16.148C8.30896 16.4257 8.53425 16.651 8.81193 16.651C9.08961 16.651 9.31491 16.4257 9.31491 16.148C9.31491 15.7374 9.64957 15.4034 10.0602 15.4034C10.3379 15.4034 10.5632 15.1781 10.5632 14.9004Z" fill="#4753BF"/>
<path d="M13.1998 16.1277C13.5542 15.9234 14.0126 16.0439 14.2189 16.3995C14.358 16.6394 14.6668 16.7211 14.9066 16.5816C15.1463 16.4421 15.2281 16.1342 15.0886 15.8939C14.6033 15.0589 13.5312 14.774 12.6956 15.258C12.4552 15.3968 12.3733 15.7046 12.5128 15.945C12.651 16.1847 12.9588 16.2685 13.1998 16.1277Z" fill="#4753BF"/>
<path d="M12.1114 19.2975C12.389 19.2975 12.6143 19.0722 12.6143 18.7945C12.6143 18.5168 12.389 18.2915 12.1114 18.2915C11.146 18.2915 10.3608 19.0767 10.3608 20.0421C10.3608 20.3198 10.5861 20.5451 10.8638 20.5451C11.1414 20.5451 11.3667 20.3198 11.3667 20.0421C11.3667 19.6315 11.7007 19.2975 12.1114 19.2975Z" fill="#4753BF"/>
<path d="M11.8965 17.782C12.167 17.8381 12.4352 17.6662 12.4925 17.393C12.5495 17.1212 12.3753 16.854 12.1035 16.797C11.7003 16.7131 11.4422 16.319 11.5278 15.9155C11.5848 15.6437 11.4106 15.3772 11.1388 15.3195C10.8716 15.2639 10.6011 15.4361 10.5428 15.7085C10.3447 16.6557 10.9479 17.5828 11.8965 17.782Z" fill="#4753BF"/>
</g>
<defs>
<clipPath id="clip0_91_185">
<rect width="34" height="34" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,12 @@
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_91_244)">
<path d="M27.5428 29.8527C27.7285 29.6609 27.7235 29.3546 27.5315 29.1689L21.6566 23.4813C23.4603 22.8765 24.7649 21.1739 24.7649 19.1694V17.7358H25.9675C26.7684 17.7358 27.42 17.0842 27.42 16.283V12.9089C27.42 12.108 26.7684 11.4564 25.9675 11.4564H24.7649V10.6445H25.1641C26.0279 10.6445 26.7312 9.94155 26.7312 9.07741C26.7312 8.21327 26.0279 7.51031 25.1641 7.51031H24.5392L22.9624 5.15179C22.5179 4.48629 21.7743 4.08901 20.9741 4.08901H17.0085C17.2089 3.44673 17.3368 2.78808 17.3368 2.34058C17.3368 1.04988 16.2898 0 15.0028 0C13.7121 0 12.6626 1.04988 12.6626 2.34057C12.6626 2.78866 12.7901 3.44719 12.9902 4.08901H9.02657C8.22633 4.08901 7.48276 4.48629 7.03889 5.15147L5.46152 7.51031H4.83651C3.97269 7.51031 3.26941 8.21327 3.26941 9.07741C3.26941 9.94155 3.97269 10.6445 4.83651 10.6445H5.23569V11.4564H4.03627C3.23478 11.4564 2.58313 12.108 2.58313 12.9089V16.283C2.58313 17.0842 3.23478 17.7358 4.03627 17.7358H5.23569V19.1694C5.23569 21.1737 6.5402 22.8762 8.3436 23.4812L2.46854 29.1689C2.27651 29.3547 2.27147 29.661 2.45721 29.8527C2.64537 30.0471 2.95131 30.0473 3.14097 29.864L9.50283 23.705C9.59692 23.7108 9.69034 23.7193 9.78588 23.7193H20.2148C20.3101 23.7193 20.4033 23.7108 20.4972 23.705L26.859 29.864C27.049 30.0476 27.355 30.0467 27.5428 29.8527ZM15.0028 0.967081C15.7565 0.967081 16.3697 1.58316 16.3697 2.34057C16.3697 2.69567 16.2381 3.3936 15.9913 4.08774H14.0074C13.7613 3.39423 13.6297 2.69631 13.6297 2.34057C13.6296 1.58316 14.2454 0.967081 15.0028 0.967081ZM25.9675 12.4235C26.2351 12.4235 26.4529 12.6413 26.4529 12.9089V16.283C26.4529 16.5509 26.2351 16.7687 25.9675 16.7687H24.7649V12.4235H25.9675ZM7.8429 5.68884C8.10734 5.29251 8.54995 5.05609 9.02657 5.05609H20.9741C21.4507 5.05609 21.8933 5.29251 22.1584 5.68916L23.3762 7.51031H6.62441L7.8429 5.68884ZM4.23649 9.07741C4.23649 8.74655 4.50597 8.47739 4.83651 8.47739C26.7531 8.47757 17.7492 8.47763 25.1641 8.47739C25.4947 8.47739 25.7641 8.74655 25.7641 9.07741C25.7641 9.40827 25.4947 9.67743 25.1641 9.67743C-13.1473 9.67681 27.0798 9.67734 4.83651 9.67743C4.50596 9.67743 4.23649 9.40827 4.23649 9.07741ZM4.03627 16.7687C3.76806 16.7687 3.55021 16.5509 3.55021 16.283V12.9089C3.55021 12.6413 3.76806 12.4235 4.03627 12.4235H5.23569V16.7687H4.03627ZM9.78588 22.7522C7.81016 22.7522 6.20277 21.1452 6.20277 19.1694C6.20344 19.2383 6.20548 15.3933 6.20277 10.6445H23.7979C23.7978 10.5794 23.7967 12.4874 23.7979 19.1694C23.7979 21.1452 22.1905 22.7522 20.2148 22.7522H9.78588Z" fill="white"/>
<path d="M9.9458 30H20.0548C20.1896 30 20.318 29.9437 20.4099 29.8448C20.5012 29.746 20.5472 29.6134 20.5371 29.479C20.4546 28.4194 19.0342 26.6165 18.7503 26.2658C18.5664 26.0385 18.1824 26.0385 17.9985 26.2658C17.8138 26.4939 17.1526 27.3361 16.6874 28.1888C16.2222 27.3361 15.5609 26.4939 15.3762 26.2658C15.1924 26.0385 14.8083 26.0385 14.6244 26.2658C14.4398 26.4939 13.7785 27.3359 13.3131 28.1885C12.8479 27.3359 12.1867 26.4938 12.0021 26.2658C11.8183 26.0385 11.4342 26.0385 11.2504 26.2658C10.9664 26.6165 9.54601 28.4194 9.46352 29.479C9.45345 29.6134 9.49941 29.746 9.59071 29.8448C9.68262 29.9437 9.81106 30 9.9458 30ZM18.3744 27.3632C18.7698 27.9012 19.1847 28.5419 19.4082 29.0329H17.3412C17.5647 28.5422 17.9796 27.9012 18.3744 27.3632ZM15.0003 27.3632C15.3951 27.9015 15.81 28.5422 16.0335 29.0329H13.9665C14.19 28.5422 14.6055 27.9015 15.0003 27.3632ZM11.6262 27.3632C12.021 27.9015 12.4359 28.5422 12.6594 29.0329H10.5924C10.8159 28.5422 11.2315 27.9015 11.6262 27.3632Z" fill="white"/>
<path d="M19.7192 11.9994H10.2808C9.32815 11.9994 8.5531 12.7744 8.5531 13.7274V18.9298C8.5531 19.8828 9.32815 20.6578 10.2808 20.6578H19.7192C20.6725 20.6578 21.4475 19.8828 21.4475 18.9298V13.7274C21.4475 12.7744 20.6725 11.9994 19.7192 11.9994ZM20.4804 18.9298C20.4804 19.3495 20.1392 19.6907 19.7192 19.6907H10.2808C9.86144 19.6907 9.52019 19.3495 9.52019 18.9298V13.7274C9.52019 13.3077 9.86144 12.9665 10.2808 12.9665H19.7192C20.1392 12.9665 20.4804 13.3077 20.4804 13.7274L20.4804 18.9298Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_91_244">
<rect width="30" height="30" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More