Merge branch 'develop' into MED-157
This commit is contained in:
@@ -2,4 +2,4 @@
|
||||
|
||||
@kit/analytics Package provides a simple and consistent API for tracking analytics events in web applications.
|
||||
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/analytics/analytics-and-events).
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/analytics/analytics-and-events).
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,17 +4,12 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^22.15.18"
|
||||
},
|
||||
|
||||
@@ -6,9 +6,9 @@ Make sure the app installs the `@kit/billing` package before using it.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"@kit/billing": "*"
|
||||
}
|
||||
"name": "my-app",
|
||||
"dependencies": {
|
||||
"@kit/billing": "*"
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,11 +4,8 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./components/*": "./src/components/*",
|
||||
@@ -16,8 +13,6 @@
|
||||
"./types": "./src/types/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*"
|
||||
|
||||
@@ -25,21 +25,32 @@ export const LineItemSchema = z
|
||||
.describe('Unique identifier for the line item. Defined by the Provider.')
|
||||
.min(1),
|
||||
name: z
|
||||
.string().describe('Name of the line item. Displayed to the user.')
|
||||
.string()
|
||||
.describe('Name of the line item. Displayed to the user.')
|
||||
.min(1),
|
||||
description: z
|
||||
.string().describe('Description of the line item. Displayed to the user and will replace the auto-generated description inferred' +
|
||||
' from the line item. This is useful if you want to provide a more detailed description to the user.')
|
||||
.string()
|
||||
.describe(
|
||||
'Description of the line item. Displayed to the user and will replace the auto-generated description inferred' +
|
||||
' from the line item. This is useful if you want to provide a more detailed description to the user.',
|
||||
)
|
||||
.optional(),
|
||||
cost: z
|
||||
.number().describe('Cost of the line item. Displayed to the user.')
|
||||
.number()
|
||||
.describe('Cost of the line item. Displayed to the user.')
|
||||
.min(0),
|
||||
type: LineItemTypeSchema,
|
||||
unit: z
|
||||
.string().describe('Unit of the line item. Displayed to the user. Example "seat" or "GB"')
|
||||
.string()
|
||||
.describe(
|
||||
'Unit of the line item. Displayed to the user. Example "seat" or "GB"',
|
||||
)
|
||||
.optional(),
|
||||
setupFee: z
|
||||
.number().describe(`Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`)
|
||||
.number()
|
||||
.describe(
|
||||
`Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`,
|
||||
)
|
||||
.positive()
|
||||
.optional(),
|
||||
tiers: z
|
||||
@@ -78,10 +89,12 @@ export const LineItemSchema = z
|
||||
export const PlanSchema = z
|
||||
.object({
|
||||
id: z
|
||||
.string().describe('Unique identifier for the plan. Defined by yourself.')
|
||||
.string()
|
||||
.describe('Unique identifier for the plan. Defined by yourself.')
|
||||
.min(1),
|
||||
name: z
|
||||
.string().describe('Name of the plan. Displayed to the user.')
|
||||
.string()
|
||||
.describe('Name of the plan. Displayed to the user.')
|
||||
.min(1),
|
||||
interval: BillingIntervalSchema.optional(),
|
||||
custom: z.boolean().default(false).optional(),
|
||||
@@ -106,7 +119,10 @@ export const PlanSchema = z
|
||||
},
|
||||
),
|
||||
trialDays: z
|
||||
.number().describe('Number of days for the trial period. Leave empty for no trial.')
|
||||
.number()
|
||||
.describe(
|
||||
'Number of days for the trial period. Leave empty for no trial.',
|
||||
)
|
||||
.positive()
|
||||
.optional(),
|
||||
paymentType: PaymentTypeSchema,
|
||||
@@ -188,34 +204,43 @@ export const PlanSchema = z
|
||||
const ProductSchema = z
|
||||
.object({
|
||||
id: z
|
||||
.string().describe('Unique identifier for the product. Defined by th Provider.')
|
||||
.string()
|
||||
.describe('Unique identifier for the product. Defined by th Provider.')
|
||||
.min(1),
|
||||
name: z
|
||||
.string().describe('Name of the product. Displayed to the user.')
|
||||
.string()
|
||||
.describe('Name of the product. Displayed to the user.')
|
||||
.min(1),
|
||||
description: z
|
||||
.string().describe('Description of the product. Displayed to the user.')
|
||||
.string()
|
||||
.describe('Description of the product. Displayed to the user.')
|
||||
.min(1),
|
||||
currency: z
|
||||
.string().describe('Currency code for the product. Displayed to the user.')
|
||||
.string()
|
||||
.describe('Currency code for the product. Displayed to the user.')
|
||||
.min(3)
|
||||
.max(3),
|
||||
badge: z
|
||||
.string().describe('Badge for the product. Displayed to the user. Example: "Popular"')
|
||||
.string()
|
||||
.describe(
|
||||
'Badge for the product. Displayed to the user. Example: "Popular"',
|
||||
)
|
||||
.optional(),
|
||||
features: z
|
||||
.array(
|
||||
z.string(),
|
||||
).describe('Features of the product. Displayed to the user.')
|
||||
.array(z.string())
|
||||
.describe('Features of the product. Displayed to the user.')
|
||||
.nonempty(),
|
||||
enableDiscountField: z
|
||||
.boolean().describe('Enable discount field for the product in the checkout.')
|
||||
.boolean()
|
||||
.describe('Enable discount field for the product in the checkout.')
|
||||
.optional(),
|
||||
highlighted: z
|
||||
.boolean().describe('Highlight this product. Displayed to the user.')
|
||||
.boolean()
|
||||
.describe('Highlight this product. Displayed to the user.')
|
||||
.optional(),
|
||||
hidden: z
|
||||
.boolean().describe('Hide this product from being displayed to users.')
|
||||
.boolean()
|
||||
.describe('Hide this product from being displayed to users.')
|
||||
.optional(),
|
||||
plans: z.array(PlanSchema),
|
||||
})
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ReportBillingUsageSchema = z.object({
|
||||
id: z.string().describe('The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.'),
|
||||
id: z
|
||||
.string()
|
||||
.describe(
|
||||
'The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.',
|
||||
),
|
||||
eventName: z
|
||||
.string()
|
||||
.describe('The name of the event that triggered the usage')
|
||||
|
||||
@@ -24,9 +24,7 @@ export interface IHandleWebhookEventParams {
|
||||
|
||||
// this method is called when an invoice is paid. We don't have a specific use case for this
|
||||
// but it's extremely common for credit-based systems
|
||||
onInvoicePaid: (
|
||||
subscription: UpsertSubscriptionParams,
|
||||
) => Promise<unknown>;
|
||||
onInvoicePaid: (subscription: UpsertSubscriptionParams) => Promise<unknown>;
|
||||
|
||||
// generic handler for any event
|
||||
onEvent?: (data: unknown) => Promise<unknown>;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Billing - @kit/billing-gateway
|
||||
|
||||
This package is responsible for handling all billing related operations. It is a gateway to the billing service.
|
||||
This package is responsible for handling all billing related operations. It is a gateway to the billing service.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,11 +4,8 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./components": "./src/components/index.ts",
|
||||
@@ -18,9 +15,7 @@
|
||||
"devDependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@kit/billing": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/lemon-squeezy": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/stripe": "workspace:*",
|
||||
"@kit/montonio": "workspace:*",
|
||||
|
||||
@@ -107,7 +107,7 @@ function BlurryBackdrop() {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'bg-background/30 fixed left-0 top-0 w-full backdrop-blur-sm' +
|
||||
'bg-background/30 fixed top-0 left-0 w-full backdrop-blur-sm' +
|
||||
' !m-0 h-full'
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -317,7 +317,7 @@ export function PlanPicker(
|
||||
|
||||
<div
|
||||
className={
|
||||
'flex flex-col gap-y-3 lg:flex-row lg:items-center lg:space-x-4 lg:space-y-0 lg:text-right'
|
||||
'flex flex-col gap-y-3 lg:flex-row lg:items-center lg:space-y-0 lg:space-x-4 lg:text-right'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
This package is responsible for handling all billing related operations using Lemon Squeezy.
|
||||
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy).
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy).
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,11 +4,8 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./components": "./src/components/index.ts"
|
||||
@@ -18,8 +15,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/billing": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# Billing / Montonio - @kit/montonio
|
||||
|
||||
This package is responsible for handling all billing related operations using Montonio.
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,18 +4,13 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/billing": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const MontonioClientEnvSchema = z
|
||||
.object({
|
||||
accessKey: z.string().min(1),
|
||||
});
|
||||
export const MontonioClientEnvSchema = z.object({
|
||||
accessKey: z.string().min(1),
|
||||
});
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const MontonioServerEnvSchema = z
|
||||
.object({
|
||||
secretKey: z
|
||||
.string({
|
||||
error: `Please provide the variable MONTONIO_SECRET_KEY`,
|
||||
})
|
||||
.min(1),
|
||||
apiUrl: z
|
||||
.string({
|
||||
error: `Please provide the variable MONTONIO_API_URL`,
|
||||
})
|
||||
.min(1),
|
||||
});
|
||||
export const MontonioServerEnvSchema = z.object({
|
||||
secretKey: z
|
||||
.string({
|
||||
error: `Please provide the variable MONTONIO_SECRET_KEY`,
|
||||
})
|
||||
.min(1),
|
||||
apiUrl: z
|
||||
.string({
|
||||
error: `Please provide the variable MONTONIO_API_URL`,
|
||||
})
|
||||
.min(1),
|
||||
});
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
import jwt from 'jsonwebtoken';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import { MontonioClientEnvSchema } from '../schema/montonio-client-env.schema';
|
||||
import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema';
|
||||
|
||||
const clientEnv = () => MontonioClientEnvSchema.parse({
|
||||
accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY,
|
||||
});
|
||||
const clientEnv = () =>
|
||||
MontonioClientEnvSchema.parse({
|
||||
accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY,
|
||||
});
|
||||
|
||||
const serverEnv = () => MontonioServerEnvSchema.parse({
|
||||
apiUrl: process.env.MONTONIO_API_URL,
|
||||
secretKey: process.env.MONTONIO_SECRET_KEY,
|
||||
});
|
||||
const serverEnv = () =>
|
||||
MontonioServerEnvSchema.parse({
|
||||
apiUrl: process.env.MONTONIO_API_URL,
|
||||
secretKey: process.env.MONTONIO_SECRET_KEY,
|
||||
});
|
||||
|
||||
export class MontonioOrderHandlerService {
|
||||
public async getMontonioPaymentLink({
|
||||
@@ -45,23 +48,27 @@ export class MontonioOrderHandlerService {
|
||||
returnUrl,
|
||||
askAdditionalInfo: false,
|
||||
merchantReference,
|
||||
type: "one_time",
|
||||
type: 'one_time',
|
||||
};
|
||||
const token = jwt.sign(params, secretKey, {
|
||||
algorithm: "HS256",
|
||||
expiresIn: "10m",
|
||||
algorithm: 'HS256',
|
||||
expiresIn: '10m',
|
||||
});
|
||||
|
||||
try {
|
||||
const { data } = await axios.post(`${apiUrl}/api/payment-links`, { data: token });
|
||||
const { data } = await axios.post(`${apiUrl}/api/payment-links`, {
|
||||
data: token,
|
||||
});
|
||||
return data.url;
|
||||
} catch (error) {
|
||||
if (error instanceof AxiosError) {
|
||||
console.error(error.response?.data);
|
||||
}
|
||||
console.error(`Failed to create payment link, params=${JSON.stringify(params)}`, error);
|
||||
throw new Error("Failed to create payment link");
|
||||
console.error(
|
||||
`Failed to create payment link, params=${JSON.stringify(params)}`,
|
||||
error,
|
||||
);
|
||||
throw new Error('Failed to create payment link');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import type { BillingWebhookHandlerService, IHandleWebhookEventParams } from '@kit/billing';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import type {
|
||||
BillingWebhookHandlerService,
|
||||
IHandleWebhookEventParams,
|
||||
} from '@kit/billing';
|
||||
import { getLogger } from '@kit/shared/logger';
|
||||
import { Database, Enums } from '@kit/supabase/database';
|
||||
import jwt from 'jsonwebtoken';
|
||||
|
||||
import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema';
|
||||
|
||||
type UpsertOrderParams =
|
||||
@@ -10,20 +15,26 @@ type UpsertOrderParams =
|
||||
type BillingProvider = Enums<{ schema: 'medreport' }, 'billing_provider'>;
|
||||
|
||||
interface MontonioOrderToken {
|
||||
uuid: string;
|
||||
accessKey: string;
|
||||
merchantReference: string;
|
||||
merchantReferenceDisplay: string;
|
||||
paymentStatus: 'PAID' | 'FAILED' | 'CANCELLED' | 'PENDING' | 'EXPIRED' | 'REFUNDED';
|
||||
paymentMethod: string;
|
||||
grandTotal: number;
|
||||
currency: string;
|
||||
senderIban?: string;
|
||||
senderName?: string;
|
||||
paymentProviderName?: string;
|
||||
paymentLinkUuid: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
uuid: string;
|
||||
accessKey: string;
|
||||
merchantReference: string;
|
||||
merchantReferenceDisplay: string;
|
||||
paymentStatus:
|
||||
| 'PAID'
|
||||
| 'FAILED'
|
||||
| 'CANCELLED'
|
||||
| 'PENDING'
|
||||
| 'EXPIRED'
|
||||
| 'REFUNDED';
|
||||
paymentMethod: string;
|
||||
grandTotal: number;
|
||||
currency: string;
|
||||
senderIban?: string;
|
||||
senderName?: string;
|
||||
paymentProviderName?: string;
|
||||
paymentLinkUuid: string;
|
||||
iat: number;
|
||||
exp: number;
|
||||
}
|
||||
|
||||
const { secretKey } = MontonioServerEnvSchema.parse({
|
||||
@@ -39,22 +50,25 @@ export class MontonioWebhookHandlerService
|
||||
|
||||
async verifyWebhookSignature(request: Request) {
|
||||
const logger = await getLogger();
|
||||
|
||||
|
||||
let token: string;
|
||||
try {
|
||||
const url = new URL(request.url);
|
||||
const searchParams = url.searchParams;
|
||||
console.info("searchParams", searchParams, url);
|
||||
console.info('searchParams', searchParams, url);
|
||||
const tokenParam = searchParams.get('order-token') as string | null;
|
||||
if (!tokenParam) {
|
||||
throw new Error('Missing order-token');
|
||||
}
|
||||
token = tokenParam;
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
error,
|
||||
name: this.namespace,
|
||||
}, `Failed to parse Montonio webhook request`);
|
||||
logger.error(
|
||||
{
|
||||
error,
|
||||
name: this.namespace,
|
||||
},
|
||||
`Failed to parse Montonio webhook request`,
|
||||
);
|
||||
throw new Error('Invalid request');
|
||||
}
|
||||
|
||||
@@ -64,24 +78,30 @@ export class MontonioWebhookHandlerService
|
||||
});
|
||||
return decoded as MontonioOrderToken;
|
||||
} catch (error) {
|
||||
logger.error({
|
||||
error,
|
||||
name: this.namespace,
|
||||
}, `Failed to verify Montonio webhook signature`);
|
||||
logger.error(
|
||||
{
|
||||
error,
|
||||
name: this.namespace,
|
||||
},
|
||||
`Failed to verify Montonio webhook signature`,
|
||||
);
|
||||
throw new Error('Invalid signature');
|
||||
}
|
||||
}
|
||||
|
||||
async handleWebhookEvent(
|
||||
event: MontonioOrderToken,
|
||||
params: IHandleWebhookEventParams
|
||||
params: IHandleWebhookEventParams,
|
||||
) {
|
||||
const logger = await getLogger();
|
||||
|
||||
logger.info({
|
||||
name: this.namespace,
|
||||
event,
|
||||
}, `Received Montonio webhook event`);
|
||||
logger.info(
|
||||
{
|
||||
name: this.namespace,
|
||||
event,
|
||||
},
|
||||
`Received Montonio webhook event`,
|
||||
);
|
||||
|
||||
if (event.paymentStatus === 'PAID') {
|
||||
const [accountId] = event.merchantReferenceDisplay.split(':');
|
||||
@@ -101,11 +121,13 @@ export class MontonioWebhookHandlerService
|
||||
return params.onCheckoutSessionCompleted(order);
|
||||
}
|
||||
|
||||
if (event.paymentStatus === 'FAILED' || event.paymentStatus === 'CANCELLED') {
|
||||
if (
|
||||
event.paymentStatus === 'FAILED' ||
|
||||
event.paymentStatus === 'CANCELLED'
|
||||
) {
|
||||
return params.onPaymentFailed(event.uuid);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
This package is responsible for handling all billing related operations using Stripe.
|
||||
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe).
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe).
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,12 +4,9 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"start": "docker run --rm -it --name=stripe -v ~/.config/stripe:/root/.config/stripe stripe/stripe-cli:latest listen --forward-to http://host.docker.internal:3000/api/billing/webhook"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./components": "./src/components/index.ts"
|
||||
@@ -21,8 +18,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/billing": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# CMS - @kit/cms
|
||||
|
||||
CMS abstraction layer for the Makerkit framework.
|
||||
CMS abstraction layer for the Makerkit framework.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,19 +4,14 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/cms-types": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/keystatic": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/wordpress": "workspace:*",
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
Implementation of the CMS layer using the Keystatic library.
|
||||
|
||||
Please refer to the [Documentation](https://makerkit.dev/docs/next-supabase-turbo/content/keystatic).
|
||||
Please refer to the [Documentation](https://makerkit.dev/docs/next-supabase-turbo/content/keystatic).
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,11 +4,8 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./renderer": "./src/content-renderer.tsx",
|
||||
@@ -22,8 +19,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/cms-types": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@types/node": "^22.15.18",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,17 +4,12 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*"
|
||||
},
|
||||
"typesVersions": {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# CMS/Wordpress - @kit/wordpress
|
||||
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/content/wordpress).
|
||||
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/content/wordpress).
|
||||
|
||||
@@ -31,18 +31,18 @@ services:
|
||||
- WORDPRESS_DB_NAME=wordpress
|
||||
- WORDPRESS_DEBUG=1
|
||||
- WORDPRESS_CONFIG_EXTRA = |
|
||||
define('FS_METHOD', 'direct');
|
||||
/** disable wp core auto update */
|
||||
define('WP_AUTO_UPDATE_CORE', false);
|
||||
|
||||
/** local environment settings */
|
||||
define('WP_CACHE', false);
|
||||
define('ENVIRONMENT', 'local');
|
||||
|
||||
/** force site home url */
|
||||
if(!defined('WP_HOME')) {
|
||||
define('WP_HOME', 'http://localhost');
|
||||
define('WP_SITEURL', WP_HOME);
|
||||
}
|
||||
define('FS_METHOD', 'direct');
|
||||
/** disable wp core auto update */
|
||||
define('WP_AUTO_UPDATE_CORE', false);
|
||||
|
||||
/** local environment settings */
|
||||
define('WP_CACHE', false);
|
||||
define('ENVIRONMENT', 'local');
|
||||
|
||||
/** force site home url */
|
||||
if(!defined('WP_HOME')) {
|
||||
define('WP_HOME', 'http://localhost');
|
||||
define('WP_SITEURL', WP_HOME);
|
||||
}
|
||||
volumes:
|
||||
db_data:
|
||||
db_data:
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,20 +4,15 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"start": "docker compose up"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./renderer": "./src/content-renderer.tsx"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/cms-types": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@types/node": "^22.15.18",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
This package is responsible for handling webhooks from database changes.
|
||||
|
||||
For example:
|
||||
|
||||
1. when an account is deleted, we handle the cleanup of all related data in the third-party services.
|
||||
2. when a user is invited, we send an email to the user.
|
||||
3. when an account member is added, we update the subscription in the third-party services
|
||||
@@ -21,4 +22,4 @@ WEBHOOK_SENDER_PROVIDER=svix
|
||||
|
||||
For example, you can add [https://docs.svix.com/quickstart]](Swix) as a webhook sender provider that receives webhooks from the database changes and forwards them to your application.
|
||||
|
||||
Svix is not implemented yet.
|
||||
Svix is not implemented yet.
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,19 +4,14 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/billing": "workspace:*",
|
||||
"@kit/billing-gateway": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/stripe": "workspace:*",
|
||||
"@kit/montonio": "workspace:*",
|
||||
|
||||
@@ -6,7 +6,7 @@ const webhooksSecret = z
|
||||
.string({
|
||||
error: `Provide the variable SUPABASE_DB_WEBHOOK_SECRET. This is used to authenticate the webhook event from Supabase.`,
|
||||
})
|
||||
.describe(`The secret used to verify the webhook signature`,)
|
||||
.describe(`The secret used to verify the webhook signature`)
|
||||
.min(1)
|
||||
.parse(process.env.SUPABASE_DB_WEBHOOK_SECRET);
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,11 +4,8 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
@@ -16,9 +13,7 @@
|
||||
"@react-email/components": "0.0.41"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/i18n": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*"
|
||||
},
|
||||
"typesVersions": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { TFunction } from "i18next";
|
||||
import { Text } from "@react-email/components";
|
||||
import { EmailFooter } from "./footer";
|
||||
import { Text } from '@react-email/components';
|
||||
import { TFunction } from 'i18next';
|
||||
|
||||
import { EmailFooter } from './footer';
|
||||
|
||||
export default function CommonFooter({ t }: { t: TFunction }) {
|
||||
const namespace = 'common';
|
||||
@@ -15,8 +16,12 @@ export default function CommonFooter({ t }: { t: TFunction }) {
|
||||
return (
|
||||
<EmailFooter>
|
||||
{lines.map((line, index) => (
|
||||
<Text key={index} className="text-[16px] leading-[24px] text-[#242424]" dangerouslySetInnerHTML={{ __html: line }} />
|
||||
<Text
|
||||
key={index}
|
||||
className="text-[16px] leading-[24px] text-[#242424]"
|
||||
dangerouslySetInnerHTML={{ __html: line }}
|
||||
/>
|
||||
))}
|
||||
</EmailFooter>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export async function renderPatientFirstResultsReceivedEmail({
|
||||
</Text>
|
||||
<Text>{t(`${namespace}:p2`)}</Text>
|
||||
<Text>{t(`${namespace}:p3`)}</Text>
|
||||
<Text>{t(`${namespace}:p4`)}</Text>
|
||||
<Text>{t(`${namespace}:p4`)}</Text>
|
||||
<CommonFooter t={t} />
|
||||
</EmailContent>
|
||||
</EmailWrapper>
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
"paragraph2": "We're sorry to see you go. Please note that this action is irreversible, and we'll make sure to delete all of your data from our systems.",
|
||||
"paragraph3": "We thank you again for using {{productName}}.",
|
||||
"paragraph4": "The {{productName}} Team"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
"lines3": "Customer service: <a href=\"tel:+37258871517\">+372 5887 1517</a>",
|
||||
"lines4": "<a href=\"https://www.medreport.ee\">www.medreport.ee</a>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
"contactPerson": "Contact Person:",
|
||||
"email": "Email:",
|
||||
"phone": "Phone:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "Doctor's summary has arrived",
|
||||
"previewText": "The doctor has prepared a summary of the test results.",
|
||||
"p1": "The doctor's summary has arrived:",
|
||||
"p2": "It is recommended to have a comprehensive health check-up regularly, at least once a year, if you wish to maintain an active and fulfilling lifestyle.",
|
||||
"p3": "MedReport makes it easy, convenient, and fast to view health data in one place and order health check-ups.",
|
||||
"p4": "SYNLAB customer support phone: 17123"
|
||||
"subject": "Doctor's summary has arrived",
|
||||
"previewText": "The doctor has prepared a summary of the test results.",
|
||||
"p1": "The doctor's summary has arrived:",
|
||||
"p2": "It is recommended to have a comprehensive health check-up regularly, at least once a year, if you wish to maintain an active and fulfilling lifestyle.",
|
||||
"p3": "MedReport makes it easy, convenient, and fast to view health data in one place and order health check-ups.",
|
||||
"p4": "SYNLAB customer support phone: 17123"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
"joinTeam": "Join {{teamName}}",
|
||||
"copyPasteLink": "or copy and paste this URL into your browser:",
|
||||
"invitationIntendedFor": "This invitation is intended for {{invitedUserEmail}}."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"subject": "The referral has been sent to the laboratory. Please go to give samples.",
|
||||
"heading": "Thank you for your order!",
|
||||
"previewText": "The referral for tests has been sent to the laboratory.",
|
||||
"p1": "The referral for tests has been sent to the laboratory digitally. Please go to give samples: {{partnerLocation}}.",
|
||||
"p2": "If you are unable to go to the selected location to give samples, you may visit any other sampling point convenient for you - <a href='https://medreport.ee/et/verevotupunktid'>see locations and opening hours</a>.",
|
||||
"p3": "It is recommended to give samples preferably in the morning (before 12:00) and on an empty stomach without drinking or eating (you may drink water).",
|
||||
"p4": "At the sampling point, please choose in the queue system: under <strong>referrals</strong> select <strong>specialist referral</strong>.",
|
||||
"p5": "If you have any additional questions, please do not hesitate to contact us.",
|
||||
"p6": "SYNLAB customer support phone: 17123",
|
||||
"p1Urine": "The tests include a <strong>urine test</strong>. For the urine test, please collect the first morning urine.",
|
||||
"p2Urine": "You can buy a sample container at the pharmacy and bring the sample with you (procedure performed at home), or ask for one at the sampling point (procedure performed in the point’s restroom)."
|
||||
"subject": "The referral has been sent to the laboratory. Please go to give samples.",
|
||||
"heading": "Thank you for your order!",
|
||||
"previewText": "The referral for tests has been sent to the laboratory.",
|
||||
"p1": "The referral for tests has been sent to the laboratory digitally. Please go to give samples: {{partnerLocation}}.",
|
||||
"p2": "If you are unable to go to the selected location to give samples, you may visit any other sampling point convenient for you - <a href='https://medreport.ee/et/verevotupunktid'>see locations and opening hours</a>.",
|
||||
"p3": "It is recommended to give samples preferably in the morning (before 12:00) and on an empty stomach without drinking or eating (you may drink water).",
|
||||
"p4": "At the sampling point, please choose in the queue system: under <strong>referrals</strong> select <strong>specialist referral</strong>.",
|
||||
"p5": "If you have any additional questions, please do not hesitate to contact us.",
|
||||
"p6": "SYNLAB customer support phone: 17123",
|
||||
"p1Urine": "The tests include a <strong>urine test</strong>. For the urine test, please collect the first morning urine.",
|
||||
"p2Urine": "You can buy a sample container at the pharmacy and bring the sample with you (procedure performed at home), or ask for one at the sampling point (procedure performed in the point’s restroom)."
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "The first ordered test results have arrived",
|
||||
"previewText": "The first test results have arrived.",
|
||||
"p1": "The first test results have arrived:",
|
||||
"p2": "We will send the next notification once all test results have been received in the system.",
|
||||
"p3": "If you have any additional questions, please feel free to contact us.",
|
||||
"p4": "SYNLAB customer support phone: 17123"
|
||||
"subject": "The first ordered test results have arrived",
|
||||
"previewText": "The first test results have arrived.",
|
||||
"p1": "The first test results have arrived:",
|
||||
"p2": "We will send the next notification once all test results have been received in the system.",
|
||||
"p3": "If you have any additional questions, please feel free to contact us.",
|
||||
"p4": "SYNLAB customer support phone: 17123"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"subject": "All ordered test results have arrived. Awaiting doctor's summary.",
|
||||
"previewText": "All test results have arrived.",
|
||||
"p1": "All test results have arrived:",
|
||||
"p2": "We will send the next notification once the doctor's summary has been prepared.",
|
||||
"p3": "SYNLAB customer support phone: 17123"
|
||||
"subject": "All ordered test results have arrived. Awaiting doctor's summary.",
|
||||
"previewText": "All test results have arrived.",
|
||||
"p1": "All test results have arrived:",
|
||||
"p2": "We will send the next notification once the doctor's summary has been prepared.",
|
||||
"p3": "SYNLAB customer support phone: 17123"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"subject": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"previewText": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"heading": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"hello": "Hello {{personName}},",
|
||||
"lines1": "The order for {{analysisPackageName}} analysis package has been sent to the lab. Please go to the lab to collect the sample: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>If you are unable to go to the lab to collect the sample, you can go to any other suitable collection point - <a href=\"https://medreport.ee/et/verevotupunktid\">view locations and opening hours</a>.</i>",
|
||||
"lines3": "It is recommended to collect the sample in the morning (before 12:00) and not to eat or drink (water can be drunk).",
|
||||
"lines4": "At the collection point, select the order from the queue: the order from the doctor.",
|
||||
"lines5": "If you have any questions, please contact us.",
|
||||
"lines6": "SYNLAB customer service phone: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
"subject": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"previewText": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"heading": "Your Medreport order has been placed - {{analysisPackageName}}",
|
||||
"hello": "Hello {{personName}},",
|
||||
"lines1": "The order for {{analysisPackageName}} analysis package has been sent to the lab. Please go to the lab to collect the sample: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>If you are unable to go to the lab to collect the sample, you can go to any other suitable collection point - <a href=\"https://medreport.ee/et/verevotupunktid\">view locations and opening hours</a>.</i>",
|
||||
"lines3": "It is recommended to collect the sample in the morning (before 12:00) and not to eat or drink (water can be drunk).",
|
||||
"lines4": "At the collection point, select the order from the queue: the order from the doctor.",
|
||||
"lines5": "If you have any questions, please contact us.",
|
||||
"lines6": "SYNLAB customer service phone: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"previewText": "Kõik analüüside vastused on saabunud",
|
||||
"subject": "Patsiendi kõikide analüüside vastused on saabunud",
|
||||
"openOrdersHeading": "Vaata tulemusi ja kirjuta kokkuvõte:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
"previewText": "Kõik analüüside vastused on saabunud",
|
||||
"subject": "Patsiendi kõikide analüüside vastused on saabunud",
|
||||
"openOrdersHeading": "Vaata tulemusi ja kirjuta kokkuvõte:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
},
|
||||
"helloName": "Tere, {{name}}",
|
||||
"hello": "Tere"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "Arsti kokkuvõte on saabunud",
|
||||
"previewText": "Arst on koostanud kokkuvõte analüüsitulemustele.",
|
||||
"p1": "Arsti kokkuvõte on saabunud:",
|
||||
"p2": "Põhjalikul terviseuuringul on soovituslik käia regulaarselt, aga vähemalt üks kord aastas, kui soovite säilitada aktiivset ja täisväärtuslikku elustiili.",
|
||||
"p3": "MedReport aitab lihtsalt, mugavalt ja kiirelt terviseandmeid ühest kohast vaadata ning tellida terviseuuringuid.",
|
||||
"p4": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
"subject": "Arsti kokkuvõte on saabunud",
|
||||
"previewText": "Arst on koostanud kokkuvõte analüüsitulemustele.",
|
||||
"p1": "Arsti kokkuvõte on saabunud:",
|
||||
"p2": "Põhjalikul terviseuuringul on soovituslik käia regulaarselt, aga vähemalt üks kord aastas, kui soovite säilitada aktiivset ja täisväärtuslikku elustiili.",
|
||||
"p3": "MedReport aitab lihtsalt, mugavalt ja kiirelt terviseandmeid ühest kohast vaadata ning tellida terviseuuringuid.",
|
||||
"p4": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "Saabusid esimesed analüüside vastused",
|
||||
"subject": "Uus töö - saabusid esimesed analüüside vastused",
|
||||
"resultsReceivedForOrders": "Patsiendile saabusid esimesed analüüside vastused.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
"previewText": "Saabusid esimesed analüüside vastused",
|
||||
"subject": "Uus töö - saabusid esimesed analüüside vastused",
|
||||
"resultsReceivedForOrders": "Patsiendile saabusid esimesed analüüside vastused.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Vaata tulemusi",
|
||||
"ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "Palun koosta kokkuvõte",
|
||||
"subject": "Palun koosta kokkuvõte",
|
||||
"resultsReceivedForOrders": "Palun vaata tulemused üle ja kirjuta kokkuvõte.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Töö {{nr}}",
|
||||
"ifLinksDisabled": "Kui lingid ei tööta, näed vabasid töid sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
"previewText": "Palun koosta kokkuvõte",
|
||||
"subject": "Palun koosta kokkuvõte",
|
||||
"resultsReceivedForOrders": "Palun vaata tulemused üle ja kirjuta kokkuvõte.",
|
||||
"openOrdersHeading": "Vaata siit:",
|
||||
"linkText": "Töö {{nr}}",
|
||||
"ifLinksDisabled": "Kui lingid ei tööta, näed vabasid töid sellelt aadressilt:",
|
||||
"hello": "Tere"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"subject": "Saatekiri on saadetud laborisse. Palun mine proove andma.",
|
||||
"heading": "Täname tellimuse eest!",
|
||||
"previewText": "Saatekiri uuringute tegemiseks on saadetud laborisse.",
|
||||
"p1": "Saatekiri uuringute tegemiseks on saadetud laborisse digitaalselt. Palun mine proove andma: {{partnerLocation}}.",
|
||||
"p2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - <a href='https://medreport.ee/et/verevotupunktid'>vaata asukohti ja lahtiolekuaegasid</a>.",
|
||||
"p3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).",
|
||||
"p4": "Proovivõtupunktis valige järjekorrasüsteemis: <strong>saatekirjad</strong> alt <strong>eriarsti saatekiri</strong>",
|
||||
"p5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"p6": "SYNLAB klienditoe telefon: 17123",
|
||||
"p1Urine": "Analüüsides on ette nähtud <strong>uriinianalüüs</strong>. Uriinianalüüsiks võta hommikune esmane uriin.",
|
||||
"p2Urine": "Proovitopsi võib soetada apteegist ja analüüsi kaasa võtta (teostada protseduur kodus) või küsida proovivõtupunktist (teostada protseduur proovipunkti wc-s)."
|
||||
}
|
||||
"subject": "Saatekiri on saadetud laborisse. Palun mine proove andma.",
|
||||
"heading": "Täname tellimuse eest!",
|
||||
"previewText": "Saatekiri uuringute tegemiseks on saadetud laborisse.",
|
||||
"p1": "Saatekiri uuringute tegemiseks on saadetud laborisse digitaalselt. Palun mine proove andma: {{partnerLocation}}.",
|
||||
"p2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - <a href='https://medreport.ee/et/verevotupunktid'>vaata asukohti ja lahtiolekuaegasid</a>.",
|
||||
"p3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).",
|
||||
"p4": "Proovivõtupunktis valige järjekorrasüsteemis: <strong>saatekirjad</strong> alt <strong>eriarsti saatekiri</strong>",
|
||||
"p5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"p6": "SYNLAB klienditoe telefon: 17123",
|
||||
"p1Urine": "Analüüsides on ette nähtud <strong>uriinianalüüs</strong>. Uriinianalüüsiks võta hommikune esmane uriin.",
|
||||
"p2Urine": "Proovitopsi võib soetada apteegist ja analüüsi kaasa võtta (teostada protseduur kodus) või küsida proovivõtupunktist (teostada protseduur proovipunkti wc-s)."
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "Saabusid tellitud uuringute esimesed tulemused",
|
||||
"previewText": "Esimesed uuringute tulemused on saabunud.",
|
||||
"p1": "Esimesed uuringute tulemused on saabunud:",
|
||||
"p2": "Saadame järgmise teavituse, kui kõik uuringute vastused on saabunud süsteemi.",
|
||||
"p3": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"p4": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
"subject": "Saabusid tellitud uuringute esimesed tulemused",
|
||||
"previewText": "Esimesed uuringute tulemused on saabunud.",
|
||||
"p1": "Esimesed uuringute tulemused on saabunud:",
|
||||
"p2": "Saadame järgmise teavituse, kui kõik uuringute vastused on saabunud süsteemi.",
|
||||
"p3": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"p4": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"subject": "Kõikide tellitud uuringute tulemused on saabunud. Ootab arsti kokkuvõtet.",
|
||||
"previewText": "Kõikide uuringute tulemused on saabunud.",
|
||||
"p1": "Kõikide uuringute tulemused on saabunud:",
|
||||
"p2": "Saadame järgmise teavituse kui arsti kokkuvõte on koostatud.",
|
||||
"p3": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
"subject": "Kõikide tellitud uuringute tulemused on saabunud. Ootab arsti kokkuvõtet.",
|
||||
"previewText": "Kõikide uuringute tulemused on saabunud.",
|
||||
"p1": "Kõikide uuringute tulemused on saabunud:",
|
||||
"p2": "Saadame järgmise teavituse kui arsti kokkuvõte on koostatud.",
|
||||
"p3": "SYNLAB klienditoe telefon: 17123"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"subject": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"previewText": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"heading": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"hello": "Tere {{personName}},",
|
||||
"lines1": "Saatekiri {{analysisPackageName}} analüüsi uuringuteks on saadetud laborisse digitaalselt. Palun mine proove andma: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - <a href=\"https://medreport.ee/et/verevotupunktid\">vaata asukohti ja lahtiolekuaegasid</a>.</i>",
|
||||
"lines3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).",
|
||||
"lines4": "Proovivõtupunktis valige järjekorrasüsteemis: <strong>saatekirjad</strong> alt <strong>eriarsti saatekiri</strong>.",
|
||||
"lines5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"lines6": "SYNLAB klienditoe telefon: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
"subject": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"previewText": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"heading": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}",
|
||||
"hello": "Tere {{personName}},",
|
||||
"lines1": "Saatekiri {{analysisPackageName}} analüüsi uuringuteks on saadetud laborisse digitaalselt. Palun mine proove andma: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - <a href=\"https://medreport.ee/et/verevotupunktid\">vaata asukohti ja lahtiolekuaegasid</a>.</i>",
|
||||
"lines3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).",
|
||||
"lines4": "Proovivõtupunktis valige järjekorrasüsteemis: <strong>saatekirjad</strong> alt <strong>eriarsti saatekiri</strong>.",
|
||||
"lines5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.",
|
||||
"lines6": "SYNLAB klienditoe telefon: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
"previewText": "All analysis results have been received",
|
||||
"subject": "All patient analysis results have been received",
|
||||
"openOrdersHeading": "Review the results and prepare a summary:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello"
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
"lines3": "Служба поддержки: <a href=\"tel:+37258871517\">+372 5887 1517</a>",
|
||||
"lines4": "<a href=\"https://www.medreport.ee\">www.medreport.ee</a>"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
"contactPerson": "Контактное лицо:",
|
||||
"email": "Электронная почта:",
|
||||
"phone": "Телефон:"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "Заключение врача готово",
|
||||
"previewText": "Врач подготовил заключение по результатам анализов.",
|
||||
"p1": "Заключение врача готово:",
|
||||
"p2": "Рекомендуется проходить комплексное обследование регулярно, но как минимум один раз в год, если вы хотите сохранить активный и полноценный образ жизни.",
|
||||
"p3": "MedReport позволяет легко, удобно и быстро просматривать медицинские данные в одном месте и заказывать обследования.",
|
||||
"p4": "Телефон службы поддержки SYNLAB: 17123"
|
||||
}
|
||||
"subject": "Заключение врача готово",
|
||||
"previewText": "Врач подготовил заключение по результатам анализов.",
|
||||
"p1": "Заключение врача готово:",
|
||||
"p2": "Рекомендуется проходить комплексное обследование регулярно, но как минимум один раз в год, если вы хотите сохранить активный и полноценный образ жизни.",
|
||||
"p3": "MedReport позволяет легко, удобно и быстро просматривать медицинские данные в одном месте и заказывать обследования.",
|
||||
"p4": "Телефон службы поддержки SYNLAB: 17123"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
"previewText": "First analysis responses received",
|
||||
"subject": "New job - first analysis responses received",
|
||||
"resultsReceivedForOrders": "New job available to claim",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "See results",
|
||||
"ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
"previewText": "New jobs available",
|
||||
"subject": "Please write a summary",
|
||||
"resultsReceivedForOrders": "Please review the results and write a summary.",
|
||||
"openOrdersHeading": "See here:",
|
||||
"linkText": "Open job {{nr}}",
|
||||
"ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.",
|
||||
"hello": "Hello,"
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"subject": "Направление отправлено в лабораторию. Пожалуйста, сдайте анализы.",
|
||||
"heading": "Спасибо за заказ!",
|
||||
"previewText": "Направление на обследование отправлено в лабораторию.",
|
||||
"p1": "Направление на обследование было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: {{partnerLocation}}.",
|
||||
"p2": "Если у вас нет возможности прийти в выбранный пункт сдачи анализов, вы можете обратиться в любой удобный для вас пункт – <a href='https://medreport.ee/et/verevotupunktid'>посмотреть адреса и часы работы</a>.",
|
||||
"p3": "Рекомендуется сдавать анализы утром (до 12:00) натощак, без еды и напитков (разрешается пить воду).",
|
||||
"p4": "В пункте сдачи анализов выберите в системе очереди: в разделе <strong>направления</strong> → <strong>направление от специалиста</strong>.",
|
||||
"p5": "Если у вас возникли дополнительные вопросы, пожалуйста, свяжитесь с нами.",
|
||||
"p6": "Телефон службы поддержки SYNLAB: 17123",
|
||||
"p1Urine": "В обследование входит <strong>анализ мочи</strong>. Для анализа необходимо собрать первую утреннюю мочу.",
|
||||
"p2Urine": "Контейнер можно приобрести в аптеке и принести образец с собой (процедура проводится дома) или взять контейнер в пункте сдачи (процедура проводится в туалете пункта)."
|
||||
"subject": "Направление отправлено в лабораторию. Пожалуйста, сдайте анализы.",
|
||||
"heading": "Спасибо за заказ!",
|
||||
"previewText": "Направление на обследование отправлено в лабораторию.",
|
||||
"p1": "Направление на обследование было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: {{partnerLocation}}.",
|
||||
"p2": "Если у вас нет возможности прийти в выбранный пункт сдачи анализов, вы можете обратиться в любой удобный для вас пункт – <a href='https://medreport.ee/et/verevotupunktid'>посмотреть адреса и часы работы</a>.",
|
||||
"p3": "Рекомендуется сдавать анализы утром (до 12:00) натощак, без еды и напитков (разрешается пить воду).",
|
||||
"p4": "В пункте сдачи анализов выберите в системе очереди: в разделе <strong>направления</strong> → <strong>направление от специалиста</strong>.",
|
||||
"p5": "Если у вас возникли дополнительные вопросы, пожалуйста, свяжитесь с нами.",
|
||||
"p6": "Телефон службы поддержки SYNLAB: 17123",
|
||||
"p1Urine": "В обследование входит <strong>анализ мочи</strong>. Для анализа необходимо собрать первую утреннюю мочу.",
|
||||
"p2Urine": "Контейнер можно приобрести в аптеке и принести образец с собой (процедура проводится дома) или взять контейнер в пункте сдачи (процедура проводится в туалете пункта)."
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"subject": "Поступили первые результаты заказанных исследований",
|
||||
"previewText": "Первые результаты исследований поступили.",
|
||||
"p1": "Первые результаты исследований поступили:",
|
||||
"p2": "Мы отправим следующее уведомление, когда все результаты исследований будут получены в системе.",
|
||||
"p3": "Если у вас возникнут дополнительные вопросы, пожалуйста, свяжитесь с нами.",
|
||||
"p4": "Телефон службы поддержки SYNLAB: 17123"
|
||||
"subject": "Поступили первые результаты заказанных исследований",
|
||||
"previewText": "Первые результаты исследований поступили.",
|
||||
"p1": "Первые результаты исследований поступили:",
|
||||
"p2": "Мы отправим следующее уведомление, когда все результаты исследований будут получены в системе.",
|
||||
"p3": "Если у вас возникнут дополнительные вопросы, пожалуйста, свяжитесь с нами.",
|
||||
"p4": "Телефон службы поддержки SYNLAB: 17123"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"subject": "Все заказанные результаты исследований поступили. Ожидается заключение врача.",
|
||||
"previewText": "Все результаты исследований поступили.",
|
||||
"p1": "Все результаты исследований поступили:",
|
||||
"p2": "Мы отправим следующее уведомление, когда заключение врача будет подготовлено.",
|
||||
"p3": "Телефон службы поддержки SYNLAB: 17123"
|
||||
}
|
||||
"subject": "Все заказанные результаты исследований поступили. Ожидается заключение врача.",
|
||||
"previewText": "Все результаты исследований поступили.",
|
||||
"p1": "Все результаты исследований поступили:",
|
||||
"p2": "Мы отправим следующее уведомление, когда заключение врача будет подготовлено.",
|
||||
"p3": "Телефон службы поддержки SYNLAB: 17123"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"subject": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"previewText": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"heading": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"hello": "Здравствуйте, {{personName}},",
|
||||
"lines1": "Направление на исследование {{analysisPackageName}} было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>Если вы не можете посетить выбранный пункт сдачи анализов, вы можете обратиться в удобный для вас пункт - <a href=\"https://medreport.ee/et/verevotupunktid\">посмотреть адреса и часы работы</a>.</i>",
|
||||
"lines3": "Рекомендуется сдавать анализы утром (до 12:00) натощак (можно пить воду).",
|
||||
"lines4": "В пункте сдачи анализов выберите в системе очереди: <strong>направления</strong> -> <strong>направление от специалиста</strong>.",
|
||||
"lines5": "Если у вас возникнут дополнительные вопросы, смело свяжитесь с нами.",
|
||||
"lines6": "Телефон службы поддержки SYNLAB: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
"subject": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"previewText": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"heading": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}",
|
||||
"hello": "Здравствуйте, {{personName}},",
|
||||
"lines1": "Направление на исследование {{analysisPackageName}} было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: Synlab - {{partnerLocationName}}",
|
||||
"lines2": "<i>Если вы не можете посетить выбранный пункт сдачи анализов, вы можете обратиться в удобный для вас пункт - <a href=\"https://medreport.ee/et/verevotupunktid\">посмотреть адреса и часы работы</a>.</i>",
|
||||
"lines3": "Рекомендуется сдавать анализы утром (до 12:00) натощак (можно пить воду).",
|
||||
"lines4": "В пункте сдачи анализов выберите в системе очереди: <strong>направления</strong> -> <strong>направление от специалиста</strong>.",
|
||||
"lines5": "Если у вас возникнут дополнительные вопросы, смело свяжитесь с нами.",
|
||||
"lines6": "Телефон службы поддержки SYNLAB: <a href=\"tel:+37217123\">17123</a>"
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,8 +4,6 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"exports": {
|
||||
@@ -24,12 +22,10 @@
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@kit/billing-gateway": "workspace:*",
|
||||
"@kit/email-templates": "workspace:*",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/mailers": "workspace:*",
|
||||
"@kit/monitoring": "workspace:*",
|
||||
"@kit/next": "workspace:*",
|
||||
"@kit/otp": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
@@ -46,7 +42,6 @@
|
||||
"react-dom": "19.1.0",
|
||||
"sonner": "^2.0.3"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
|
||||
@@ -112,7 +112,7 @@ export function AccountSelector({
|
||||
role="combobox"
|
||||
aria-expanded={open}
|
||||
className={cn(
|
||||
'dark:shadow-primary/10 group w-full min-w-0 px-4 py-2 h-10 border-1 lg:w-auto lg:max-w-fit',
|
||||
'dark:shadow-primary/10 group h-10 w-full min-w-0 border-1 px-4 py-2 lg:w-auto lg:max-w-fit',
|
||||
{
|
||||
'justify-start': !collapsed,
|
||||
'm-auto justify-center px-4 lg:w-full': collapsed,
|
||||
@@ -124,7 +124,7 @@ export function AccountSelector({
|
||||
condition={selected}
|
||||
fallback={
|
||||
<span
|
||||
className={cn('flex max-w-full items-center size-4', {
|
||||
className={cn('flex size-4 max-w-full items-center', {
|
||||
'justify-center gap-x-0': collapsed,
|
||||
'gap-x-4': !collapsed,
|
||||
})}
|
||||
@@ -148,7 +148,7 @@ export function AccountSelector({
|
||||
'gap-x-4': !collapsed,
|
||||
})}
|
||||
>
|
||||
<Avatar className={'rounded-md size-6'}>
|
||||
<Avatar className={'size-6 rounded-md'}>
|
||||
<AvatarImage src={account.image ?? undefined} />
|
||||
|
||||
<AvatarFallback
|
||||
@@ -233,7 +233,7 @@ export function AccountSelector({
|
||||
}}
|
||||
>
|
||||
<div className={'flex items-center'}>
|
||||
<Avatar className={'rounded-xs mr-2 h-6 w-6'}>
|
||||
<Avatar className={'mr-2 h-6 w-6 rounded-xs'}>
|
||||
<AvatarImage src={account.image ?? undefined} />
|
||||
|
||||
<AvatarFallback
|
||||
@@ -297,7 +297,7 @@ export function AccountSelector({
|
||||
|
||||
function UserAvatar(props: { pictureUrl?: string }) {
|
||||
return (
|
||||
<Avatar className={'rounded-md size-6'}>
|
||||
<Avatar className={'size-6 rounded-md'}>
|
||||
<AvatarImage src={props.pictureUrl} />
|
||||
</Avatar>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './user-workspace-context';
|
||||
export * from './personal-account-settings/mfa/multi-factor-auth-list'
|
||||
export * from './personal-account-settings/mfa/multi-factor-auth-setup-dialog'
|
||||
export * from './personal-account-settings/mfa/multi-factor-auth-list';
|
||||
export * from './personal-account-settings/mfa/multi-factor-auth-setup-dialog';
|
||||
|
||||
@@ -81,7 +81,8 @@ export function PersonalAccountDropdown({
|
||||
|
||||
const { name, last_name } = personalAccountData ?? {};
|
||||
const firstNameLabel = toTitleCase(name) ?? '-';
|
||||
const fullNameLabel = name && last_name ? toTitleCase(`${name} ${last_name}`) : '-';
|
||||
const fullNameLabel =
|
||||
name && last_name ? toTitleCase(`${name} ${last_name}`) : '-';
|
||||
|
||||
const hasTotpFactor = useMemo(() => {
|
||||
const factors = user?.factors ?? [];
|
||||
|
||||
@@ -347,9 +347,7 @@ function FactorQrCode({
|
||||
<QrImage src={form.getValues('qrCode')} />
|
||||
</div>
|
||||
|
||||
<p className='text-center text-sm'>
|
||||
{form.getValues('totpSecret')}
|
||||
</p>
|
||||
<p className="text-center text-sm">{form.getValues('totpSecret')}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SupabaseClient } from '@supabase/supabase-js';
|
||||
|
||||
import { Database } from '@kit/supabase/database';
|
||||
|
||||
import PersonalCode from '~/lib/utils';
|
||||
|
||||
import { AccountWithParams } from '../types/accounts';
|
||||
@@ -11,7 +12,7 @@ import { AccountWithParams } from '../types/accounts';
|
||||
* @param {SupabaseClient<Database>} client - The Supabase client instance.
|
||||
*/
|
||||
class AccountsApi {
|
||||
constructor(private readonly client: SupabaseClient<Database>) { }
|
||||
constructor(private readonly client: SupabaseClient<Database>) {}
|
||||
|
||||
/**
|
||||
* @name getAccount
|
||||
|
||||
@@ -11,13 +11,13 @@ export enum ApplicationRoleEnum {
|
||||
export type AccountWithParams =
|
||||
Database['medreport']['Tables']['accounts']['Row'] & {
|
||||
accountParams:
|
||||
| (Pick<
|
||||
Database['medreport']['Tables']['account_params']['Row'],
|
||||
'weight' | 'height'
|
||||
> & {
|
||||
isSmoker:
|
||||
| Database['medreport']['Tables']['account_params']['Row']['is_smoker']
|
||||
| (Pick<
|
||||
Database['medreport']['Tables']['account_params']['Row'],
|
||||
'weight' | 'height'
|
||||
> & {
|
||||
isSmoker:
|
||||
| Database['medreport']['Tables']['account_params']['Row']['is_smoker']
|
||||
| null;
|
||||
})
|
||||
| null;
|
||||
})
|
||||
| null;
|
||||
};
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,16 +4,11 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"devDependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/next": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
|
||||
@@ -48,7 +48,7 @@ export function AdminCreateUserDialog(props: React.PropsWithChildren) {
|
||||
email: '',
|
||||
password: '',
|
||||
emailConfirm: false,
|
||||
personalCode: ''
|
||||
personalCode: '',
|
||||
},
|
||||
mode: 'onBlur',
|
||||
});
|
||||
@@ -163,7 +163,7 @@ export function AdminCreateUserDialog(props: React.PropsWithChildren) {
|
||||
<FormField
|
||||
name={'emailConfirm'}
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-start space-x-3 space-y-0 rounded-md border p-4">
|
||||
<FormItem className="flex flex-row items-start space-y-0 space-x-3 rounded-md border p-4">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value}
|
||||
|
||||
@@ -148,12 +148,17 @@ export const deleteAccountAction = adminAction(
|
||||
}
|
||||
const medusa = getAdminSdk();
|
||||
const { customer_groups } = await medusa.admin.customerGroup.list();
|
||||
const customerGroup = customer_groups.find(({ name }) => name === customerGroupName);
|
||||
const customerGroup = customer_groups.find(
|
||||
({ name }) => name === customerGroupName,
|
||||
);
|
||||
if (customerGroup) {
|
||||
try {
|
||||
await medusa.admin.customerGroup.delete(customerGroup.id);
|
||||
} catch (e) {
|
||||
logger.error({ accountId }, `Error deleting Medusa customer group for company ${customerGroupName}`);
|
||||
logger.error(
|
||||
{ accountId },
|
||||
`Error deleting Medusa customer group for company ${customerGroupName}`,
|
||||
);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -288,22 +293,29 @@ export const createCompanyAccountAction = enhanceAction(
|
||||
|
||||
logger.info(ctx, `Creating Medusa customer group`);
|
||||
const medusa = getAdminSdk();
|
||||
const { customer_groups: existingCustomerGroups } = await medusa.admin.customerGroup.list();
|
||||
const isExisting = existingCustomerGroups.find((group) => group.name === name);
|
||||
const { customer_groups: existingCustomerGroups } =
|
||||
await medusa.admin.customerGroup.list();
|
||||
const isExisting = existingCustomerGroups.find(
|
||||
(group) => group.name === name,
|
||||
);
|
||||
if (isExisting) {
|
||||
logger.info(ctx, `Customer group already exists`);
|
||||
} else {
|
||||
logger.info(ctx, `Creating Medusa customer group`);
|
||||
const { data: account } = await client
|
||||
.schema('medreport').from('accounts')
|
||||
.schema('medreport')
|
||||
.from('accounts')
|
||||
.select('medusa_account_id')
|
||||
.eq('personal_code', ownerPersonalCode)
|
||||
.single().throwOnError();
|
||||
.single()
|
||||
.throwOnError();
|
||||
const medusaAccountId = account.medusa_account_id;
|
||||
if (!medusaAccountId) {
|
||||
logger.error(ctx, `User has no Medusa account ID`);
|
||||
} else {
|
||||
const { customer_group: { id: customerGroupId } } = await medusa.admin.customerGroup.create({ name });
|
||||
const {
|
||||
customer_group: { id: customerGroupId },
|
||||
} = await medusa.admin.customerGroup.create({ name });
|
||||
const { customers } = await medusa.admin.customer.list({
|
||||
id: medusaAccountId,
|
||||
});
|
||||
@@ -316,7 +328,6 @@ export const createCompanyAccountAction = enhanceAction(
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
redirect(`/admin/accounts/${data.id}`);
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CreateUserProfileSchema = z.object({
|
||||
personalCode: z.string().regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, {
|
||||
message: 'Invalid Estonian personal code format',
|
||||
}),
|
||||
personalCode: z
|
||||
.string()
|
||||
.regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, {
|
||||
message: 'Invalid Estonian personal code format',
|
||||
}),
|
||||
});
|
||||
|
||||
export type CreateUserProfileSchemaType = z.infer<typeof CreateUserProfileSchema>;
|
||||
|
||||
export type CreateUserProfileSchemaType = z.infer<
|
||||
typeof CreateUserProfileSchema
|
||||
>;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CreateUserSchema = z.object({
|
||||
personalCode: z.string().regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, {
|
||||
message: 'Invalid Estonian personal code format',
|
||||
}),
|
||||
personalCode: z
|
||||
.string()
|
||||
.regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, {
|
||||
message: 'Invalid Estonian personal code format',
|
||||
}),
|
||||
email: z.string().email({ message: 'Please enter a valid email address' }),
|
||||
password: z
|
||||
.string()
|
||||
|
||||
@@ -44,7 +44,8 @@ class AdminAccountsService {
|
||||
.from('accounts')
|
||||
.select('*')
|
||||
.eq('id', accountId)
|
||||
.single().throwOnError();
|
||||
.single()
|
||||
.throwOnError();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import Medusa from "@medusajs/js-sdk"
|
||||
import Medusa from '@medusajs/js-sdk';
|
||||
|
||||
export const getAdminSdk = () => {
|
||||
const medusaBackendUrl = process.env.MEDUSA_BACKEND_PUBLIC_URL!;
|
||||
const medusaPublishableApiKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!;
|
||||
const medusaPublishableApiKey =
|
||||
process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!;
|
||||
const key = process.env.MEDUSA_SECRET_API_KEY!;
|
||||
|
||||
if (!medusaBackendUrl || !medusaPublishableApiKey) {
|
||||
@@ -13,4 +14,4 @@ export const getAdminSdk = () => {
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
apiKey: key,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,5 @@
|
||||
"tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json"
|
||||
},
|
||||
"include": ["*.ts", "src"],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import eslintConfigBase from '@kit/eslint-config/base.js';
|
||||
|
||||
export default eslintConfigBase;
|
||||
@@ -4,8 +4,6 @@
|
||||
"version": "0.1.0",
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf .turbo node_modules",
|
||||
"format": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"lint": "eslint .",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"exports": {
|
||||
@@ -24,8 +22,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hookform/resolvers": "^5.0.1",
|
||||
"@kit/eslint-config": "workspace:*",
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/shared": "workspace:*",
|
||||
"@kit/supabase": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
@@ -39,7 +35,6 @@
|
||||
"next": "15.3.2",
|
||||
"sonner": "^2.0.3"
|
||||
},
|
||||
"prettier": "@kit/prettier-config",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
|
||||
@@ -7,7 +7,7 @@ export function AuthLayoutShell({
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'sm:py-auto flex flex-col items-center justify-center py-6 h-screen' +
|
||||
'sm:py-auto flex h-screen flex-col items-center justify-center py-6' +
|
||||
' bg-background lg:bg-muted/30 gap-y-10 lg:gap-y-8'
|
||||
}
|
||||
>
|
||||
|
||||
@@ -4,13 +4,13 @@ import { CheckCircledIcon } from '@radix-ui/react-icons';
|
||||
|
||||
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||
import { If } from '@kit/ui/if';
|
||||
import { Spinner } from '@kit/ui/makerkit/spinner';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
|
||||
import { useCaptchaToken } from '../captcha/client';
|
||||
import { usePasswordSignUpFlow } from '../hooks/use-sign-up-flow';
|
||||
import { AuthErrorAlert } from './auth-error-alert';
|
||||
import { PasswordSignUpForm } from './password-sign-up-form';
|
||||
import { Spinner } from '@kit/ui/makerkit/spinner';
|
||||
|
||||
interface EmailPasswordSignUpContainerProps {
|
||||
authConfig: {
|
||||
@@ -56,8 +56,9 @@ export function EmailPasswordSignUpContainer({
|
||||
<div className="flex justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : <SuccessAlert />
|
||||
}
|
||||
) : (
|
||||
<SuccessAlert />
|
||||
)}
|
||||
</If>
|
||||
|
||||
<If condition={!showVerifyEmailAlert}>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import type { Provider } from '@supabase/supabase-js';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import type { Provider } from '@supabase/supabase-js';
|
||||
|
||||
import { isBrowser } from '@kit/shared/utils';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert';
|
||||
import { If } from '@kit/ui/if';
|
||||
@@ -53,7 +54,7 @@ export function SignUpMethodsContainer(props: {
|
||||
return;
|
||||
}
|
||||
setTimeout(() => {
|
||||
router.replace(props.paths.updateAccount)
|
||||
router.replace(props.paths.updateAccount);
|
||||
}, 2_500);
|
||||
}}
|
||||
/>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user