Merge branch 'main' into B2B-88
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
# https://app.supabase.com/project/_/settings/api
|
# https://app.supabase.com/project/_/settings/api
|
||||||
NEXT_PUBLIC_SUPABASE_URL=your-project-url
|
NEXT_PUBLIC_SUPABASE_URL=your-project-url
|
||||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||||
|
NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
|
||||||
|
|
||||||
MEDIPOST_URL=your-medpost-url
|
MEDIPOST_URL=your-medpost-url
|
||||||
MEDIPOST_USER=your-medpost-user
|
MEDIPOST_USER=your-medpost-user
|
||||||
|
|||||||
@@ -9,20 +9,17 @@ import {
|
|||||||
import { Trans } from '@kit/ui/trans';
|
import { Trans } from '@kit/ui/trans';
|
||||||
|
|
||||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
import { MedReportTitle } from '@/components/MedReportTitle';
|
||||||
|
|
||||||
function Home() {
|
function Home() {
|
||||||
return (
|
return (
|
||||||
<div className={'mt-4 flex flex-col space-y-24 py-14'}>
|
<div className={'mt-4 flex flex-col space-y-24 py-14'}>
|
||||||
<div className={'container mx-auto'}>
|
<div className={'container mx-auto'}>
|
||||||
<Hero
|
<Hero
|
||||||
title={
|
title={<MedReportTitle />}
|
||||||
<>
|
|
||||||
<span>Med Report</span>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
subtitle={
|
subtitle={
|
||||||
<span>
|
<span>
|
||||||
Lihtne, mugav ja kiire ülevaade Sinu tervise seisundist
|
<Trans i18nKey={'marketing:heroSubtitle'} />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
cta={<MainCallToActionButton />}
|
cta={<MainCallToActionButton />}
|
||||||
@@ -56,8 +53,8 @@ function MainCallToActionButton() {
|
|||||||
</CtaButton>
|
</CtaButton>
|
||||||
|
|
||||||
<CtaButton variant={'link'}>
|
<CtaButton variant={'link'}>
|
||||||
<Link href={'/contact'}>
|
<Link href={'/register-company'}>
|
||||||
<Trans i18nKey={'common:contactUs'} />
|
<Trans i18nKey={'account:createCompanyAccount'} />
|
||||||
</Link>
|
</Link>
|
||||||
</CtaButton>
|
</CtaButton>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
11
app/(public)/layout.tsx
Normal file
11
app/(public)/layout.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||||
|
|
||||||
|
function SiteLayout(props: React.PropsWithChildren) {
|
||||||
|
return (
|
||||||
|
<div className={'flex min-h-[100vh] flex-col justify-center items-center'}>
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withI18n(SiteLayout);
|
||||||
90
app/(public)/register-company/page.tsx
Normal file
90
app/(public)/register-company/page.tsx
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { MedReportTitle } from "@/components/MedReportTitle";
|
||||||
|
import React from "react";
|
||||||
|
import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { companySchema } from "@/lib/validations/companySchema";
|
||||||
|
import { CompanySubmitData } from "@/lib/types/company";
|
||||||
|
import { submitCompanyRegistration } from "@/lib/services/register-company.service";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { Label } from "@kit/ui/label";
|
||||||
|
import { Input } from "@kit/ui/input";
|
||||||
|
import { SubmitButton } from "@/components/ui/submit-button";
|
||||||
|
import { FormItem } from "@kit/ui/form";
|
||||||
|
import { Trans } from "@kit/ui/trans";
|
||||||
|
|
||||||
|
export default function RegisterCompany() {
|
||||||
|
const router = useRouter();
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
formState: { errors, isValid, isSubmitting },
|
||||||
|
} = useForm({
|
||||||
|
resolver: yupResolver(companySchema),
|
||||||
|
mode: "onChange",
|
||||||
|
});
|
||||||
|
|
||||||
|
async function onSubmit(data: CompanySubmitData) {
|
||||||
|
const formData = new FormData();
|
||||||
|
Object.entries(data).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined) formData.append(key, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await submitCompanyRegistration(formData);
|
||||||
|
router.push("/register-company/success");
|
||||||
|
} catch (err: unknown) {
|
||||||
|
if (err instanceof Error) {
|
||||||
|
alert("Server validation error: " + err.message);
|
||||||
|
}
|
||||||
|
alert("Server validation error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row border rounded-3xl border-border max-w-5xl overflow-hidden">
|
||||||
|
<div className="flex flex-col text-center py-14 px-12 w-1/2">
|
||||||
|
<MedReportTitle />
|
||||||
|
<h1 className="pt-8">Ettevõtte andmed</h1>
|
||||||
|
<p className="pt-2 text-muted-foreground text-sm">
|
||||||
|
Pakkumise saamiseks palun sisesta ettevõtte andmed millega MedReport
|
||||||
|
kasutada kavatsed.
|
||||||
|
</p>
|
||||||
|
<form
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
noValidate
|
||||||
|
className="flex gap-7 flex-col text-left pt-8 px-6"
|
||||||
|
>
|
||||||
|
<FormItem>
|
||||||
|
<Label>Ettevõtte nimi</Label>
|
||||||
|
<Input {...register("companyName")} />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Label>Kontaktisik</Label>
|
||||||
|
<Input {...register("contactPerson")} />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Label>E-mail</Label>
|
||||||
|
<Input type="email" {...register("email")}></Input>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Label>Telefon</Label>
|
||||||
|
<Input type="tel" {...register("phone")} />
|
||||||
|
</FormItem>
|
||||||
|
<SubmitButton
|
||||||
|
disabled={!isValid || isSubmitting}
|
||||||
|
pendingText="Saatmine..."
|
||||||
|
type="submit"
|
||||||
|
formAction={submitCompanyRegistration}
|
||||||
|
className="mt-4 hover:bg-primary/90"
|
||||||
|
>
|
||||||
|
<Trans i18nKey={'account:requestCompanyAccount'} />
|
||||||
|
</SubmitButton>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/2 min-w-[460px] bg-[url(/assets/med-report-logo-big.png)] bg-cover bg-center bg-no-repeat">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
26
app/(public)/register-company/success/page.tsx
Normal file
26
app/(public)/register-company/success/page.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { MedReportTitle } from "@/components/MedReportTitle";
|
||||||
|
import { Button } from "@/packages/ui/src/shadcn/button";
|
||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default function CompanyRegistrationSuccess() {
|
||||||
|
return (
|
||||||
|
<div className="pt-2 px-16 pb-12 border rounded-3xl border-border">
|
||||||
|
<MedReportTitle />
|
||||||
|
<div className="flex flex-col items-center px-4">
|
||||||
|
<Image
|
||||||
|
src="/assets/success.png"
|
||||||
|
alt="Success"
|
||||||
|
className="pt-6 pb-8"
|
||||||
|
width={326}
|
||||||
|
height={195}
|
||||||
|
/>
|
||||||
|
<h1 className="pb-2">Päring edukalt saadetud!</h1>
|
||||||
|
<p className=" text-muted-foreground text-sm">Saadame teile esimesel võimalusel vastuse</p>
|
||||||
|
</div>
|
||||||
|
<Button className="w-full mt-8">
|
||||||
|
<Link href="/">Tagasi kodulehele</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
22
app/(public)/sign-in/page.tsx
Normal file
22
app/(public)/sign-in/page.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Button } from '@kit/ui/button';
|
||||||
|
import Link from "next/link";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export default async function SignIn() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<Button variant="outline">
|
||||||
|
<Link href="/">Smart-ID</Link>
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline">
|
||||||
|
<Link href="/">Mobiil-ID</Link>
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline">
|
||||||
|
<Link href="/">ID-Kaart</Link>
|
||||||
|
</Button>
|
||||||
|
<Button variant="outline">
|
||||||
|
<Link href="/register-company">Loo ettevõtte konto</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
BIN
app/icon.ico
Normal file
BIN
app/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
10
components/MedReportTitle.tsx
Normal file
10
components/MedReportTitle.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { MedReportSmallLogo } from "@/public/assets/MedReportSmallLogo";
|
||||||
|
|
||||||
|
export const MedReportTitle = () => (
|
||||||
|
<div className="flex gap-2 justify-center">
|
||||||
|
<MedReportSmallLogo />
|
||||||
|
<span className="text-foreground text-lg font-semibold tracking-tighter">
|
||||||
|
MedReport
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
67
components/header-auth.tsx
Normal file
67
components/header-auth.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import { signOutAction } from "@/lib/actions/sign-out";
|
||||||
|
import { hasEnvVars } from "@/utils/supabase/check-env-vars";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { Badge } from "./ui/badge";
|
||||||
|
import { Button } from "./ui/button";
|
||||||
|
import { createClient } from "@/utils/supabase/server";
|
||||||
|
|
||||||
|
export default async function AuthButton() {
|
||||||
|
const supabase = await createClient();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { user },
|
||||||
|
} = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (!hasEnvVars) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex gap-4 items-center">
|
||||||
|
<div>
|
||||||
|
<Badge
|
||||||
|
variant={"default"}
|
||||||
|
className="font-normal pointer-events-none"
|
||||||
|
>
|
||||||
|
Please update .env.local file with anon key and url
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button
|
||||||
|
asChild
|
||||||
|
size="sm"
|
||||||
|
variant={"outline"}
|
||||||
|
disabled
|
||||||
|
className="opacity-75 cursor-none pointer-events-none"
|
||||||
|
>
|
||||||
|
<Link href="/sign-in">Sign in</Link>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
asChild
|
||||||
|
size="sm"
|
||||||
|
variant={"default"}
|
||||||
|
disabled
|
||||||
|
className="opacity-75 cursor-none pointer-events-none"
|
||||||
|
>
|
||||||
|
<Link href="example/sign-up">Sign up</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return user ? (
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
Hey, {user.email}!
|
||||||
|
<form action={signOutAction}>
|
||||||
|
<Button type="submit" variant={"outline"}>
|
||||||
|
Sign out
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Button asChild size="sm" variant={"outline"}>
|
||||||
|
<Link href="/sign-in">Sign in</Link>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
components/ui/submit-button.tsx
Normal file
23
components/ui/submit-button.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@kit/ui/button";
|
||||||
|
import { type ComponentProps } from "react";
|
||||||
|
import { useFormStatus } from "react-dom";
|
||||||
|
|
||||||
|
type Props = ComponentProps<typeof Button> & {
|
||||||
|
pendingText?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SubmitButton({
|
||||||
|
children,
|
||||||
|
pendingText = "Submitting...",
|
||||||
|
...props
|
||||||
|
}: Props) {
|
||||||
|
const { pending } = useFormStatus();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button type="submit" aria-disabled={pending} {...props}>
|
||||||
|
{pending ? pendingText : children}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
BIN
fonts/InterDisplay-Medium.woff2
Normal file
BIN
fonts/InterDisplay-Medium.woff2
Normal file
Binary file not shown.
BIN
fonts/InterDisplay-Regular.woff2
Normal file
BIN
fonts/InterDisplay-Regular.woff2
Normal file
Binary file not shown.
10
lib/actions/sign-out.tsx
Normal file
10
lib/actions/sign-out.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { createClient } from "@/utils/supabase/server";
|
||||||
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
|
export const signOutAction = async () => {
|
||||||
|
const supabase = await createClient();
|
||||||
|
await supabase.auth.signOut();
|
||||||
|
return redirect("/sign-in");
|
||||||
|
};
|
||||||
27
lib/fonts.ts
27
lib/fonts.ts
@@ -1,4 +1,5 @@
|
|||||||
import { Inter as SansFont } from 'next/font/google';
|
import { Geist as HeadingFont } from 'next/font/google';
|
||||||
|
import SansFont from 'next/font/local';
|
||||||
|
|
||||||
import { cn } from '@kit/ui/utils';
|
import { cn } from '@kit/ui/utils';
|
||||||
|
|
||||||
@@ -8,18 +9,32 @@ import { cn } from '@kit/ui/utils';
|
|||||||
* By default, it uses the Inter font from Google Fonts.
|
* By default, it uses the Inter font from Google Fonts.
|
||||||
*/
|
*/
|
||||||
const sans = SansFont({
|
const sans = SansFont({
|
||||||
subsets: ['latin'],
|
|
||||||
variable: '--font-sans',
|
variable: '--font-sans',
|
||||||
fallback: ['system-ui', 'Helvetica Neue', 'Helvetica', 'Arial'],
|
src: [
|
||||||
preload: true,
|
{
|
||||||
weight: ['300', '400', '500', '600', '700'],
|
path: '../fonts/InterDisplay-Regular.woff2',
|
||||||
|
weight: '400',
|
||||||
|
style: 'normal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '../fonts/InterDisplay-Medium.woff2',
|
||||||
|
weight: '500',
|
||||||
|
style: 'medium',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @heading
|
* @heading
|
||||||
* @description Define here the heading font.
|
* @description Define here the heading font.
|
||||||
*/
|
*/
|
||||||
const heading = sans;
|
const heading = HeadingFont({
|
||||||
|
variable: '--font-heading',
|
||||||
|
fallback: ['system-ui', 'Helvetica Neue', 'Helvetica', 'Arial'],
|
||||||
|
preload: true,
|
||||||
|
weight: ['300', '400', '500', '600', '700'],
|
||||||
|
});
|
||||||
|
|
||||||
// we export these fonts into the root layout
|
// we export these fonts into the root layout
|
||||||
export { sans, heading };
|
export { sans, heading };
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const defaultLanguage = process.env.NEXT_PUBLIC_DEFAULT_LOCALE ?? 'en';
|
|||||||
* By default, only the default language is supported.
|
* By default, only the default language is supported.
|
||||||
* Add more languages here if needed.
|
* Add more languages here if needed.
|
||||||
*/
|
*/
|
||||||
export const languages: string[] = [defaultLanguage];
|
export const languages: string[] = [defaultLanguage, 'en', 'ru'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the cookie that stores the selected language.
|
* The name of the cookie that stores the selected language.
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import {
|
import {
|
||||||
GetMessageListResponse,
|
GetMessageListResponse,
|
||||||
MedipostAction,
|
MedipostAction,
|
||||||
|
MedipostPublicMessageResponse,
|
||||||
Message,
|
Message,
|
||||||
|
UuringuGrupp,
|
||||||
} from "@/lib/types/medipost";
|
} from "@/lib/types/medipost";
|
||||||
|
import { Tables } from "@/supabase/database.types";
|
||||||
|
import { createClient, SupabaseClient } from "@supabase/supabase-js";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { xml2json } from "xml-js";
|
import { XMLParser } from "fast-xml-parser";
|
||||||
|
import { SyncStatus } from "@/lib/types/audit";
|
||||||
|
import { toArray } from "@/lib/utils";
|
||||||
|
|
||||||
const BASE_URL = process.env.MEDIPOST_URL!;
|
const BASE_URL = process.env.MEDIPOST_URL!;
|
||||||
const USER = process.env.MEDIPOST_USER!;
|
const USER = process.env.MEDIPOST_USER!;
|
||||||
@@ -15,9 +21,10 @@ export async function getMessages() {
|
|||||||
const publicMessage = await getLatestPublicMessageListItem();
|
const publicMessage = await getLatestPublicMessageListItem();
|
||||||
|
|
||||||
if (!publicMessage) {
|
if (!publicMessage) {
|
||||||
return [];
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Teenused tuleb mappida kokku MedReport teenustega. <UuringId> alusel
|
||||||
return getPublicMessage(publicMessage.messageId);
|
return getPublicMessage(publicMessage.messageId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -55,18 +62,13 @@ export async function getPublicMessage(messageId: string) {
|
|||||||
Accept: "application/xml",
|
Accept: "application/xml",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const parser = new XMLParser({ ignoreAttributes: false });
|
||||||
|
const parsed: MedipostPublicMessageResponse = parser.parse(data);
|
||||||
|
|
||||||
if (data.code && data.code !== 0) {
|
if (parsed.ANSWER?.CODE && parsed.ANSWER?.CODE !== 0) {
|
||||||
throw new Error(`Failed to get public message (id: ${messageId})`);
|
throw new Error(`Failed to get public message (id: ${messageId})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = JSON.parse(
|
|
||||||
xml2json(data, {
|
|
||||||
compact: true,
|
|
||||||
spaces: 2,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,14 +126,8 @@ export async function getPrivateMessage(messageId: string) {
|
|||||||
throw new Error(`Failed to get private message (id: ${messageId})`);
|
throw new Error(`Failed to get private message (id: ${messageId})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = JSON.parse(
|
const parser = new XMLParser({ ignoreAttributes: false });
|
||||||
xml2json(data, {
|
return parser.parse(data);
|
||||||
compact: true,
|
|
||||||
spaces: 2,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return parsed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deletePrivateMessage(messageId: string) {
|
export async function deletePrivateMessage(messageId: string) {
|
||||||
@@ -170,6 +166,187 @@ export async function readPrivateMessageResponse() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function saveAnalysisGroup(
|
||||||
|
analysisGroup: UuringuGrupp,
|
||||||
|
supabase: SupabaseClient
|
||||||
|
) {
|
||||||
|
const { data: insertedAnalysisGroup, error } = await supabase
|
||||||
|
.from("analysis_groups")
|
||||||
|
.upsert(
|
||||||
|
{
|
||||||
|
original_id: analysisGroup.UuringuGruppId,
|
||||||
|
name: analysisGroup.UuringuGruppNimi,
|
||||||
|
order: analysisGroup.UuringuGruppJarjekord,
|
||||||
|
},
|
||||||
|
{ onConflict: "original_id", ignoreDuplicates: false }
|
||||||
|
)
|
||||||
|
.select("id");
|
||||||
|
|
||||||
|
if (error || !insertedAnalysisGroup[0]?.id) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to insert analysis group (id: ${analysisGroup.UuringuGruppId}), error: ${error?.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const analysisGroupId = insertedAnalysisGroup[0].id;
|
||||||
|
|
||||||
|
const analysisGroupCodes = toArray(analysisGroup.Kood);
|
||||||
|
const codes: Partial<Tables<"codes">>[] = analysisGroupCodes.map((kood) => ({
|
||||||
|
hk_code: kood.HkKood,
|
||||||
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||||
|
coefficient: kood.Koefitsient,
|
||||||
|
price: kood.Hind,
|
||||||
|
analysis_group_id: analysisGroupId,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const analysisGroupItems = toArray(analysisGroup.Uuring);
|
||||||
|
|
||||||
|
for (const item of analysisGroupItems) {
|
||||||
|
const analysisElement = item.UuringuElement;
|
||||||
|
|
||||||
|
const { data: insertedAnalysisElement, error } = await supabase
|
||||||
|
.from("analysis_elements")
|
||||||
|
.upsert(
|
||||||
|
{
|
||||||
|
analysis_id_oid: analysisElement.UuringIdOID,
|
||||||
|
analysis_id_original: analysisElement.UuringId,
|
||||||
|
tehik_short_loinc: analysisElement.TLyhend,
|
||||||
|
tehik_loinc_name: analysisElement.KNimetus,
|
||||||
|
analysis_name_lab: analysisElement.UuringNimi,
|
||||||
|
order: analysisElement.Jarjekord,
|
||||||
|
parent_analysis_group_id: analysisGroupId,
|
||||||
|
material_groups: toArray(item.MaterjalideGrupp),
|
||||||
|
},
|
||||||
|
{ onConflict: "analysis_id_original", ignoreDuplicates: false }
|
||||||
|
)
|
||||||
|
.select('id');
|
||||||
|
|
||||||
|
if (error || !insertedAnalysisElement[0]?.id) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to insert analysis element (id: ${analysisElement.UuringId}), error: ${error?.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertedAnalysisElementId = insertedAnalysisElement[0].id;
|
||||||
|
|
||||||
|
if (analysisElement.Kood) {
|
||||||
|
const analysisElementCodes = toArray(analysisElement.Kood);
|
||||||
|
codes.push(
|
||||||
|
...analysisElementCodes.map((kood) => ({
|
||||||
|
hk_code: kood.HkKood,
|
||||||
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||||
|
coefficient: kood.Koefitsient,
|
||||||
|
price: kood.Hind,
|
||||||
|
analysis_element_id: insertedAnalysisElementId,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const analyses = analysisElement.UuringuElement;
|
||||||
|
if (analyses?.length) {
|
||||||
|
for (const analysis of analyses) {
|
||||||
|
const { data: insertedAnalysis, error } = await supabase
|
||||||
|
.from("analyses")
|
||||||
|
.upsert(
|
||||||
|
{
|
||||||
|
analysis_id_oid: analysis.UuringIdOID,
|
||||||
|
analysis_id_original: analysis.UuringId,
|
||||||
|
tehik_short_loinc: analysis.TLyhend,
|
||||||
|
tehik_loinc_name: analysis.KNimetus,
|
||||||
|
analysis_name_lab: analysis.UuringNimi,
|
||||||
|
order: analysis.Jarjekord,
|
||||||
|
parent_analysis_element_id: insertedAnalysisElementId,
|
||||||
|
},
|
||||||
|
{ onConflict: "analysis_id_original", ignoreDuplicates: false }
|
||||||
|
)
|
||||||
|
.select('id');
|
||||||
|
|
||||||
|
if (error || !insertedAnalysis[0]?.id) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to insert analysis (id: ${analysis.UuringId}) error: ${error?.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const insertedAnalysisId = insertedAnalysis[0].id;
|
||||||
|
if (analysisElement.Kood) {
|
||||||
|
const analysisCodes = toArray(analysis.Kood);
|
||||||
|
|
||||||
|
codes.push(
|
||||||
|
...analysisCodes.map((kood) => ({
|
||||||
|
hk_code: kood.HkKood,
|
||||||
|
hk_code_multiplier: kood.HkKoodiKordaja,
|
||||||
|
coefficient: kood.Koefitsient,
|
||||||
|
price: kood.Hind,
|
||||||
|
analysis_id: insertedAnalysisId,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const { error: codesError } = await supabase
|
||||||
|
.from("codes")
|
||||||
|
.upsert(codes, { ignoreDuplicates: false });
|
||||||
|
|
||||||
|
if (codesError?.code) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to insert codes (analysis group id: ${analysisGroup.UuringuGruppId})`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function syncPublicMessage(
|
||||||
|
message?: MedipostPublicMessageResponse | null
|
||||||
|
) {
|
||||||
|
const supabase = createClient(
|
||||||
|
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||||
|
process.env.NEXT_PUBLIC_SUPABASE_SERVICE_ROLE_KEY!,
|
||||||
|
{
|
||||||
|
auth: {
|
||||||
|
persistSession: false,
|
||||||
|
autoRefreshToken: false,
|
||||||
|
detectSessionInUrl: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const providers = toArray(message?.Saadetis?.Teenused.Teostaja);
|
||||||
|
const analysisGroups = providers.flatMap((provider) =>
|
||||||
|
toArray(provider.UuringuGrupp)
|
||||||
|
);
|
||||||
|
if (!message || !analysisGroups.length) {
|
||||||
|
return supabase.schema("audit").from("sync_entries").insert({
|
||||||
|
operation: "ANALYSES_SYNC",
|
||||||
|
comment: "No data received",
|
||||||
|
status: SyncStatus.Fail,
|
||||||
|
changed_by_role: "service_role",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const analysisGroup of analysisGroups) {
|
||||||
|
await saveAnalysisGroup(analysisGroup, supabase);
|
||||||
|
}
|
||||||
|
|
||||||
|
await supabase.schema("audit").from("sync_entries").insert({
|
||||||
|
operation: "ANALYSES_SYNC",
|
||||||
|
status: SyncStatus.Success,
|
||||||
|
changed_by_role: "service_role",
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
await supabase
|
||||||
|
.schema("audit")
|
||||||
|
.from("sync_entries")
|
||||||
|
.insert({
|
||||||
|
operation: "ANALYSES_SYNC",
|
||||||
|
status: SyncStatus.Fail,
|
||||||
|
comment: JSON.stringify(e),
|
||||||
|
changed_by_role: "service_role",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getLatestMessage(messages?: Message[]) {
|
function getLatestMessage(messages?: Message[]) {
|
||||||
if (!messages?.length) {
|
if (!messages?.length) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
31
lib/services/register-company.service.ts
Normal file
31
lib/services/register-company.service.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import * as yup from "yup";
|
||||||
|
import { companySchema } from "@/lib/validations/companySchema";
|
||||||
|
|
||||||
|
export async function submitCompanyRegistration(formData: FormData) {
|
||||||
|
const data = {
|
||||||
|
companyName: formData.get("companyName")?.toString() || "",
|
||||||
|
contactPerson: formData.get("contactPerson")?.toString() || "",
|
||||||
|
email: formData.get("email")?.toString() || "",
|
||||||
|
phone: formData.get("phone")?.toString() || "",
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await companySchema.validate(data, { abortEarly: false });
|
||||||
|
|
||||||
|
console.log("Valid data:", data);
|
||||||
|
} catch (validationError) {
|
||||||
|
if (validationError instanceof yup.ValidationError) {
|
||||||
|
const errors = validationError.inner.map((err) => ({
|
||||||
|
path: err.path,
|
||||||
|
message: err.message,
|
||||||
|
}));
|
||||||
|
throw new Error(
|
||||||
|
"Validation failed: " +
|
||||||
|
errors.map((e) => `${e.path}: ${e.message}`).join(", ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw validationError;
|
||||||
|
}
|
||||||
|
}
|
||||||
4
lib/types/audit.ts
Normal file
4
lib/types/audit.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum SyncStatus {
|
||||||
|
Success = "SUCCESS",
|
||||||
|
Fail = "FAIL",
|
||||||
|
}
|
||||||
6
lib/types/company.ts
Normal file
6
lib/types/company.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export interface CompanySubmitData {
|
||||||
|
companyName: string;
|
||||||
|
contactPerson: string;
|
||||||
|
email: string;
|
||||||
|
phone?: string;
|
||||||
|
}
|
||||||
@@ -20,3 +20,122 @@ export enum MedipostAction {
|
|||||||
GetPrivateMessage = "GetPrivateMessage",
|
GetPrivateMessage = "GetPrivateMessage",
|
||||||
DeletePrivateMessage = "DeletePrivateMessage",
|
DeletePrivateMessage = "DeletePrivateMessage",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type VoimalikVaartus = {
|
||||||
|
VaartusId: string;
|
||||||
|
Vaartus: "jah" | "ei";
|
||||||
|
VaartusJarjekord: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Sisendparameeter = {
|
||||||
|
"@_VastuseTyyp"?: "ARV" | "VABATEKST" | "KODEERITUD" | "AJAHETK";
|
||||||
|
"@_VastuseKoodistikuOID"?: string;
|
||||||
|
"@_VastuseKoodistikuNimi"?: string;
|
||||||
|
"@_URL"?: string;
|
||||||
|
|
||||||
|
UuringIdOID: string;
|
||||||
|
UuringId: string;
|
||||||
|
TLyhend: string;
|
||||||
|
KNimetus: string;
|
||||||
|
UuringNimi: string;
|
||||||
|
Jarjekord: number;
|
||||||
|
|
||||||
|
VoimalikVaartus: VoimalikVaartus[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Kood = {
|
||||||
|
HkKood: string;
|
||||||
|
HkKoodiKordaja: number;
|
||||||
|
Koefitsient: number; // float
|
||||||
|
Hind: number; // float
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UuringuAlamElement = {
|
||||||
|
UuringIdOID: string;
|
||||||
|
UuringId: string;
|
||||||
|
TLyhend: string;
|
||||||
|
KNimetus: string;
|
||||||
|
UuringNimi: string;
|
||||||
|
Jarjekord: string;
|
||||||
|
Kood?: Kood[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UuringuElement = {
|
||||||
|
UuringIdOID: string;
|
||||||
|
UuringId: string;
|
||||||
|
TLyhend: string;
|
||||||
|
KNimetus: string;
|
||||||
|
UuringNimi: string;
|
||||||
|
Jarjekord: string;
|
||||||
|
Kood?: Kood[];
|
||||||
|
UuringuElement?: UuringuAlamElement[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Uuring = {
|
||||||
|
tellitav: "JAH" | "EI";
|
||||||
|
UuringuElement: UuringuElement; //1..1
|
||||||
|
MaterjalideGrupp?: MaterjalideGrupp[]; //0..n
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UuringuGrupp = {
|
||||||
|
UuringuGruppId: string;
|
||||||
|
UuringuGruppNimi: string;
|
||||||
|
UuringuGruppJarjekord: number;
|
||||||
|
Uuring: Uuring | Uuring[]; //1..n
|
||||||
|
Kood?: Kood | Kood[]; //0..n
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Konteiner = {
|
||||||
|
ProovinouKoodOID: string;
|
||||||
|
ProovinouKood: string;
|
||||||
|
KonteineriNimi: string;
|
||||||
|
KonteineriKirjeldus: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Materjal = {
|
||||||
|
MaterjaliTyypOID: string;
|
||||||
|
MaterjaliTyyp: string;
|
||||||
|
MaterjaliNimi: string;
|
||||||
|
KonteineriOmadus: string;
|
||||||
|
MaterjaliPaige: { Kohustuslik: "JAH" | "EI" }; //0..1
|
||||||
|
Konteiner?: Konteiner[]; //0..n
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MaterjalideGrupp = {
|
||||||
|
vaikimisi: "JAH" | "EI";
|
||||||
|
Materjal: Materjal; //1..n
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Teostaja = {
|
||||||
|
UuringuGrupp?: UuringuGrupp | UuringuGrupp[]; //0...n
|
||||||
|
Asutus: {
|
||||||
|
AsutuseId: string;
|
||||||
|
AsutuseNimi: string;
|
||||||
|
AsutuseKood: string;
|
||||||
|
AllyksuseNimi: string;
|
||||||
|
Telefon: string;
|
||||||
|
Aadress: string;
|
||||||
|
};
|
||||||
|
Sisendparameeter?: Sisendparameeter | Sisendparameeter[]; //0...n
|
||||||
|
};
|
||||||
|
|
||||||
|
export type MedipostPublicMessageResponse = {
|
||||||
|
"?xml": {
|
||||||
|
"@_version": string;
|
||||||
|
"@_encoding": "UTF-8";
|
||||||
|
"@_standalone"?: "yes" | "no";
|
||||||
|
};
|
||||||
|
ANSWER?: { CODE: number };
|
||||||
|
Saadetis?: {
|
||||||
|
Pais: {
|
||||||
|
Pakett: { "#text": "SL" | "OL" | "AL" | "ME" }; // SL - Teenused, OL - Tellimus (meie poolt saadetav saatekiri), AL - Vastus (saatekirja vastus), ME - Teade
|
||||||
|
Saatja: string;
|
||||||
|
Saaja: string;
|
||||||
|
Aeg: string;
|
||||||
|
SaadetisId: string;
|
||||||
|
};
|
||||||
|
Teenused: {
|
||||||
|
Teostaja: Teostaja | Teostaja[]; //1..n
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,3 +4,8 @@ import { twMerge } from "tailwind-merge";
|
|||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs));
|
return twMerge(clsx(inputs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toArray<T>(input?: T | T[] | null): T[] {
|
||||||
|
if (!input) return [];
|
||||||
|
return Array.isArray(input) ? input : [input];
|
||||||
|
}
|
||||||
|
|||||||
8
lib/validations/companySchema.ts
Normal file
8
lib/validations/companySchema.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import * as yup from "yup";
|
||||||
|
|
||||||
|
export const companySchema = yup.object({
|
||||||
|
companyName: yup.string().required("Company name is required"),
|
||||||
|
contactPerson: yup.string().required("Contact person is required"),
|
||||||
|
email: yup.string().email("Invalid email").required("Email is required"),
|
||||||
|
phone: yup.string().optional(),
|
||||||
|
});
|
||||||
@@ -61,6 +61,7 @@
|
|||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"fast-xml-parser": "^5.2.3",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"lucide-react": "^0.510.0",
|
"lucide-react": "^0.510.0",
|
||||||
"next": "15.3.2",
|
"next": "15.3.2",
|
||||||
@@ -73,10 +74,10 @@
|
|||||||
"recharts": "2.15.3",
|
"recharts": "2.15.3",
|
||||||
"sonner": "^2.0.3",
|
"sonner": "^2.0.3",
|
||||||
"tailwind-merge": "^3.3.0",
|
"tailwind-merge": "^3.3.0",
|
||||||
"xml-js": "^1.6.11",
|
|
||||||
"zod": "^3.24.4"
|
"zod": "^3.24.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@hookform/resolvers": "^5.0.1",
|
||||||
"@kit/eslint-config": "workspace:*",
|
"@kit/eslint-config": "workspace:*",
|
||||||
"@kit/prettier-config": "workspace:*",
|
"@kit/prettier-config": "workspace:*",
|
||||||
"@kit/tsconfig": "workspace:*",
|
"@kit/tsconfig": "workspace:*",
|
||||||
@@ -85,6 +86,7 @@
|
|||||||
"@types/node": "^22.15.18",
|
"@types/node": "^22.15.18",
|
||||||
"@types/react": "19.1.4",
|
"@types/react": "19.1.4",
|
||||||
"@types/react-dom": "19.1.5",
|
"@types/react-dom": "19.1.5",
|
||||||
|
"react-hook-form": "^7.57.0",
|
||||||
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
"babel-plugin-react-compiler": "19.1.0-rc.2",
|
||||||
"cssnano": "^7.0.7",
|
"cssnano": "^7.0.7",
|
||||||
"pino-pretty": "^13.0.0",
|
"pino-pretty": "^13.0.0",
|
||||||
@@ -92,7 +94,8 @@
|
|||||||
"supabase": "^2.22.12",
|
"supabase": "^2.22.12",
|
||||||
"tailwindcss": "4.1.7",
|
"tailwindcss": "4.1.7",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5.8.3"
|
"typescript": "^5.8.3",
|
||||||
|
"yup": "^1.6.1"
|
||||||
},
|
},
|
||||||
"prettier": "@kit/prettier-config",
|
"prettier": "@kit/prettier-config",
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
@@ -100,4 +103,4 @@
|
|||||||
"> 0.7%",
|
"> 0.7%",
|
||||||
"not dead"
|
"not dead"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { cn } from '../../lib/utils';
|
import { cn } from '../../lib/utils';
|
||||||
|
import { LanguageSelector } from '@kit/ui/language-selector';
|
||||||
interface HeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
interface HeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||||
logo?: React.ReactNode;
|
logo?: React.ReactNode;
|
||||||
navigation?: React.ReactNode;
|
navigation?: React.ReactNode;
|
||||||
@@ -25,7 +25,8 @@ export const Header: React.FC<HeaderProps> = function ({
|
|||||||
<div className="grid h-14 grid-cols-3 items-center">
|
<div className="grid h-14 grid-cols-3 items-center">
|
||||||
<div className={'mx-auto md:mx-0'}>{logo}</div>
|
<div className={'mx-auto md:mx-0'}>{logo}</div>
|
||||||
<div className="order-first md:order-none">{navigation}</div>
|
<div className="order-first md:order-none">{navigation}</div>
|
||||||
<div className="flex items-center justify-end gap-x-2">{actions}</div>
|
|
||||||
|
<div className="flex items-center justify-end gap-x-2"><div className="max-w-[100px]"><LanguageSelector /></div>{actions}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const buttonVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
'bg-primary text-primary-foreground hover:bg-primary/90 shadow-xs',
|
'bg-primary text-primary-foreground font-medium hover:bg-primary/90 shadow-xs',
|
||||||
destructive:
|
destructive:
|
||||||
'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-xs',
|
'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-xs',
|
||||||
outline:
|
outline:
|
||||||
|
|||||||
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
@@ -101,6 +101,9 @@ importers:
|
|||||||
date-fns:
|
date-fns:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
|
fast-xml-parser:
|
||||||
|
specifier: ^5.2.3
|
||||||
|
version: 5.2.5
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: ^0.510.0
|
specifier: ^0.510.0
|
||||||
version: 0.510.0(react@19.1.0)
|
version: 0.510.0(react@19.1.0)
|
||||||
@@ -134,9 +137,6 @@ importers:
|
|||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^3.3.0
|
specifier: ^3.3.0
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
xml-js:
|
|
||||||
specifier: ^1.6.11
|
|
||||||
version: 1.6.11
|
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.24.4
|
specifier: ^3.24.4
|
||||||
version: 3.25.56
|
version: 3.25.56
|
||||||
@@ -189,6 +189,9 @@ importers:
|
|||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.8.3
|
specifier: ^5.8.3
|
||||||
version: 5.8.3
|
version: 5.8.3
|
||||||
|
yup:
|
||||||
|
specifier: ^1.6.1
|
||||||
|
version: 1.6.1
|
||||||
|
|
||||||
packages/analytics:
|
packages/analytics:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@@ -5362,6 +5365,10 @@ packages:
|
|||||||
fast-uri@3.0.6:
|
fast-uri@3.0.6:
|
||||||
resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==}
|
resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==}
|
||||||
|
|
||||||
|
fast-xml-parser@5.2.5:
|
||||||
|
resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
fastq@1.19.1:
|
fastq@1.19.1:
|
||||||
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
|
resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
|
||||||
|
|
||||||
@@ -6727,6 +6734,9 @@ packages:
|
|||||||
prop-types@15.8.1:
|
prop-types@15.8.1:
|
||||||
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
|
||||||
|
|
||||||
|
property-expr@2.0.6:
|
||||||
|
resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==}
|
||||||
|
|
||||||
prosemirror-commands@1.7.1:
|
prosemirror-commands@1.7.1:
|
||||||
resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==}
|
resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==}
|
||||||
|
|
||||||
@@ -6976,9 +6986,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
sax@1.4.1:
|
|
||||||
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
|
|
||||||
|
|
||||||
scheduler@0.26.0:
|
scheduler@0.26.0:
|
||||||
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
|
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
|
||||||
|
|
||||||
@@ -7176,6 +7183,9 @@ packages:
|
|||||||
'@types/node':
|
'@types/node':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
strnum@2.1.1:
|
||||||
|
resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==}
|
||||||
|
|
||||||
styled-jsx@5.1.6:
|
styled-jsx@5.1.6:
|
||||||
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
|
resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
|
||||||
engines: {node: '>= 12.0.0'}
|
engines: {node: '>= 12.0.0'}
|
||||||
@@ -7273,6 +7283,9 @@ packages:
|
|||||||
thread-stream@3.1.0:
|
thread-stream@3.1.0:
|
||||||
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
|
resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
|
||||||
|
|
||||||
|
tiny-case@1.0.3:
|
||||||
|
resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==}
|
||||||
|
|
||||||
tiny-invariant@1.0.6:
|
tiny-invariant@1.0.6:
|
||||||
resolution: {integrity: sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==}
|
resolution: {integrity: sha512-FOyLWWVjG+aC0UqG76V53yAWdXfH8bO6FNmyZOuUrzDzK8DI3/JRY25UD7+g49JWM1LXwymsKERB+DzI0dTEQA==}
|
||||||
|
|
||||||
@@ -7290,6 +7303,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
|
|
||||||
|
toposort@2.0.2:
|
||||||
|
resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==}
|
||||||
|
|
||||||
totalist@3.0.1:
|
totalist@3.0.1:
|
||||||
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -7354,6 +7370,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==}
|
resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
type-fest@2.19.0:
|
||||||
|
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
|
||||||
|
engines: {node: '>=12.20'}
|
||||||
|
|
||||||
typed-array-buffer@1.0.3:
|
typed-array-buffer@1.0.3:
|
||||||
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
|
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -7579,10 +7599,6 @@ packages:
|
|||||||
utf-8-validate:
|
utf-8-validate:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
xml-js@1.6.11:
|
|
||||||
resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
xtend@4.0.2:
|
xtend@4.0.2:
|
||||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||||
engines: {node: '>=0.4'}
|
engines: {node: '>=0.4'}
|
||||||
@@ -7639,6 +7655,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
yup@1.6.1:
|
||||||
|
resolution: {integrity: sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==}
|
||||||
|
|
||||||
zod@3.25.56:
|
zod@3.25.56:
|
||||||
resolution: {integrity: sha512-rd6eEF3BTNvQnR2e2wwolfTmUTnp70aUTqr0oaGbHifzC3BKJsoV+Gat8vxUMR1hwOKBs6El+qWehrHbCpW6SQ==}
|
resolution: {integrity: sha512-rd6eEF3BTNvQnR2e2wwolfTmUTnp70aUTqr0oaGbHifzC3BKJsoV+Gat8vxUMR1hwOKBs6El+qWehrHbCpW6SQ==}
|
||||||
|
|
||||||
@@ -12494,6 +12513,10 @@ snapshots:
|
|||||||
|
|
||||||
fast-uri@3.0.6: {}
|
fast-uri@3.0.6: {}
|
||||||
|
|
||||||
|
fast-xml-parser@5.2.5:
|
||||||
|
dependencies:
|
||||||
|
strnum: 2.1.1
|
||||||
|
|
||||||
fastq@1.19.1:
|
fastq@1.19.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify: 1.1.0
|
reusify: 1.1.0
|
||||||
@@ -13960,6 +13983,8 @@ snapshots:
|
|||||||
object-assign: 4.1.1
|
object-assign: 4.1.1
|
||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
|
|
||||||
|
property-expr@2.0.6: {}
|
||||||
|
|
||||||
prosemirror-commands@1.7.1:
|
prosemirror-commands@1.7.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
prosemirror-model: 1.25.1
|
prosemirror-model: 1.25.1
|
||||||
@@ -14266,8 +14291,6 @@ snapshots:
|
|||||||
|
|
||||||
safe-stable-stringify@2.5.0: {}
|
safe-stable-stringify@2.5.0: {}
|
||||||
|
|
||||||
sax@1.4.1: {}
|
|
||||||
|
|
||||||
scheduler@0.26.0: {}
|
scheduler@0.26.0: {}
|
||||||
|
|
||||||
schema-utils@4.3.2:
|
schema-utils@4.3.2:
|
||||||
@@ -14537,6 +14560,8 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 22.15.30
|
'@types/node': 22.15.30
|
||||||
|
|
||||||
|
strnum@2.1.1: {}
|
||||||
|
|
||||||
styled-jsx@5.1.6(@babel/core@7.27.4)(react@19.1.0):
|
styled-jsx@5.1.6(@babel/core@7.27.4)(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
client-only: 0.0.1
|
client-only: 0.0.1
|
||||||
@@ -14626,6 +14651,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
real-require: 0.2.0
|
real-require: 0.2.0
|
||||||
|
|
||||||
|
tiny-case@1.0.3: {}
|
||||||
|
|
||||||
tiny-invariant@1.0.6: {}
|
tiny-invariant@1.0.6: {}
|
||||||
|
|
||||||
tiny-invariant@1.3.3: {}
|
tiny-invariant@1.3.3: {}
|
||||||
@@ -14641,6 +14668,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
|
|
||||||
|
toposort@2.0.2: {}
|
||||||
|
|
||||||
totalist@3.0.1: {}
|
totalist@3.0.1: {}
|
||||||
|
|
||||||
tr46@0.0.3: {}
|
tr46@0.0.3: {}
|
||||||
@@ -14693,6 +14722,8 @@ snapshots:
|
|||||||
|
|
||||||
type-fest@0.7.1: {}
|
type-fest@0.7.1: {}
|
||||||
|
|
||||||
|
type-fest@2.19.0: {}
|
||||||
|
|
||||||
typed-array-buffer@1.0.3:
|
typed-array-buffer@1.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.4
|
call-bound: 1.0.4
|
||||||
@@ -15006,10 +15037,6 @@ snapshots:
|
|||||||
|
|
||||||
ws@8.18.2: {}
|
ws@8.18.2: {}
|
||||||
|
|
||||||
xml-js@1.6.11:
|
|
||||||
dependencies:
|
|
||||||
sax: 1.4.1
|
|
||||||
|
|
||||||
xtend@4.0.2: {}
|
xtend@4.0.2: {}
|
||||||
|
|
||||||
y-prosemirror@1.3.5(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27):
|
y-prosemirror@1.3.5(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.27))(yjs@13.6.27):
|
||||||
@@ -15056,6 +15083,13 @@ snapshots:
|
|||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|
||||||
|
yup@1.6.1:
|
||||||
|
dependencies:
|
||||||
|
property-expr: 2.0.6
|
||||||
|
tiny-case: 1.0.3
|
||||||
|
toposort: 2.0.2
|
||||||
|
type-fest: 2.19.0
|
||||||
|
|
||||||
zod@3.25.56: {}
|
zod@3.25.56: {}
|
||||||
|
|
||||||
zwitch@2.0.4: {}
|
zwitch@2.0.4: {}
|
||||||
|
|||||||
16
public/assets/MedReportSmallLogo.tsx
Normal file
16
public/assets/MedReportSmallLogo.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
export const MedReportSmallLogo = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="21"
|
||||||
|
height="21"
|
||||||
|
viewBox="0 0 21 21"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M20.7002 11.7002C15.7296 11.7002 11.7002 15.7296 11.7002 20.7002H8.10059C8.10059 13.7414 13.7414 8.10059 20.7002 8.10059V11.7002ZM12.8994 0.299805C12.8994 7.25859 7.25859 12.8994 0.299805 12.8994V9.2998C5.27037 9.2998 9.2998 5.27037 9.2998 0.299805H12.8994Z"
|
||||||
|
fill="#0A5328"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
BIN
public/assets/med-report-logo-big.png
Normal file
BIN
public/assets/med-report-logo-big.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
public/assets/success.png
Normal file
BIN
public/assets/success.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -111,5 +111,7 @@
|
|||||||
"languageDescription": "Choose your preferred language",
|
"languageDescription": "Choose your preferred language",
|
||||||
"noTeamsYet": "You don't have any teams yet.",
|
"noTeamsYet": "You don't have any teams yet.",
|
||||||
"createTeam": "Create a team to get started.",
|
"createTeam": "Create a team to get started.",
|
||||||
"createTeamButtonLabel": "Create a Team"
|
"createTeamButtonLabel": "Create a Team",
|
||||||
|
"createCompanyAccount": "Create Company Account",
|
||||||
|
"requestCompanyAccount": "Request Company Account"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,5 +35,6 @@
|
|||||||
"contactSuccessDescription": "We have received your message and will get back to you as soon as possible",
|
"contactSuccessDescription": "We have received your message and will get back to you as soon as possible",
|
||||||
"contactErrorDescription": "An error occurred while sending your message. Please try again later",
|
"contactErrorDescription": "An error occurred while sending your message. Please try again later",
|
||||||
"footerDescription": "Here you can add a description about your company or product",
|
"footerDescription": "Here you can add a description about your company or product",
|
||||||
"copyright": "© Copyright {{year}} {{product}}. All Rights Reserved."
|
"copyright": "© Copyright {{year}} {{product}}. All Rights Reserved.",
|
||||||
|
"heroSubtitle": "A simple, convenient, and quick overview of your health condition"
|
||||||
}
|
}
|
||||||
|
|||||||
117
public/locales/et/account.json
Normal file
117
public/locales/et/account.json
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"accountTabLabel": "Account Settings",
|
||||||
|
"accountTabDescription": "Manage your account settings",
|
||||||
|
"homePage": "Home",
|
||||||
|
"billingTab": "Billing",
|
||||||
|
"settingsTab": "Settings",
|
||||||
|
"multiFactorAuth": "Multi-Factor Authentication",
|
||||||
|
"multiFactorAuthDescription": "Set up Multi-Factor Authentication method to further secure your account",
|
||||||
|
"updateProfileSuccess": "Profile successfully updated",
|
||||||
|
"updateProfileError": "Encountered an error. Please try again",
|
||||||
|
"updatePasswordSuccess": "Password update request successful",
|
||||||
|
"updatePasswordSuccessMessage": "Your password has been successfully updated!",
|
||||||
|
"updatePasswordError": "Encountered an error. Please try again",
|
||||||
|
"updatePasswordLoading": "Updating password...",
|
||||||
|
"updateProfileLoading": "Updating profile...",
|
||||||
|
"name": "Your Name",
|
||||||
|
"nameDescription": "Update your name to be displayed on your profile",
|
||||||
|
"emailLabel": "Email Address",
|
||||||
|
"accountImage": "Your Profile Picture",
|
||||||
|
"accountImageDescription": "Please choose a photo to upload as your profile picture.",
|
||||||
|
"profilePictureHeading": "Upload a Profile Picture",
|
||||||
|
"profilePictureSubheading": "Choose a photo to upload as your profile picture.",
|
||||||
|
"updateProfileSubmitLabel": "Update Profile",
|
||||||
|
"updatePasswordCardTitle": "Update your Password",
|
||||||
|
"updatePasswordCardDescription": "Update your password to keep your account secure.",
|
||||||
|
"currentPassword": "Current Password",
|
||||||
|
"newPassword": "New Password",
|
||||||
|
"repeatPassword": "Repeat New Password",
|
||||||
|
"repeatPasswordDescription": "Please repeat your new password to confirm it",
|
||||||
|
"yourPassword": "Your Password",
|
||||||
|
"updatePasswordSubmitLabel": "Update Password",
|
||||||
|
"updateEmailCardTitle": "Update your Email",
|
||||||
|
"updateEmailCardDescription": "Update your email address you use to login to your account",
|
||||||
|
"newEmail": "Your New Email",
|
||||||
|
"repeatEmail": "Repeat Email",
|
||||||
|
"updateEmailSubmitLabel": "Update Email Address",
|
||||||
|
"updateEmailSuccess": "Email update request successful",
|
||||||
|
"updateEmailSuccessMessage": "We sent you an email to confirm your new email address. Please check your inbox and click on the link to confirm your new email address.",
|
||||||
|
"updateEmailLoading": "Updating your email...",
|
||||||
|
"updateEmailError": "Email not updated. Please try again",
|
||||||
|
"passwordNotMatching": "Passwords do not match. Make sure you're using the correct password",
|
||||||
|
"emailNotMatching": "Emails do not match. Make sure you're using the correct email",
|
||||||
|
"passwordNotChanged": "Your password has not changed",
|
||||||
|
"emailsNotMatching": "Emails do not match. Make sure you're using the correct email",
|
||||||
|
"cannotUpdatePassword": "You cannot update your password because your account is not linked to any.",
|
||||||
|
"setupMfaButtonLabel": "Setup a new Factor",
|
||||||
|
"multiFactorSetupErrorHeading": "Setup Failed",
|
||||||
|
"multiFactorSetupErrorDescription": "Sorry, there was an error while setting up your factor. Please try again.",
|
||||||
|
"multiFactorAuthHeading": "Secure your account with Multi-Factor Authentication",
|
||||||
|
"multiFactorModalHeading": "Use your authenticator app to scan the QR code below. Then enter the code generated.",
|
||||||
|
"factorNameLabel": "A memorable name to identify this factor",
|
||||||
|
"factorNameHint": "Use an easy-to-remember name to easily identify this factor in the future. Ex. iPhone 14",
|
||||||
|
"factorNameSubmitLabel": "Set factor name",
|
||||||
|
"unenrollTooltip": "Unenroll this factor",
|
||||||
|
"unenrollingFactor": "Unenrolling factor...",
|
||||||
|
"unenrollFactorSuccess": "Factor successfully unenrolled",
|
||||||
|
"unenrollFactorError": "Unenrolling factor failed",
|
||||||
|
"factorsListError": "Error loading factors list",
|
||||||
|
"factorsListErrorDescription": "Sorry, we couldn't load the factors list. Please try again.",
|
||||||
|
"factorName": "Factor Name",
|
||||||
|
"factorType": "Type",
|
||||||
|
"factorStatus": "Status",
|
||||||
|
"mfaEnabledSuccessTitle": "Multi-Factor authentication is enabled",
|
||||||
|
"mfaEnabledSuccessDescription": "Congratulations! You have successfully enrolled in the multi factor authentication process. You will now be able to access your account with a combination of your password and an authentication code sent to your phone number.",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"addEmailAddress": "Add Email address",
|
||||||
|
"verifyActivationCodeDescription": "Enter the 6-digit code generated by your authenticator app in the field above",
|
||||||
|
"loadingFactors": "Loading factors...",
|
||||||
|
"enableMfaFactor": "Enable Factor",
|
||||||
|
"disableMfaFactor": "Disable Factor",
|
||||||
|
"qrCodeErrorHeading": "QR Code Error",
|
||||||
|
"qrCodeErrorDescription": "Sorry, we weren't able to generate the QR code",
|
||||||
|
"multiFactorSetupSuccess": "Factor successfully enrolled",
|
||||||
|
"submitVerificationCode": "Submit Verification Code",
|
||||||
|
"mfaEnabledSuccessAlert": "Multi-Factor authentication is enabled",
|
||||||
|
"verifyingCode": "Verifying code...",
|
||||||
|
"invalidVerificationCodeHeading": "Invalid Verification Code",
|
||||||
|
"invalidVerificationCodeDescription": "The verification code you entered is invalid. Please try again.",
|
||||||
|
"unenrollFactorModalHeading": "Unenroll Factor",
|
||||||
|
"unenrollFactorModalDescription": "You're about to unenroll this factor. You will not be able to use it to login to your account.",
|
||||||
|
"unenrollFactorModalBody": "You're about to unenroll this factor. You will not be able to use it to login to your account.",
|
||||||
|
"unenrollFactorModalButtonLabel": "Yes, unenroll factor",
|
||||||
|
"selectFactor": "Choose a factor to verify your identity",
|
||||||
|
"disableMfa": "Disable Multi-Factor Authentication",
|
||||||
|
"disableMfaButtonLabel": "Disable MFA",
|
||||||
|
"confirmDisableMfaButtonLabel": "Yes, disable MFA",
|
||||||
|
"disablingMfa": "Disabling Multi-Factor Authentication. Please wait...",
|
||||||
|
"disableMfaSuccess": "Multi-Factor Authentication successfully disabled",
|
||||||
|
"disableMfaError": "Sorry, we encountered an error. MFA has not been disabled.",
|
||||||
|
"sendingEmailVerificationLink": "Sending Email...",
|
||||||
|
"sendEmailVerificationLinkSuccess": "Verification link successfully sent",
|
||||||
|
"sendEmailVerificationLinkError": "Sorry, we weren't able to send you the email",
|
||||||
|
"sendVerificationLinkSubmitLabel": "Send Verification Link",
|
||||||
|
"sendVerificationLinkSuccessLabel": "Email sent! Check your Inbox",
|
||||||
|
"verifyEmailAlertHeading": "Please verify your email to enable MFA",
|
||||||
|
"verificationLinkAlertDescription": "Your email is not yet verified. Please verify your email to be able to set up Multi-Factor Authentication.",
|
||||||
|
"authFactorName": "Factor Name (optional)",
|
||||||
|
"authFactorNameHint": "Assign a name that helps you remember the phone number used",
|
||||||
|
"loadingUser": "Loading user details. Please wait...",
|
||||||
|
"linkPhoneNumber": "Link Phone Number",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneDescription": "Some actions cannot be undone. Please be careful.",
|
||||||
|
"deleteAccount": "Delete your Account",
|
||||||
|
"deletingAccount": "Deleting account. Please wait...",
|
||||||
|
"deleteAccountDescription": "This will delete your account and the accounts you own. Furthermore, we will immediately cancel any active subscriptions. This action cannot be undone.",
|
||||||
|
"deleteProfileConfirmationInputLabel": "Type DELETE to confirm",
|
||||||
|
"deleteAccountErrorHeading": "Sorry, we couldn't delete your account",
|
||||||
|
"needsReauthentication": "Reauthentication Required",
|
||||||
|
"needsReauthenticationDescription": "You need to reauthenticate to change your password. Please sign out and sign in again to change your password.",
|
||||||
|
"language": "Language",
|
||||||
|
"languageDescription": "Choose your preferred language",
|
||||||
|
"noTeamsYet": "You don't have any teams yet.",
|
||||||
|
"createTeam": "Create a team to get started.",
|
||||||
|
"createTeamButtonLabel": "Create a Team",
|
||||||
|
"createCompanyAccount": "Create Company Account",
|
||||||
|
"requestCompanyAccount": "Küsi pakkumist"
|
||||||
|
}
|
||||||
90
public/locales/et/auth.json
Normal file
90
public/locales/et/auth.json
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"signUpHeading": "Create an account",
|
||||||
|
"signUp": "Sign Up",
|
||||||
|
"signUpSubheading": "Fill the form below to create an account.",
|
||||||
|
"signInHeading": "Sign in to your account",
|
||||||
|
"signInSubheading": "Welcome back! Please enter your details",
|
||||||
|
"signIn": "Sign In",
|
||||||
|
"getStarted": "Get started",
|
||||||
|
"updatePassword": "Update Password",
|
||||||
|
"signOut": "Sign out",
|
||||||
|
"signingIn": "Signing in...",
|
||||||
|
"signingUp": "Signing up...",
|
||||||
|
"doNotHaveAccountYet": "Do not have an account yet?",
|
||||||
|
"alreadyHaveAnAccount": "Already have an account?",
|
||||||
|
"signUpToAcceptInvite": "Please sign in/up to accept the invite",
|
||||||
|
"clickToAcceptAs": "Click the button below to accept the invite with as <b>{{email}}</b>",
|
||||||
|
"acceptInvite": "Accept invite",
|
||||||
|
"acceptingInvite": "Accepting Invite...",
|
||||||
|
"acceptInviteSuccess": "Invite successfully accepted",
|
||||||
|
"acceptInviteError": "Error encountered while accepting invite",
|
||||||
|
"acceptInviteWithDifferentAccount": "Want to accept the invite with a different account?",
|
||||||
|
"alreadyHaveAccountStatement": "I already have an account, I want to sign in instead",
|
||||||
|
"doNotHaveAccountStatement": "I do not have an account, I want to sign up instead",
|
||||||
|
"signInWithProvider": "Sign in with {{provider}}",
|
||||||
|
"signInWithPhoneNumber": "Sign in with Phone Number",
|
||||||
|
"signInWithEmail": "Sign in with Email",
|
||||||
|
"signUpWithEmail": "Sign up with Email",
|
||||||
|
"passwordHint": "Ensure it's at least 8 characters",
|
||||||
|
"repeatPasswordHint": "Type your password again",
|
||||||
|
"repeatPassword": "Repeat password",
|
||||||
|
"passwordForgottenQuestion": "Password forgotten?",
|
||||||
|
"passwordResetLabel": "Reset Password",
|
||||||
|
"passwordResetSubheading": "Enter your email address below. You will receive a link to reset your password.",
|
||||||
|
"passwordResetSuccessMessage": "Check your Inbox! We emailed you a link for resetting your Password.",
|
||||||
|
"passwordRecoveredQuestion": "Password recovered?",
|
||||||
|
"passwordLengthError": "Please provide a password with at least 6 characters",
|
||||||
|
"sendEmailLink": "Send Email Link",
|
||||||
|
"sendingEmailLink": "Sending Email Link...",
|
||||||
|
"sendLinkSuccessDescription": "Check your email, we just sent you a link. Follow the link to sign in.",
|
||||||
|
"sendLinkSuccess": "We sent you a link by email",
|
||||||
|
"sendLinkSuccessToast": "Link successfully sent",
|
||||||
|
"getNewLink": "Get a new link",
|
||||||
|
"verifyCodeHeading": "Verify your account",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"verificationCodeHint": "Enter the code we sent you by SMS",
|
||||||
|
"verificationCodeSubmitButtonLabel": "Submit Verification Code",
|
||||||
|
"sendingMfaCode": "Sending Verification Code...",
|
||||||
|
"verifyingMfaCode": "Verifying code...",
|
||||||
|
"sendMfaCodeError": "Sorry, we couldn't send you a verification code",
|
||||||
|
"verifyMfaCodeSuccess": "Code verified! Signing you in...",
|
||||||
|
"verifyMfaCodeError": "Ops! It looks like the code is not correct",
|
||||||
|
"reauthenticate": "Reauthenticate",
|
||||||
|
"reauthenticateDescription": "For security reasons, we need you to re-authenticate",
|
||||||
|
"errorAlertHeading": "Sorry, we could not authenticate you",
|
||||||
|
"emailConfirmationAlertHeading": "We sent you a confirmation email.",
|
||||||
|
"emailConfirmationAlertBody": "Welcome! Please check your email and click the link to verify your account.",
|
||||||
|
"resendLink": "Resend link",
|
||||||
|
"resendLinkSuccessDescription": "We sent you a new link to your email! Follow the link to sign in.",
|
||||||
|
"resendLinkSuccess": "Check your email!",
|
||||||
|
"authenticationErrorAlertHeading": "Authentication Error",
|
||||||
|
"authenticationErrorAlertBody": "Sorry, we could not authenticate you. Please try again.",
|
||||||
|
"sendEmailCode": "Get code to your Email",
|
||||||
|
"sendingEmailCode": "Sending code...",
|
||||||
|
"resetPasswordError": "Sorry, we could not reset your password. Please try again.",
|
||||||
|
"emailPlaceholder": "your@email.com",
|
||||||
|
"inviteAlertHeading": "You have been invited to join a team",
|
||||||
|
"inviteAlertBody": "Please sign in or sign up to accept the invite and join the team.",
|
||||||
|
"acceptTermsAndConditions": "I accept the <TermsOfServiceLink /> and <PrivacyPolicyLink />",
|
||||||
|
"termsOfService": "Terms of Service",
|
||||||
|
"privacyPolicy": "Privacy Policy",
|
||||||
|
"orContinueWith": "Or continue with",
|
||||||
|
"redirecting": "You're in! Please wait...",
|
||||||
|
"errors": {
|
||||||
|
"Invalid login credentials": "The credentials entered are invalid",
|
||||||
|
"User already registered": "This credential is already in use. Please try with another one.",
|
||||||
|
"Email not confirmed": "Please confirm your email address before signing in",
|
||||||
|
"default": "We have encountered an error. Please ensure you have a working internet connection and try again",
|
||||||
|
"generic": "Sorry, we weren't able to authenticate you. Please try again.",
|
||||||
|
"link": "Sorry, we encountered an error while sending your link. Please try again.",
|
||||||
|
"codeVerifierMismatch": "It looks like you're trying to sign in using a different browser than the one you used to request the sign in link. Please try again using the same browser.",
|
||||||
|
"minPasswordLength": "Password must be at least 8 characters long",
|
||||||
|
"passwordsDoNotMatch": "The passwords do not match",
|
||||||
|
"minPasswordNumbers": "Password must contain at least one number",
|
||||||
|
"minPasswordSpecialChars": "Password must contain at least one special character",
|
||||||
|
"uppercasePassword": "Password must contain at least one uppercase letter",
|
||||||
|
"insufficient_aal": "Please sign-in with your current multi-factor authentication to perform this action",
|
||||||
|
"otp_expired": "The email link has expired. Please try again.",
|
||||||
|
"same_password": "The password cannot be the same as the current password"
|
||||||
|
}
|
||||||
|
}
|
||||||
120
public/locales/et/billing.json
Normal file
120
public/locales/et/billing.json
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
{
|
||||||
|
"subscriptionTabSubheading": "Manage your Subscription and Billing",
|
||||||
|
"planCardTitle": "Your Plan",
|
||||||
|
"planCardDescription": "Below are the details of your current plan. You can change your plan or cancel your subscription at any time.",
|
||||||
|
"planRenewal": "Renews every {{interval}} at {{price}}",
|
||||||
|
"planDetails": "Plan Details",
|
||||||
|
"checkout": "Proceed to Checkout",
|
||||||
|
"trialEndsOn": "Your trial ends on",
|
||||||
|
"billingPortalCardButton": "Visit Billing Portal",
|
||||||
|
"billingPortalCardTitle": "Manage your Billing Details",
|
||||||
|
"billingPortalCardDescription": "Visit your Billing Portal to manage your subscription and billing. You can update or cancel your plan, or download your invoices.",
|
||||||
|
"cancelAtPeriodEndDescription": "Your subscription is scheduled to be canceled on {{- endDate }}.",
|
||||||
|
"renewAtPeriodEndDescription": "Your subscription is scheduled to be renewed on {{- endDate }}",
|
||||||
|
"noPermissionsAlertHeading": "You don't have permissions to change the billing settings",
|
||||||
|
"noPermissionsAlertBody": "Please contact your account owner to change the billing settings for your account.",
|
||||||
|
"checkoutSuccessTitle": "Done! You're all set.",
|
||||||
|
"checkoutSuccessDescription": "Thank you for subscribing, we have successfully processed your subscription! A confirmation email will be sent to {{ customerEmail }}.",
|
||||||
|
"checkoutSuccessBackButton": "Proceed to App",
|
||||||
|
"cannotManageBillingAlertTitle": "You cannot manage billing",
|
||||||
|
"cannotManageBillingAlertDescription": "You do not have permissions to manage billing. Please contact your account owner.",
|
||||||
|
"manageTeamPlan": "Manage your Team Plan",
|
||||||
|
"manageTeamPlanDescription": "Choose a plan that fits your team's needs. You can upgrade or downgrade your plan at any time.",
|
||||||
|
"basePlan": "Base Plan",
|
||||||
|
"billingInterval": {
|
||||||
|
"label": "Choose your billing interval",
|
||||||
|
"month": "Billed monthly",
|
||||||
|
"year": "Billed yearly"
|
||||||
|
},
|
||||||
|
"perMonth": "month",
|
||||||
|
"custom": "Custom Plan",
|
||||||
|
"lifetime": "Lifetime",
|
||||||
|
"trialPeriod": "{{period}} day trial",
|
||||||
|
"perPeriod": "per {{period}}",
|
||||||
|
"redirectingToPayment": "Redirecting to checkout. Please wait...",
|
||||||
|
"proceedToPayment": "Proceed to Payment",
|
||||||
|
"startTrial": "Start Trial",
|
||||||
|
"perTeamMember": "Per team member",
|
||||||
|
"perUnit": "Per {{unit}} usage",
|
||||||
|
"teamMembers": "Team Members",
|
||||||
|
"includedUpTo": "Up to {{upTo}} {{unit}} included in the plan",
|
||||||
|
"fromPreviousTierUpTo": "for each {{unit}} for the next {{ upTo }} {{ unit }}",
|
||||||
|
"andAbove": "above {{ previousTier }} {{ unit }}",
|
||||||
|
"startingAtPriceUnit": "Starting at {{price}}/{{unit}}",
|
||||||
|
"priceUnit": "{{price}}/{{unit}}",
|
||||||
|
"forEveryUnit": "for every {{ unit }}",
|
||||||
|
"setupFee": "plus a {{ setupFee }} setup fee",
|
||||||
|
"perUnitIncluded": "({{included}} included)",
|
||||||
|
"featuresLabel": "Features",
|
||||||
|
"detailsLabel": "Details",
|
||||||
|
"planPickerLabel": "Pick your preferred plan",
|
||||||
|
"planCardLabel": "Manage your Plan",
|
||||||
|
"planPickerAlertErrorTitle": "Error requesting checkout",
|
||||||
|
"planPickerAlertErrorDescription": "There was an error requesting checkout. Please try again later.",
|
||||||
|
"subscriptionCancelled": "Subscription Cancelled",
|
||||||
|
"cancelSubscriptionDate": "Your subscription will be cancelled at the end of the period",
|
||||||
|
"noPlanChosen": "Please choose a plan",
|
||||||
|
"noIntervalPlanChosen": "Please choose a billing interval",
|
||||||
|
"status": {
|
||||||
|
"free": {
|
||||||
|
"badge": "Free Plan",
|
||||||
|
"heading": "You are currently on the Free Plan",
|
||||||
|
"description": "You're on a free plan. You can upgrade to a paid plan at any time."
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"badge": "Active",
|
||||||
|
"heading": "Your subscription is active",
|
||||||
|
"description": "Your subscription is active. You can manage your subscription and billing in the Customer Portal."
|
||||||
|
},
|
||||||
|
"trialing": {
|
||||||
|
"badge": "Trial",
|
||||||
|
"heading": "You're on a trial",
|
||||||
|
"description": "You can enjoy the benefits of plan until the trial ends"
|
||||||
|
},
|
||||||
|
"past_due": {
|
||||||
|
"badge": "Past Due",
|
||||||
|
"heading": "Your invoice is past due",
|
||||||
|
"description": "Your invoice is past due. Please update your payment method."
|
||||||
|
},
|
||||||
|
"canceled": {
|
||||||
|
"badge": "Canceled",
|
||||||
|
"heading": "Your subscription is canceled",
|
||||||
|
"description": "Your subscription is canceled. It is scheduled to end at end of the billing period."
|
||||||
|
},
|
||||||
|
"unpaid": {
|
||||||
|
"badge": "Unpaid",
|
||||||
|
"heading": "Your invoice is unpaid",
|
||||||
|
"description": "Your invoice is unpaid. Please update your payment method."
|
||||||
|
},
|
||||||
|
"incomplete": {
|
||||||
|
"badge": "Incomplete",
|
||||||
|
"heading": "We're waiting for your payment",
|
||||||
|
"description": "We're waiting for your payment to go through. Please bear with us."
|
||||||
|
},
|
||||||
|
"incomplete_expired": {
|
||||||
|
"badge": "Expired",
|
||||||
|
"heading": "Your payment has expired",
|
||||||
|
"description": "Your payment has expired. Please update your payment method."
|
||||||
|
},
|
||||||
|
"paused": {
|
||||||
|
"badge": "Paused",
|
||||||
|
"heading": "Your subscription is paused",
|
||||||
|
"description": "Your subscription is paused. You can resume it at any time."
|
||||||
|
},
|
||||||
|
"succeeded": {
|
||||||
|
"badge": "Succeeded",
|
||||||
|
"heading": "Your payment was successful",
|
||||||
|
"description": "Your payment was successful. Thank you for subscribing!"
|
||||||
|
},
|
||||||
|
"pending": {
|
||||||
|
"badge": "Pending",
|
||||||
|
"heading": "Your payment is pending",
|
||||||
|
"description": "Your payment is pending. Please bear with us."
|
||||||
|
},
|
||||||
|
"failed": {
|
||||||
|
"badge": "Failed",
|
||||||
|
"heading": "Your payment failed",
|
||||||
|
"description": "Your payment failed. Please update your payment method."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
public/locales/et/common.json
Normal file
96
public/locales/et/common.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"homeTabLabel": "Home",
|
||||||
|
"homeTabDescription": "Welcome to your home page",
|
||||||
|
"accountMembers": "Team Members",
|
||||||
|
"membersTabDescription": "Here you can manage the members of your team.",
|
||||||
|
"billingTabLabel": "Billing",
|
||||||
|
"billingTabDescription": "Manage your billing and subscription",
|
||||||
|
"dashboardTabLabel": "Dashboard",
|
||||||
|
"settingsTabLabel": "Settings",
|
||||||
|
"profileSettingsTabLabel": "Profile",
|
||||||
|
"subscriptionSettingsTabLabel": "Subscription",
|
||||||
|
"dashboardTabDescription": "An overview of your account's activity and performance across all your projects.",
|
||||||
|
"settingsTabDescription": "Manage your settings and preferences.",
|
||||||
|
"emailAddress": "Email Address",
|
||||||
|
"password": "Password",
|
||||||
|
"modalConfirmationQuestion": "Are you sure you want to continue?",
|
||||||
|
"imageInputLabel": "Click here to upload an image",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"clear": "Clear",
|
||||||
|
"notFound": "Not Found",
|
||||||
|
"backToHomePage": "Back to Home Page",
|
||||||
|
"goBack": "Go Back",
|
||||||
|
"genericServerError": "Sorry, something went wrong.",
|
||||||
|
"genericServerErrorHeading": "Sorry, something went wrong while processing your request. Please contact us if the issue persists.",
|
||||||
|
"pageNotFound": "Sorry, this page does not exist.",
|
||||||
|
"pageNotFoundSubHeading": "Apologies, the page you were looking for was not found",
|
||||||
|
"genericError": "Sorry, something went wrong.",
|
||||||
|
"genericErrorSubHeading": "Apologies, an error occurred while processing your request. Please contact us if the issue persists.",
|
||||||
|
"anonymousUser": "Anonymous",
|
||||||
|
"tryAgain": "Try Again",
|
||||||
|
"theme": "Theme",
|
||||||
|
"lightTheme": "Light",
|
||||||
|
"darkTheme": "Dark",
|
||||||
|
"systemTheme": "System",
|
||||||
|
"expandSidebar": "Expand Sidebar",
|
||||||
|
"collapseSidebar": "Collapse Sidebar",
|
||||||
|
"documentation": "Documentation",
|
||||||
|
"getStarted": "Get Started",
|
||||||
|
"getStartedWithPlan": "Get Started with {{plan}}",
|
||||||
|
"retry": "Retry",
|
||||||
|
"contactUs": "Contact Us",
|
||||||
|
"loading": "Loading. Please wait...",
|
||||||
|
"yourAccounts": "Your Accounts",
|
||||||
|
"continue": "Continue",
|
||||||
|
"skip": "Skip",
|
||||||
|
"signedInAs": "Signed in as",
|
||||||
|
"pageOfPages": "Page {{page}} of {{total}}",
|
||||||
|
"noData": "No data available",
|
||||||
|
"pageNotFoundHeading": "Ouch! :|",
|
||||||
|
"errorPageHeading": "Ouch! :|",
|
||||||
|
"notifications": "Notifications",
|
||||||
|
"noNotifications": "No notifications",
|
||||||
|
"justNow": "Just now",
|
||||||
|
"newVersionAvailable": "New version available",
|
||||||
|
"newVersionAvailableDescription": "A new version of the app is available. It is recommended to refresh the page to get the latest updates and avoid any issues.",
|
||||||
|
"newVersionSubmitButton": "Reload and Update",
|
||||||
|
"back": "Back",
|
||||||
|
"routes": {
|
||||||
|
"home": "Home",
|
||||||
|
"account": "Account",
|
||||||
|
"members": "Members",
|
||||||
|
"billing": "Billing",
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"settings": "Settings",
|
||||||
|
"profile": "Profile",
|
||||||
|
"application": "Application"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"owner": {
|
||||||
|
"label": "Owner"
|
||||||
|
},
|
||||||
|
"member": {
|
||||||
|
"label": "Member"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otp": {
|
||||||
|
"requestVerificationCode": "Request Verification Code",
|
||||||
|
"requestVerificationCodeDescription": "We must verify your identity to continue with this action. We'll send a verification code to the email address {{email}}.",
|
||||||
|
"sendingCode": "Sending Code...",
|
||||||
|
"sendVerificationCode": "Send Verification Code",
|
||||||
|
"enterVerificationCode": "Enter Verification Code",
|
||||||
|
"codeSentToEmail": "We've sent a verification code to the email address {{email}}.",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"enterCodeFromEmail": "Enter the 6-digit code we sent to your email.",
|
||||||
|
"verifying": "Verifying...",
|
||||||
|
"verifyCode": "Verify Code",
|
||||||
|
"requestNewCode": "Request New Code",
|
||||||
|
"errorSendingCode": "Error sending code. Please try again."
|
||||||
|
},
|
||||||
|
"cookieBanner": {
|
||||||
|
"title": "Hey, we use cookies 🍪",
|
||||||
|
"description": "This website uses cookies to ensure you get the best experience on our website.",
|
||||||
|
"reject": "Reject",
|
||||||
|
"accept": "Accept"
|
||||||
|
}
|
||||||
|
}
|
||||||
40
public/locales/et/marketing.json
Normal file
40
public/locales/et/marketing.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"blog": "Blog",
|
||||||
|
"blogSubtitle": "News and updates about the platform",
|
||||||
|
"documentation": "Documentation",
|
||||||
|
"documentationSubtitle": "Tutorials and guide to get started with the platform",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"faqSubtitle": "Frequently asked questions about the platform",
|
||||||
|
"pricing": "Pricing",
|
||||||
|
"pricingSubtitle": "Pricing plans and payment options",
|
||||||
|
"backToBlog": "Back to blog",
|
||||||
|
"noPosts": "No posts found",
|
||||||
|
"blogPaginationNext": "Next Page",
|
||||||
|
"blogPaginationPrevious": "Previous Page",
|
||||||
|
"readMore": "Read more",
|
||||||
|
"contactFaq": "If you have any questions, please contact us",
|
||||||
|
"contact": "Contact",
|
||||||
|
"about": "About",
|
||||||
|
"product": "Product",
|
||||||
|
"legal": "Legal",
|
||||||
|
"termsOfService": "Terms of Service",
|
||||||
|
"termsOfServiceDescription": "Our terms and conditions",
|
||||||
|
"cookiePolicy": "Cookie Policy",
|
||||||
|
"cookiePolicyDescription": "Our cookie policy and how we use them",
|
||||||
|
"privacyPolicy": "Privacy Policy",
|
||||||
|
"privacyPolicyDescription": "Our privacy policy and how we use your data",
|
||||||
|
"contactDescription": "Contact us for any questions or feedback",
|
||||||
|
"contactHeading": "Send us a message",
|
||||||
|
"contactSubheading": "We will get back to you as soon as possible",
|
||||||
|
"contactName": "Your Name",
|
||||||
|
"contactEmail": "Your Email",
|
||||||
|
"contactMessage": "Your Message",
|
||||||
|
"sendMessage": "Send Message",
|
||||||
|
"contactSuccess": "Your message has been sent successfully",
|
||||||
|
"contactError": "An error occurred while sending your message",
|
||||||
|
"contactSuccessDescription": "We have received your message and will get back to you as soon as possible",
|
||||||
|
"contactErrorDescription": "An error occurred while sending your message. Please try again later",
|
||||||
|
"footerDescription": "Here you can add a description about your company or product",
|
||||||
|
"copyright": "© Copyright {{year}} {{product}}. All Rights Reserved.",
|
||||||
|
"heroSubtitle": "Lihtne, mugav ja kiire ülevaade Sinu tervise seisundist"
|
||||||
|
}
|
||||||
163
public/locales/et/teams.json
Normal file
163
public/locales/et/teams.json
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"pageTitle": "Home"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"pageTitle": "Settings",
|
||||||
|
"pageDescription": "Manage your Team details",
|
||||||
|
"teamLogo": "Team Logo",
|
||||||
|
"teamLogoDescription": "Update your team's logo to make it easier to identify",
|
||||||
|
"teamName": "Team Name",
|
||||||
|
"teamNameDescription": "Update your team's name",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneDescription": "This section contains actions that are irreversible"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"pageTitle": "Members"
|
||||||
|
},
|
||||||
|
"billing": {
|
||||||
|
"pageTitle": "Billing"
|
||||||
|
},
|
||||||
|
"yourTeams": "Your Teams ({{teamsCount}})",
|
||||||
|
"createTeam": "Create a Team",
|
||||||
|
"creatingTeam": "Creating Team...",
|
||||||
|
"personalAccount": "Personal Account",
|
||||||
|
"searchAccount": "Search Account...",
|
||||||
|
"membersTabLabel": "Members",
|
||||||
|
"memberName": "Name",
|
||||||
|
"youLabel": "You",
|
||||||
|
"emailLabel": "Email",
|
||||||
|
"roleLabel": "Role",
|
||||||
|
"primaryOwnerLabel": "Primary Owner",
|
||||||
|
"joinedAtLabel": "Joined at",
|
||||||
|
"invitedAtLabel": "Invited at",
|
||||||
|
"inviteMembersPageSubheading": "Invite members to your Team",
|
||||||
|
"createTeamModalHeading": "Create Team",
|
||||||
|
"createTeamModalDescription": "Create a new Team to manage your projects and members.",
|
||||||
|
"teamNameLabel": "Team Name",
|
||||||
|
"teamNameDescription": "Your team name should be unique and descriptive",
|
||||||
|
"createTeamSubmitLabel": "Create Team",
|
||||||
|
"createTeamSuccess": "Team created successfully",
|
||||||
|
"createTeamError": "Team not created. Please try again.",
|
||||||
|
"createTeamLoading": "Creating team...",
|
||||||
|
"settingsPageLabel": "General",
|
||||||
|
"createTeamDropdownLabel": "New team",
|
||||||
|
"changeRole": "Change Role",
|
||||||
|
"removeMember": "Remove from Account",
|
||||||
|
"inviteMembersSuccess": "Members invited successfully!",
|
||||||
|
"inviteMembersError": "Sorry, we encountered an error! Please try again",
|
||||||
|
"inviteMembersLoading": "Inviting members...",
|
||||||
|
"removeInviteButtonLabel": "Remove invite",
|
||||||
|
"addAnotherMemberButtonLabel": "Add another one",
|
||||||
|
"inviteMembersButtonLabel": "Send Invites",
|
||||||
|
"removeMemberModalHeading": "You are removing this user",
|
||||||
|
"removeMemberModalDescription": "Remove this member from the team. They will no longer have access to the team.",
|
||||||
|
"removeMemberSuccessMessage": "Member removed successfully",
|
||||||
|
"removeMemberErrorMessage": "Sorry, we encountered an error. Please try again",
|
||||||
|
"removeMemberErrorHeading": "Sorry, we couldn't remove the selected member.",
|
||||||
|
"removeMemberLoadingMessage": "Removing member...",
|
||||||
|
"removeMemberSubmitLabel": "Remove User from Team",
|
||||||
|
"chooseDifferentRoleError": "Role is the same as the current one",
|
||||||
|
"updateRole": "Update Role",
|
||||||
|
"updateRoleLoadingMessage": "Updating role...",
|
||||||
|
"updateRoleSuccessMessage": "Role updated successfully",
|
||||||
|
"updatingRoleErrorMessage": "Sorry, we encountered an error. Please try again.",
|
||||||
|
"updateMemberRoleModalHeading": "Update Member's Role",
|
||||||
|
"updateMemberRoleModalDescription": "Change the role of the selected member. The role determines the permissions of the member.",
|
||||||
|
"roleMustBeDifferent": "Role must be different from the current one",
|
||||||
|
"memberRoleInputLabel": "Member role",
|
||||||
|
"updateRoleDescription": "Pick a role for this member.",
|
||||||
|
"updateRoleSubmitLabel": "Update Role",
|
||||||
|
"transferOwnership": "Transfer Ownership",
|
||||||
|
"transferOwnershipDescription": "Transfer ownership of the team to another member.",
|
||||||
|
"transferOwnershipInputLabel": "Please type TRANSFER to confirm the transfer of ownership.",
|
||||||
|
"transferOwnershipInputDescription": "By transferring ownership, you will no longer be the primary owner of the team.",
|
||||||
|
"deleteInvitation": "Delete Invitation",
|
||||||
|
"deleteInvitationDialogDescription": "You are about to delete the invitation. The user will no longer be able to join the team.",
|
||||||
|
"deleteInviteSuccessMessage": "Invite deleted successfully",
|
||||||
|
"deleteInviteErrorMessage": "Invite not deleted. Please try again.",
|
||||||
|
"deleteInviteLoadingMessage": "Deleting invite. Please wait...",
|
||||||
|
"confirmDeletingMemberInvite": "You are deleting the invite to <b>{{ email }}</b>",
|
||||||
|
"transferOwnershipDisclaimer": "You are transferring ownership of the selected team to <b>{{ member }}</b>.",
|
||||||
|
"transferringOwnership": "Transferring ownership...",
|
||||||
|
"transferOwnershipSuccess": "Ownership successfully transferred",
|
||||||
|
"transferOwnershipError": "Sorry, we could not transfer ownership to the selected member. Please try again.",
|
||||||
|
"deleteInviteSubmitLabel": "Delete Invite",
|
||||||
|
"youBadgeLabel": "You",
|
||||||
|
"updateTeamLoadingMessage": "Updating Team...",
|
||||||
|
"updateTeamSuccessMessage": "Team successfully updated",
|
||||||
|
"updateTeamErrorMessage": "Could not update Team. Please try again.",
|
||||||
|
"updateLogoErrorMessage": "Could not update Logo. Please try again.",
|
||||||
|
"teamNameInputLabel": "Team Name",
|
||||||
|
"teamLogoInputHeading": "Upload your team's Logo",
|
||||||
|
"teamLogoInputSubheading": "Please choose a photo to upload as your team logo.",
|
||||||
|
"updateTeamSubmitLabel": "Update Team",
|
||||||
|
"inviteMembersHeading": "Invite Members to your Team",
|
||||||
|
"inviteMembersDescription": "Invite members to your team by entering their email and role.",
|
||||||
|
"emailPlaceholder": "member@email.com",
|
||||||
|
"membersPageHeading": "Members",
|
||||||
|
"inviteMembersButton": "Invite Members",
|
||||||
|
"invitingMembers": "Inviting members...",
|
||||||
|
"inviteMembersSuccessMessage": "Members invited successfully",
|
||||||
|
"inviteMembersErrorMessage": "Sorry, members could not be invited. Please try again.",
|
||||||
|
"pendingInvitesHeading": "Pending Invites",
|
||||||
|
"pendingInvitesDescription": " Here you can manage the pending invitations to your team.",
|
||||||
|
"noPendingInvites": "No pending invites found",
|
||||||
|
"loadingMembers": "Loading members...",
|
||||||
|
"loadMembersError": "Sorry, we couldn't fetch your team's members.",
|
||||||
|
"loadInvitedMembersError": "Sorry, we couldn't fetch your team's invited members.",
|
||||||
|
"loadingInvitedMembers": "Loading invited members...",
|
||||||
|
"invitedBadge": "Invited",
|
||||||
|
"duplicateInviteEmailError": "You have already entered this email address",
|
||||||
|
"invitingOwnAccountError": "Hey, that's your email!",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneSubheading": "Delete or leave your team",
|
||||||
|
"deleteTeam": "Delete Team",
|
||||||
|
"deleteTeamDescription": "This action cannot be undone. All data associated with this team will be deleted.",
|
||||||
|
"deletingTeam": "Deleting team",
|
||||||
|
"deleteTeamModalHeading": "Deleting Team",
|
||||||
|
"deletingTeamDescription": "You are about to delete the team {{ teamName }}. This action cannot be undone.",
|
||||||
|
"deleteTeamInputField": "Type the name of the team to confirm",
|
||||||
|
"leaveTeam": "Leave Team",
|
||||||
|
"leavingTeamModalHeading": "Leaving Team",
|
||||||
|
"leavingTeamModalDescription": "You are about to leave this team. You will no longer have access to it.",
|
||||||
|
"leaveTeamDescription": "Click the button below to leave the team. Remember, you will no longer have access to it and will need to be re-invited to join.",
|
||||||
|
"deleteTeamDisclaimer": "You are deleting the team {{ teamName }}. This action cannot be undone.",
|
||||||
|
"leaveTeamDisclaimer": "You are leaving the team {{ teamName }}. You will no longer have access to it.",
|
||||||
|
"deleteTeamErrorHeading": "Sorry, we couldn't delete your team.",
|
||||||
|
"leaveTeamErrorHeading": "Sorry, we couldn't leave your team.",
|
||||||
|
"searchMembersPlaceholder": "Search members",
|
||||||
|
"createTeamErrorHeading": "Sorry, we couldn't create your team.",
|
||||||
|
"createTeamErrorMessage": "We encountered an error creating your team. Please try again.",
|
||||||
|
"transferTeamErrorHeading": "Sorry, we couldn't transfer ownership of your team.",
|
||||||
|
"transferTeamErrorMessage": "We encountered an error transferring ownership of your team. Please try again.",
|
||||||
|
"updateRoleErrorHeading": "Sorry, we couldn't update the role of the selected member.",
|
||||||
|
"updateRoleErrorMessage": "We encountered an error updating the role of the selected member. Please try again.",
|
||||||
|
"searchInvitations": "Search Invitations",
|
||||||
|
"updateInvitation": "Update Invitation",
|
||||||
|
"removeInvitation": "Remove Invitation",
|
||||||
|
"acceptInvitation": "Accept Invitation",
|
||||||
|
"renewInvitation": "Renew Invitation",
|
||||||
|
"resendInvitation": "Resend Invitation",
|
||||||
|
"expiresAtLabel": "Expires at",
|
||||||
|
"expired": "Expired",
|
||||||
|
"active": "Active",
|
||||||
|
"inviteStatus": "Status",
|
||||||
|
"inviteNotFoundOrExpired": "Invite not found or expired",
|
||||||
|
"inviteNotFoundOrExpiredDescription": "The invite you are looking for is either expired or does not exist. Please contact the team owner to renew the invite.",
|
||||||
|
"backToHome": "Back to Home",
|
||||||
|
"renewInvitationDialogDescription": "You are about to renew the invitation to {{ email }}. The user will be able to join the team.",
|
||||||
|
"renewInvitationErrorTitle": "Sorry, we couldn't renew the invitation.",
|
||||||
|
"renewInvitationErrorDescription": "We encountered an error renewing the invitation. Please try again.",
|
||||||
|
"signInWithDifferentAccount": "Sign in with a different account",
|
||||||
|
"signInWithDifferentAccountDescription": "If you wish to accept the invitation with a different account, please sign out and back in with the account you wish to use.",
|
||||||
|
"acceptInvitationHeading": "Accept Invitation to join {{accountName}}",
|
||||||
|
"acceptInvitationDescription": "You have been invited to join the team {{accountName}}. If you wish to accept the invitation, please click the button below.",
|
||||||
|
"continueAs": "Continue as {{email}}",
|
||||||
|
"joinTeamAccount": "Join Team",
|
||||||
|
"joiningTeam": "Joining team...",
|
||||||
|
"leaveTeamInputLabel": "Please type LEAVE to confirm leaving the team.",
|
||||||
|
"leaveTeamInputDescription": "By leaving the team, you will no longer have access to it.",
|
||||||
|
"reservedNameError": "This name is reserved. Please choose a different one.",
|
||||||
|
"specialCharactersError": "This name cannot contain special characters. Please choose a different one."
|
||||||
|
}
|
||||||
117
public/locales/ru/account.json
Normal file
117
public/locales/ru/account.json
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"accountTabLabel": "Account Settings",
|
||||||
|
"accountTabDescription": "Manage your account settings",
|
||||||
|
"homePage": "Home",
|
||||||
|
"billingTab": "Billing",
|
||||||
|
"settingsTab": "Settings",
|
||||||
|
"multiFactorAuth": "Multi-Factor Authentication",
|
||||||
|
"multiFactorAuthDescription": "Set up Multi-Factor Authentication method to further secure your account",
|
||||||
|
"updateProfileSuccess": "Profile successfully updated",
|
||||||
|
"updateProfileError": "Encountered an error. Please try again",
|
||||||
|
"updatePasswordSuccess": "Password update request successful",
|
||||||
|
"updatePasswordSuccessMessage": "Your password has been successfully updated!",
|
||||||
|
"updatePasswordError": "Encountered an error. Please try again",
|
||||||
|
"updatePasswordLoading": "Updating password...",
|
||||||
|
"updateProfileLoading": "Updating profile...",
|
||||||
|
"name": "Your Name",
|
||||||
|
"nameDescription": "Update your name to be displayed on your profile",
|
||||||
|
"emailLabel": "Email Address",
|
||||||
|
"accountImage": "Your Profile Picture",
|
||||||
|
"accountImageDescription": "Please choose a photo to upload as your profile picture.",
|
||||||
|
"profilePictureHeading": "Upload a Profile Picture",
|
||||||
|
"profilePictureSubheading": "Choose a photo to upload as your profile picture.",
|
||||||
|
"updateProfileSubmitLabel": "Update Profile",
|
||||||
|
"updatePasswordCardTitle": "Update your Password",
|
||||||
|
"updatePasswordCardDescription": "Update your password to keep your account secure.",
|
||||||
|
"currentPassword": "Current Password",
|
||||||
|
"newPassword": "New Password",
|
||||||
|
"repeatPassword": "Repeat New Password",
|
||||||
|
"repeatPasswordDescription": "Please repeat your new password to confirm it",
|
||||||
|
"yourPassword": "Your Password",
|
||||||
|
"updatePasswordSubmitLabel": "Update Password",
|
||||||
|
"updateEmailCardTitle": "Update your Email",
|
||||||
|
"updateEmailCardDescription": "Update your email address you use to login to your account",
|
||||||
|
"newEmail": "Your New Email",
|
||||||
|
"repeatEmail": "Repeat Email",
|
||||||
|
"updateEmailSubmitLabel": "Update Email Address",
|
||||||
|
"updateEmailSuccess": "Email update request successful",
|
||||||
|
"updateEmailSuccessMessage": "We sent you an email to confirm your new email address. Please check your inbox and click on the link to confirm your new email address.",
|
||||||
|
"updateEmailLoading": "Updating your email...",
|
||||||
|
"updateEmailError": "Email not updated. Please try again",
|
||||||
|
"passwordNotMatching": "Passwords do not match. Make sure you're using the correct password",
|
||||||
|
"emailNotMatching": "Emails do not match. Make sure you're using the correct email",
|
||||||
|
"passwordNotChanged": "Your password has not changed",
|
||||||
|
"emailsNotMatching": "Emails do not match. Make sure you're using the correct email",
|
||||||
|
"cannotUpdatePassword": "You cannot update your password because your account is not linked to any.",
|
||||||
|
"setupMfaButtonLabel": "Setup a new Factor",
|
||||||
|
"multiFactorSetupErrorHeading": "Setup Failed",
|
||||||
|
"multiFactorSetupErrorDescription": "Sorry, there was an error while setting up your factor. Please try again.",
|
||||||
|
"multiFactorAuthHeading": "Secure your account with Multi-Factor Authentication",
|
||||||
|
"multiFactorModalHeading": "Use your authenticator app to scan the QR code below. Then enter the code generated.",
|
||||||
|
"factorNameLabel": "A memorable name to identify this factor",
|
||||||
|
"factorNameHint": "Use an easy-to-remember name to easily identify this factor in the future. Ex. iPhone 14",
|
||||||
|
"factorNameSubmitLabel": "Set factor name",
|
||||||
|
"unenrollTooltip": "Unenroll this factor",
|
||||||
|
"unenrollingFactor": "Unenrolling factor...",
|
||||||
|
"unenrollFactorSuccess": "Factor successfully unenrolled",
|
||||||
|
"unenrollFactorError": "Unenrolling factor failed",
|
||||||
|
"factorsListError": "Error loading factors list",
|
||||||
|
"factorsListErrorDescription": "Sorry, we couldn't load the factors list. Please try again.",
|
||||||
|
"factorName": "Factor Name",
|
||||||
|
"factorType": "Type",
|
||||||
|
"factorStatus": "Status",
|
||||||
|
"mfaEnabledSuccessTitle": "Multi-Factor authentication is enabled",
|
||||||
|
"mfaEnabledSuccessDescription": "Congratulations! You have successfully enrolled in the multi factor authentication process. You will now be able to access your account with a combination of your password and an authentication code sent to your phone number.",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"addEmailAddress": "Add Email address",
|
||||||
|
"verifyActivationCodeDescription": "Enter the 6-digit code generated by your authenticator app in the field above",
|
||||||
|
"loadingFactors": "Loading factors...",
|
||||||
|
"enableMfaFactor": "Enable Factor",
|
||||||
|
"disableMfaFactor": "Disable Factor",
|
||||||
|
"qrCodeErrorHeading": "QR Code Error",
|
||||||
|
"qrCodeErrorDescription": "Sorry, we weren't able to generate the QR code",
|
||||||
|
"multiFactorSetupSuccess": "Factor successfully enrolled",
|
||||||
|
"submitVerificationCode": "Submit Verification Code",
|
||||||
|
"mfaEnabledSuccessAlert": "Multi-Factor authentication is enabled",
|
||||||
|
"verifyingCode": "Verifying code...",
|
||||||
|
"invalidVerificationCodeHeading": "Invalid Verification Code",
|
||||||
|
"invalidVerificationCodeDescription": "The verification code you entered is invalid. Please try again.",
|
||||||
|
"unenrollFactorModalHeading": "Unenroll Factor",
|
||||||
|
"unenrollFactorModalDescription": "You're about to unenroll this factor. You will not be able to use it to login to your account.",
|
||||||
|
"unenrollFactorModalBody": "You're about to unenroll this factor. You will not be able to use it to login to your account.",
|
||||||
|
"unenrollFactorModalButtonLabel": "Yes, unenroll factor",
|
||||||
|
"selectFactor": "Choose a factor to verify your identity",
|
||||||
|
"disableMfa": "Disable Multi-Factor Authentication",
|
||||||
|
"disableMfaButtonLabel": "Disable MFA",
|
||||||
|
"confirmDisableMfaButtonLabel": "Yes, disable MFA",
|
||||||
|
"disablingMfa": "Disabling Multi-Factor Authentication. Please wait...",
|
||||||
|
"disableMfaSuccess": "Multi-Factor Authentication successfully disabled",
|
||||||
|
"disableMfaError": "Sorry, we encountered an error. MFA has not been disabled.",
|
||||||
|
"sendingEmailVerificationLink": "Sending Email...",
|
||||||
|
"sendEmailVerificationLinkSuccess": "Verification link successfully sent",
|
||||||
|
"sendEmailVerificationLinkError": "Sorry, we weren't able to send you the email",
|
||||||
|
"sendVerificationLinkSubmitLabel": "Send Verification Link",
|
||||||
|
"sendVerificationLinkSuccessLabel": "Email sent! Check your Inbox",
|
||||||
|
"verifyEmailAlertHeading": "Please verify your email to enable MFA",
|
||||||
|
"verificationLinkAlertDescription": "Your email is not yet verified. Please verify your email to be able to set up Multi-Factor Authentication.",
|
||||||
|
"authFactorName": "Factor Name (optional)",
|
||||||
|
"authFactorNameHint": "Assign a name that helps you remember the phone number used",
|
||||||
|
"loadingUser": "Loading user details. Please wait...",
|
||||||
|
"linkPhoneNumber": "Link Phone Number",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneDescription": "Some actions cannot be undone. Please be careful.",
|
||||||
|
"deleteAccount": "Delete your Account",
|
||||||
|
"deletingAccount": "Deleting account. Please wait...",
|
||||||
|
"deleteAccountDescription": "This will delete your account and the accounts you own. Furthermore, we will immediately cancel any active subscriptions. This action cannot be undone.",
|
||||||
|
"deleteProfileConfirmationInputLabel": "Type DELETE to confirm",
|
||||||
|
"deleteAccountErrorHeading": "Sorry, we couldn't delete your account",
|
||||||
|
"needsReauthentication": "Reauthentication Required",
|
||||||
|
"needsReauthenticationDescription": "You need to reauthenticate to change your password. Please sign out and sign in again to change your password.",
|
||||||
|
"language": "Language",
|
||||||
|
"languageDescription": "Choose your preferred language",
|
||||||
|
"noTeamsYet": "You don't have any teams yet.",
|
||||||
|
"createTeam": "Create a team to get started.",
|
||||||
|
"createTeamButtonLabel": "Create a Team",
|
||||||
|
"createCompanyAccount": "Create Company Account",
|
||||||
|
"requestCompanyAccount": "Request Company Account"
|
||||||
|
}
|
||||||
90
public/locales/ru/auth.json
Normal file
90
public/locales/ru/auth.json
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
{
|
||||||
|
"signUpHeading": "Create an account",
|
||||||
|
"signUp": "Sign Up",
|
||||||
|
"signUpSubheading": "Fill the form below to create an account.",
|
||||||
|
"signInHeading": "Sign in to your account",
|
||||||
|
"signInSubheading": "Welcome back! Please enter your details",
|
||||||
|
"signIn": "Sign In",
|
||||||
|
"getStarted": "Get started",
|
||||||
|
"updatePassword": "Update Password",
|
||||||
|
"signOut": "Sign out",
|
||||||
|
"signingIn": "Signing in...",
|
||||||
|
"signingUp": "Signing up...",
|
||||||
|
"doNotHaveAccountYet": "Do not have an account yet?",
|
||||||
|
"alreadyHaveAnAccount": "Already have an account?",
|
||||||
|
"signUpToAcceptInvite": "Please sign in/up to accept the invite",
|
||||||
|
"clickToAcceptAs": "Click the button below to accept the invite with as <b>{{email}}</b>",
|
||||||
|
"acceptInvite": "Accept invite",
|
||||||
|
"acceptingInvite": "Accepting Invite...",
|
||||||
|
"acceptInviteSuccess": "Invite successfully accepted",
|
||||||
|
"acceptInviteError": "Error encountered while accepting invite",
|
||||||
|
"acceptInviteWithDifferentAccount": "Want to accept the invite with a different account?",
|
||||||
|
"alreadyHaveAccountStatement": "I already have an account, I want to sign in instead",
|
||||||
|
"doNotHaveAccountStatement": "I do not have an account, I want to sign up instead",
|
||||||
|
"signInWithProvider": "Sign in with {{provider}}",
|
||||||
|
"signInWithPhoneNumber": "Sign in with Phone Number",
|
||||||
|
"signInWithEmail": "Sign in with Email",
|
||||||
|
"signUpWithEmail": "Sign up with Email",
|
||||||
|
"passwordHint": "Ensure it's at least 8 characters",
|
||||||
|
"repeatPasswordHint": "Type your password again",
|
||||||
|
"repeatPassword": "Repeat password",
|
||||||
|
"passwordForgottenQuestion": "Password forgotten?",
|
||||||
|
"passwordResetLabel": "Reset Password",
|
||||||
|
"passwordResetSubheading": "Enter your email address below. You will receive a link to reset your password.",
|
||||||
|
"passwordResetSuccessMessage": "Check your Inbox! We emailed you a link for resetting your Password.",
|
||||||
|
"passwordRecoveredQuestion": "Password recovered?",
|
||||||
|
"passwordLengthError": "Please provide a password with at least 6 characters",
|
||||||
|
"sendEmailLink": "Send Email Link",
|
||||||
|
"sendingEmailLink": "Sending Email Link...",
|
||||||
|
"sendLinkSuccessDescription": "Check your email, we just sent you a link. Follow the link to sign in.",
|
||||||
|
"sendLinkSuccess": "We sent you a link by email",
|
||||||
|
"sendLinkSuccessToast": "Link successfully sent",
|
||||||
|
"getNewLink": "Get a new link",
|
||||||
|
"verifyCodeHeading": "Verify your account",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"verificationCodeHint": "Enter the code we sent you by SMS",
|
||||||
|
"verificationCodeSubmitButtonLabel": "Submit Verification Code",
|
||||||
|
"sendingMfaCode": "Sending Verification Code...",
|
||||||
|
"verifyingMfaCode": "Verifying code...",
|
||||||
|
"sendMfaCodeError": "Sorry, we couldn't send you a verification code",
|
||||||
|
"verifyMfaCodeSuccess": "Code verified! Signing you in...",
|
||||||
|
"verifyMfaCodeError": "Ops! It looks like the code is not correct",
|
||||||
|
"reauthenticate": "Reauthenticate",
|
||||||
|
"reauthenticateDescription": "For security reasons, we need you to re-authenticate",
|
||||||
|
"errorAlertHeading": "Sorry, we could not authenticate you",
|
||||||
|
"emailConfirmationAlertHeading": "We sent you a confirmation email.",
|
||||||
|
"emailConfirmationAlertBody": "Welcome! Please check your email and click the link to verify your account.",
|
||||||
|
"resendLink": "Resend link",
|
||||||
|
"resendLinkSuccessDescription": "We sent you a new link to your email! Follow the link to sign in.",
|
||||||
|
"resendLinkSuccess": "Check your email!",
|
||||||
|
"authenticationErrorAlertHeading": "Authentication Error",
|
||||||
|
"authenticationErrorAlertBody": "Sorry, we could not authenticate you. Please try again.",
|
||||||
|
"sendEmailCode": "Get code to your Email",
|
||||||
|
"sendingEmailCode": "Sending code...",
|
||||||
|
"resetPasswordError": "Sorry, we could not reset your password. Please try again.",
|
||||||
|
"emailPlaceholder": "your@email.com",
|
||||||
|
"inviteAlertHeading": "You have been invited to join a team",
|
||||||
|
"inviteAlertBody": "Please sign in or sign up to accept the invite and join the team.",
|
||||||
|
"acceptTermsAndConditions": "I accept the <TermsOfServiceLink /> and <PrivacyPolicyLink />",
|
||||||
|
"termsOfService": "Terms of Service",
|
||||||
|
"privacyPolicy": "Privacy Policy",
|
||||||
|
"orContinueWith": "Or continue with",
|
||||||
|
"redirecting": "You're in! Please wait...",
|
||||||
|
"errors": {
|
||||||
|
"Invalid login credentials": "The credentials entered are invalid",
|
||||||
|
"User already registered": "This credential is already in use. Please try with another one.",
|
||||||
|
"Email not confirmed": "Please confirm your email address before signing in",
|
||||||
|
"default": "We have encountered an error. Please ensure you have a working internet connection and try again",
|
||||||
|
"generic": "Sorry, we weren't able to authenticate you. Please try again.",
|
||||||
|
"link": "Sorry, we encountered an error while sending your link. Please try again.",
|
||||||
|
"codeVerifierMismatch": "It looks like you're trying to sign in using a different browser than the one you used to request the sign in link. Please try again using the same browser.",
|
||||||
|
"minPasswordLength": "Password must be at least 8 characters long",
|
||||||
|
"passwordsDoNotMatch": "The passwords do not match",
|
||||||
|
"minPasswordNumbers": "Password must contain at least one number",
|
||||||
|
"minPasswordSpecialChars": "Password must contain at least one special character",
|
||||||
|
"uppercasePassword": "Password must contain at least one uppercase letter",
|
||||||
|
"insufficient_aal": "Please sign-in with your current multi-factor authentication to perform this action",
|
||||||
|
"otp_expired": "The email link has expired. Please try again.",
|
||||||
|
"same_password": "The password cannot be the same as the current password"
|
||||||
|
}
|
||||||
|
}
|
||||||
120
public/locales/ru/billing.json
Normal file
120
public/locales/ru/billing.json
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
{
|
||||||
|
"subscriptionTabSubheading": "Manage your Subscription and Billing",
|
||||||
|
"planCardTitle": "Your Plan",
|
||||||
|
"planCardDescription": "Below are the details of your current plan. You can change your plan or cancel your subscription at any time.",
|
||||||
|
"planRenewal": "Renews every {{interval}} at {{price}}",
|
||||||
|
"planDetails": "Plan Details",
|
||||||
|
"checkout": "Proceed to Checkout",
|
||||||
|
"trialEndsOn": "Your trial ends on",
|
||||||
|
"billingPortalCardButton": "Visit Billing Portal",
|
||||||
|
"billingPortalCardTitle": "Manage your Billing Details",
|
||||||
|
"billingPortalCardDescription": "Visit your Billing Portal to manage your subscription and billing. You can update or cancel your plan, or download your invoices.",
|
||||||
|
"cancelAtPeriodEndDescription": "Your subscription is scheduled to be canceled on {{- endDate }}.",
|
||||||
|
"renewAtPeriodEndDescription": "Your subscription is scheduled to be renewed on {{- endDate }}",
|
||||||
|
"noPermissionsAlertHeading": "You don't have permissions to change the billing settings",
|
||||||
|
"noPermissionsAlertBody": "Please contact your account owner to change the billing settings for your account.",
|
||||||
|
"checkoutSuccessTitle": "Done! You're all set.",
|
||||||
|
"checkoutSuccessDescription": "Thank you for subscribing, we have successfully processed your subscription! A confirmation email will be sent to {{ customerEmail }}.",
|
||||||
|
"checkoutSuccessBackButton": "Proceed to App",
|
||||||
|
"cannotManageBillingAlertTitle": "You cannot manage billing",
|
||||||
|
"cannotManageBillingAlertDescription": "You do not have permissions to manage billing. Please contact your account owner.",
|
||||||
|
"manageTeamPlan": "Manage your Team Plan",
|
||||||
|
"manageTeamPlanDescription": "Choose a plan that fits your team's needs. You can upgrade or downgrade your plan at any time.",
|
||||||
|
"basePlan": "Base Plan",
|
||||||
|
"billingInterval": {
|
||||||
|
"label": "Choose your billing interval",
|
||||||
|
"month": "Billed monthly",
|
||||||
|
"year": "Billed yearly"
|
||||||
|
},
|
||||||
|
"perMonth": "month",
|
||||||
|
"custom": "Custom Plan",
|
||||||
|
"lifetime": "Lifetime",
|
||||||
|
"trialPeriod": "{{period}} day trial",
|
||||||
|
"perPeriod": "per {{period}}",
|
||||||
|
"redirectingToPayment": "Redirecting to checkout. Please wait...",
|
||||||
|
"proceedToPayment": "Proceed to Payment",
|
||||||
|
"startTrial": "Start Trial",
|
||||||
|
"perTeamMember": "Per team member",
|
||||||
|
"perUnit": "Per {{unit}} usage",
|
||||||
|
"teamMembers": "Team Members",
|
||||||
|
"includedUpTo": "Up to {{upTo}} {{unit}} included in the plan",
|
||||||
|
"fromPreviousTierUpTo": "for each {{unit}} for the next {{ upTo }} {{ unit }}",
|
||||||
|
"andAbove": "above {{ previousTier }} {{ unit }}",
|
||||||
|
"startingAtPriceUnit": "Starting at {{price}}/{{unit}}",
|
||||||
|
"priceUnit": "{{price}}/{{unit}}",
|
||||||
|
"forEveryUnit": "for every {{ unit }}",
|
||||||
|
"setupFee": "plus a {{ setupFee }} setup fee",
|
||||||
|
"perUnitIncluded": "({{included}} included)",
|
||||||
|
"featuresLabel": "Features",
|
||||||
|
"detailsLabel": "Details",
|
||||||
|
"planPickerLabel": "Pick your preferred plan",
|
||||||
|
"planCardLabel": "Manage your Plan",
|
||||||
|
"planPickerAlertErrorTitle": "Error requesting checkout",
|
||||||
|
"planPickerAlertErrorDescription": "There was an error requesting checkout. Please try again later.",
|
||||||
|
"subscriptionCancelled": "Subscription Cancelled",
|
||||||
|
"cancelSubscriptionDate": "Your subscription will be cancelled at the end of the period",
|
||||||
|
"noPlanChosen": "Please choose a plan",
|
||||||
|
"noIntervalPlanChosen": "Please choose a billing interval",
|
||||||
|
"status": {
|
||||||
|
"free": {
|
||||||
|
"badge": "Free Plan",
|
||||||
|
"heading": "You are currently on the Free Plan",
|
||||||
|
"description": "You're on a free plan. You can upgrade to a paid plan at any time."
|
||||||
|
},
|
||||||
|
"active": {
|
||||||
|
"badge": "Active",
|
||||||
|
"heading": "Your subscription is active",
|
||||||
|
"description": "Your subscription is active. You can manage your subscription and billing in the Customer Portal."
|
||||||
|
},
|
||||||
|
"trialing": {
|
||||||
|
"badge": "Trial",
|
||||||
|
"heading": "You're on a trial",
|
||||||
|
"description": "You can enjoy the benefits of plan until the trial ends"
|
||||||
|
},
|
||||||
|
"past_due": {
|
||||||
|
"badge": "Past Due",
|
||||||
|
"heading": "Your invoice is past due",
|
||||||
|
"description": "Your invoice is past due. Please update your payment method."
|
||||||
|
},
|
||||||
|
"canceled": {
|
||||||
|
"badge": "Canceled",
|
||||||
|
"heading": "Your subscription is canceled",
|
||||||
|
"description": "Your subscription is canceled. It is scheduled to end at end of the billing period."
|
||||||
|
},
|
||||||
|
"unpaid": {
|
||||||
|
"badge": "Unpaid",
|
||||||
|
"heading": "Your invoice is unpaid",
|
||||||
|
"description": "Your invoice is unpaid. Please update your payment method."
|
||||||
|
},
|
||||||
|
"incomplete": {
|
||||||
|
"badge": "Incomplete",
|
||||||
|
"heading": "We're waiting for your payment",
|
||||||
|
"description": "We're waiting for your payment to go through. Please bear with us."
|
||||||
|
},
|
||||||
|
"incomplete_expired": {
|
||||||
|
"badge": "Expired",
|
||||||
|
"heading": "Your payment has expired",
|
||||||
|
"description": "Your payment has expired. Please update your payment method."
|
||||||
|
},
|
||||||
|
"paused": {
|
||||||
|
"badge": "Paused",
|
||||||
|
"heading": "Your subscription is paused",
|
||||||
|
"description": "Your subscription is paused. You can resume it at any time."
|
||||||
|
},
|
||||||
|
"succeeded": {
|
||||||
|
"badge": "Succeeded",
|
||||||
|
"heading": "Your payment was successful",
|
||||||
|
"description": "Your payment was successful. Thank you for subscribing!"
|
||||||
|
},
|
||||||
|
"pending": {
|
||||||
|
"badge": "Pending",
|
||||||
|
"heading": "Your payment is pending",
|
||||||
|
"description": "Your payment is pending. Please bear with us."
|
||||||
|
},
|
||||||
|
"failed": {
|
||||||
|
"badge": "Failed",
|
||||||
|
"heading": "Your payment failed",
|
||||||
|
"description": "Your payment failed. Please update your payment method."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
96
public/locales/ru/common.json
Normal file
96
public/locales/ru/common.json
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"homeTabLabel": "Home",
|
||||||
|
"homeTabDescription": "Welcome to your home page",
|
||||||
|
"accountMembers": "Team Members",
|
||||||
|
"membersTabDescription": "Here you can manage the members of your team.",
|
||||||
|
"billingTabLabel": "Billing",
|
||||||
|
"billingTabDescription": "Manage your billing and subscription",
|
||||||
|
"dashboardTabLabel": "Dashboard",
|
||||||
|
"settingsTabLabel": "Settings",
|
||||||
|
"profileSettingsTabLabel": "Profile",
|
||||||
|
"subscriptionSettingsTabLabel": "Subscription",
|
||||||
|
"dashboardTabDescription": "An overview of your account's activity and performance across all your projects.",
|
||||||
|
"settingsTabDescription": "Manage your settings and preferences.",
|
||||||
|
"emailAddress": "Email Address",
|
||||||
|
"password": "Password",
|
||||||
|
"modalConfirmationQuestion": "Are you sure you want to continue?",
|
||||||
|
"imageInputLabel": "Click here to upload an image",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"clear": "Clear",
|
||||||
|
"notFound": "Not Found",
|
||||||
|
"backToHomePage": "Back to Home Page",
|
||||||
|
"goBack": "Go Back",
|
||||||
|
"genericServerError": "Sorry, something went wrong.",
|
||||||
|
"genericServerErrorHeading": "Sorry, something went wrong while processing your request. Please contact us if the issue persists.",
|
||||||
|
"pageNotFound": "Sorry, this page does not exist.",
|
||||||
|
"pageNotFoundSubHeading": "Apologies, the page you were looking for was not found",
|
||||||
|
"genericError": "Sorry, something went wrong.",
|
||||||
|
"genericErrorSubHeading": "Apologies, an error occurred while processing your request. Please contact us if the issue persists.",
|
||||||
|
"anonymousUser": "Anonymous",
|
||||||
|
"tryAgain": "Try Again",
|
||||||
|
"theme": "Theme",
|
||||||
|
"lightTheme": "Light",
|
||||||
|
"darkTheme": "Dark",
|
||||||
|
"systemTheme": "System",
|
||||||
|
"expandSidebar": "Expand Sidebar",
|
||||||
|
"collapseSidebar": "Collapse Sidebar",
|
||||||
|
"documentation": "Documentation",
|
||||||
|
"getStarted": "Get Started",
|
||||||
|
"getStartedWithPlan": "Get Started with {{plan}}",
|
||||||
|
"retry": "Retry",
|
||||||
|
"contactUs": "Contact Us",
|
||||||
|
"loading": "Loading. Please wait...",
|
||||||
|
"yourAccounts": "Your Accounts",
|
||||||
|
"continue": "Continue",
|
||||||
|
"skip": "Skip",
|
||||||
|
"signedInAs": "Signed in as",
|
||||||
|
"pageOfPages": "Page {{page}} of {{total}}",
|
||||||
|
"noData": "No data available",
|
||||||
|
"pageNotFoundHeading": "Ouch! :|",
|
||||||
|
"errorPageHeading": "Ouch! :|",
|
||||||
|
"notifications": "Notifications",
|
||||||
|
"noNotifications": "No notifications",
|
||||||
|
"justNow": "Just now",
|
||||||
|
"newVersionAvailable": "New version available",
|
||||||
|
"newVersionAvailableDescription": "A new version of the app is available. It is recommended to refresh the page to get the latest updates and avoid any issues.",
|
||||||
|
"newVersionSubmitButton": "Reload and Update",
|
||||||
|
"back": "Back",
|
||||||
|
"routes": {
|
||||||
|
"home": "Home",
|
||||||
|
"account": "Account",
|
||||||
|
"members": "Members",
|
||||||
|
"billing": "Billing",
|
||||||
|
"dashboard": "Dashboard",
|
||||||
|
"settings": "Settings",
|
||||||
|
"profile": "Profile",
|
||||||
|
"application": "Application"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"owner": {
|
||||||
|
"label": "Owner"
|
||||||
|
},
|
||||||
|
"member": {
|
||||||
|
"label": "Member"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"otp": {
|
||||||
|
"requestVerificationCode": "Request Verification Code",
|
||||||
|
"requestVerificationCodeDescription": "We must verify your identity to continue with this action. We'll send a verification code to the email address {{email}}.",
|
||||||
|
"sendingCode": "Sending Code...",
|
||||||
|
"sendVerificationCode": "Send Verification Code",
|
||||||
|
"enterVerificationCode": "Enter Verification Code",
|
||||||
|
"codeSentToEmail": "We've sent a verification code to the email address {{email}}.",
|
||||||
|
"verificationCode": "Verification Code",
|
||||||
|
"enterCodeFromEmail": "Enter the 6-digit code we sent to your email.",
|
||||||
|
"verifying": "Verifying...",
|
||||||
|
"verifyCode": "Verify Code",
|
||||||
|
"requestNewCode": "Request New Code",
|
||||||
|
"errorSendingCode": "Error sending code. Please try again."
|
||||||
|
},
|
||||||
|
"cookieBanner": {
|
||||||
|
"title": "Hey, we use cookies 🍪",
|
||||||
|
"description": "This website uses cookies to ensure you get the best experience on our website.",
|
||||||
|
"reject": "Reject",
|
||||||
|
"accept": "Accept"
|
||||||
|
}
|
||||||
|
}
|
||||||
40
public/locales/ru/marketing.json
Normal file
40
public/locales/ru/marketing.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"blog": "Blog",
|
||||||
|
"blogSubtitle": "News and updates about the platform",
|
||||||
|
"documentation": "Documentation",
|
||||||
|
"documentationSubtitle": "Tutorials and guide to get started with the platform",
|
||||||
|
"faq": "FAQ",
|
||||||
|
"faqSubtitle": "Frequently asked questions about the platform",
|
||||||
|
"pricing": "Pricing",
|
||||||
|
"pricingSubtitle": "Pricing plans and payment options",
|
||||||
|
"backToBlog": "Back to blog",
|
||||||
|
"noPosts": "No posts found",
|
||||||
|
"blogPaginationNext": "Next Page",
|
||||||
|
"blogPaginationPrevious": "Previous Page",
|
||||||
|
"readMore": "Read more",
|
||||||
|
"contactFaq": "If you have any questions, please contact us",
|
||||||
|
"contact": "Contact",
|
||||||
|
"about": "About",
|
||||||
|
"product": "Product",
|
||||||
|
"legal": "Legal",
|
||||||
|
"termsOfService": "Terms of Service",
|
||||||
|
"termsOfServiceDescription": "Our terms and conditions",
|
||||||
|
"cookiePolicy": "Cookie Policy",
|
||||||
|
"cookiePolicyDescription": "Our cookie policy and how we use them",
|
||||||
|
"privacyPolicy": "Privacy Policy",
|
||||||
|
"privacyPolicyDescription": "Our privacy policy and how we use your data",
|
||||||
|
"contactDescription": "Contact us for any questions or feedback",
|
||||||
|
"contactHeading": "Send us a message",
|
||||||
|
"contactSubheading": "We will get back to you as soon as possible",
|
||||||
|
"contactName": "Your Name",
|
||||||
|
"contactEmail": "Your Email",
|
||||||
|
"contactMessage": "Your Message",
|
||||||
|
"sendMessage": "Send Message",
|
||||||
|
"contactSuccess": "Your message has been sent successfully",
|
||||||
|
"contactError": "An error occurred while sending your message",
|
||||||
|
"contactSuccessDescription": "We have received your message and will get back to you as soon as possible",
|
||||||
|
"contactErrorDescription": "An error occurred while sending your message. Please try again later",
|
||||||
|
"footerDescription": "Here you can add a description about your company or product",
|
||||||
|
"copyright": "© Copyright {{year}} {{product}}. All Rights Reserved.",
|
||||||
|
"heroSubtitle": "Простой, удобный и быстрый обзор вашего состояния здоровья"
|
||||||
|
}
|
||||||
163
public/locales/ru/teams.json
Normal file
163
public/locales/ru/teams.json
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"pageTitle": "Home"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"pageTitle": "Settings",
|
||||||
|
"pageDescription": "Manage your Team details",
|
||||||
|
"teamLogo": "Team Logo",
|
||||||
|
"teamLogoDescription": "Update your team's logo to make it easier to identify",
|
||||||
|
"teamName": "Team Name",
|
||||||
|
"teamNameDescription": "Update your team's name",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneDescription": "This section contains actions that are irreversible"
|
||||||
|
},
|
||||||
|
"members": {
|
||||||
|
"pageTitle": "Members"
|
||||||
|
},
|
||||||
|
"billing": {
|
||||||
|
"pageTitle": "Billing"
|
||||||
|
},
|
||||||
|
"yourTeams": "Your Teams ({{teamsCount}})",
|
||||||
|
"createTeam": "Create a Team",
|
||||||
|
"creatingTeam": "Creating Team...",
|
||||||
|
"personalAccount": "Personal Account",
|
||||||
|
"searchAccount": "Search Account...",
|
||||||
|
"membersTabLabel": "Members",
|
||||||
|
"memberName": "Name",
|
||||||
|
"youLabel": "You",
|
||||||
|
"emailLabel": "Email",
|
||||||
|
"roleLabel": "Role",
|
||||||
|
"primaryOwnerLabel": "Primary Owner",
|
||||||
|
"joinedAtLabel": "Joined at",
|
||||||
|
"invitedAtLabel": "Invited at",
|
||||||
|
"inviteMembersPageSubheading": "Invite members to your Team",
|
||||||
|
"createTeamModalHeading": "Create Team",
|
||||||
|
"createTeamModalDescription": "Create a new Team to manage your projects and members.",
|
||||||
|
"teamNameLabel": "Team Name",
|
||||||
|
"teamNameDescription": "Your team name should be unique and descriptive",
|
||||||
|
"createTeamSubmitLabel": "Create Team",
|
||||||
|
"createTeamSuccess": "Team created successfully",
|
||||||
|
"createTeamError": "Team not created. Please try again.",
|
||||||
|
"createTeamLoading": "Creating team...",
|
||||||
|
"settingsPageLabel": "General",
|
||||||
|
"createTeamDropdownLabel": "New team",
|
||||||
|
"changeRole": "Change Role",
|
||||||
|
"removeMember": "Remove from Account",
|
||||||
|
"inviteMembersSuccess": "Members invited successfully!",
|
||||||
|
"inviteMembersError": "Sorry, we encountered an error! Please try again",
|
||||||
|
"inviteMembersLoading": "Inviting members...",
|
||||||
|
"removeInviteButtonLabel": "Remove invite",
|
||||||
|
"addAnotherMemberButtonLabel": "Add another one",
|
||||||
|
"inviteMembersButtonLabel": "Send Invites",
|
||||||
|
"removeMemberModalHeading": "You are removing this user",
|
||||||
|
"removeMemberModalDescription": "Remove this member from the team. They will no longer have access to the team.",
|
||||||
|
"removeMemberSuccessMessage": "Member removed successfully",
|
||||||
|
"removeMemberErrorMessage": "Sorry, we encountered an error. Please try again",
|
||||||
|
"removeMemberErrorHeading": "Sorry, we couldn't remove the selected member.",
|
||||||
|
"removeMemberLoadingMessage": "Removing member...",
|
||||||
|
"removeMemberSubmitLabel": "Remove User from Team",
|
||||||
|
"chooseDifferentRoleError": "Role is the same as the current one",
|
||||||
|
"updateRole": "Update Role",
|
||||||
|
"updateRoleLoadingMessage": "Updating role...",
|
||||||
|
"updateRoleSuccessMessage": "Role updated successfully",
|
||||||
|
"updatingRoleErrorMessage": "Sorry, we encountered an error. Please try again.",
|
||||||
|
"updateMemberRoleModalHeading": "Update Member's Role",
|
||||||
|
"updateMemberRoleModalDescription": "Change the role of the selected member. The role determines the permissions of the member.",
|
||||||
|
"roleMustBeDifferent": "Role must be different from the current one",
|
||||||
|
"memberRoleInputLabel": "Member role",
|
||||||
|
"updateRoleDescription": "Pick a role for this member.",
|
||||||
|
"updateRoleSubmitLabel": "Update Role",
|
||||||
|
"transferOwnership": "Transfer Ownership",
|
||||||
|
"transferOwnershipDescription": "Transfer ownership of the team to another member.",
|
||||||
|
"transferOwnershipInputLabel": "Please type TRANSFER to confirm the transfer of ownership.",
|
||||||
|
"transferOwnershipInputDescription": "By transferring ownership, you will no longer be the primary owner of the team.",
|
||||||
|
"deleteInvitation": "Delete Invitation",
|
||||||
|
"deleteInvitationDialogDescription": "You are about to delete the invitation. The user will no longer be able to join the team.",
|
||||||
|
"deleteInviteSuccessMessage": "Invite deleted successfully",
|
||||||
|
"deleteInviteErrorMessage": "Invite not deleted. Please try again.",
|
||||||
|
"deleteInviteLoadingMessage": "Deleting invite. Please wait...",
|
||||||
|
"confirmDeletingMemberInvite": "You are deleting the invite to <b>{{ email }}</b>",
|
||||||
|
"transferOwnershipDisclaimer": "You are transferring ownership of the selected team to <b>{{ member }}</b>.",
|
||||||
|
"transferringOwnership": "Transferring ownership...",
|
||||||
|
"transferOwnershipSuccess": "Ownership successfully transferred",
|
||||||
|
"transferOwnershipError": "Sorry, we could not transfer ownership to the selected member. Please try again.",
|
||||||
|
"deleteInviteSubmitLabel": "Delete Invite",
|
||||||
|
"youBadgeLabel": "You",
|
||||||
|
"updateTeamLoadingMessage": "Updating Team...",
|
||||||
|
"updateTeamSuccessMessage": "Team successfully updated",
|
||||||
|
"updateTeamErrorMessage": "Could not update Team. Please try again.",
|
||||||
|
"updateLogoErrorMessage": "Could not update Logo. Please try again.",
|
||||||
|
"teamNameInputLabel": "Team Name",
|
||||||
|
"teamLogoInputHeading": "Upload your team's Logo",
|
||||||
|
"teamLogoInputSubheading": "Please choose a photo to upload as your team logo.",
|
||||||
|
"updateTeamSubmitLabel": "Update Team",
|
||||||
|
"inviteMembersHeading": "Invite Members to your Team",
|
||||||
|
"inviteMembersDescription": "Invite members to your team by entering their email and role.",
|
||||||
|
"emailPlaceholder": "member@email.com",
|
||||||
|
"membersPageHeading": "Members",
|
||||||
|
"inviteMembersButton": "Invite Members",
|
||||||
|
"invitingMembers": "Inviting members...",
|
||||||
|
"inviteMembersSuccessMessage": "Members invited successfully",
|
||||||
|
"inviteMembersErrorMessage": "Sorry, members could not be invited. Please try again.",
|
||||||
|
"pendingInvitesHeading": "Pending Invites",
|
||||||
|
"pendingInvitesDescription": " Here you can manage the pending invitations to your team.",
|
||||||
|
"noPendingInvites": "No pending invites found",
|
||||||
|
"loadingMembers": "Loading members...",
|
||||||
|
"loadMembersError": "Sorry, we couldn't fetch your team's members.",
|
||||||
|
"loadInvitedMembersError": "Sorry, we couldn't fetch your team's invited members.",
|
||||||
|
"loadingInvitedMembers": "Loading invited members...",
|
||||||
|
"invitedBadge": "Invited",
|
||||||
|
"duplicateInviteEmailError": "You have already entered this email address",
|
||||||
|
"invitingOwnAccountError": "Hey, that's your email!",
|
||||||
|
"dangerZone": "Danger Zone",
|
||||||
|
"dangerZoneSubheading": "Delete or leave your team",
|
||||||
|
"deleteTeam": "Delete Team",
|
||||||
|
"deleteTeamDescription": "This action cannot be undone. All data associated with this team will be deleted.",
|
||||||
|
"deletingTeam": "Deleting team",
|
||||||
|
"deleteTeamModalHeading": "Deleting Team",
|
||||||
|
"deletingTeamDescription": "You are about to delete the team {{ teamName }}. This action cannot be undone.",
|
||||||
|
"deleteTeamInputField": "Type the name of the team to confirm",
|
||||||
|
"leaveTeam": "Leave Team",
|
||||||
|
"leavingTeamModalHeading": "Leaving Team",
|
||||||
|
"leavingTeamModalDescription": "You are about to leave this team. You will no longer have access to it.",
|
||||||
|
"leaveTeamDescription": "Click the button below to leave the team. Remember, you will no longer have access to it and will need to be re-invited to join.",
|
||||||
|
"deleteTeamDisclaimer": "You are deleting the team {{ teamName }}. This action cannot be undone.",
|
||||||
|
"leaveTeamDisclaimer": "You are leaving the team {{ teamName }}. You will no longer have access to it.",
|
||||||
|
"deleteTeamErrorHeading": "Sorry, we couldn't delete your team.",
|
||||||
|
"leaveTeamErrorHeading": "Sorry, we couldn't leave your team.",
|
||||||
|
"searchMembersPlaceholder": "Search members",
|
||||||
|
"createTeamErrorHeading": "Sorry, we couldn't create your team.",
|
||||||
|
"createTeamErrorMessage": "We encountered an error creating your team. Please try again.",
|
||||||
|
"transferTeamErrorHeading": "Sorry, we couldn't transfer ownership of your team.",
|
||||||
|
"transferTeamErrorMessage": "We encountered an error transferring ownership of your team. Please try again.",
|
||||||
|
"updateRoleErrorHeading": "Sorry, we couldn't update the role of the selected member.",
|
||||||
|
"updateRoleErrorMessage": "We encountered an error updating the role of the selected member. Please try again.",
|
||||||
|
"searchInvitations": "Search Invitations",
|
||||||
|
"updateInvitation": "Update Invitation",
|
||||||
|
"removeInvitation": "Remove Invitation",
|
||||||
|
"acceptInvitation": "Accept Invitation",
|
||||||
|
"renewInvitation": "Renew Invitation",
|
||||||
|
"resendInvitation": "Resend Invitation",
|
||||||
|
"expiresAtLabel": "Expires at",
|
||||||
|
"expired": "Expired",
|
||||||
|
"active": "Active",
|
||||||
|
"inviteStatus": "Status",
|
||||||
|
"inviteNotFoundOrExpired": "Invite not found or expired",
|
||||||
|
"inviteNotFoundOrExpiredDescription": "The invite you are looking for is either expired or does not exist. Please contact the team owner to renew the invite.",
|
||||||
|
"backToHome": "Back to Home",
|
||||||
|
"renewInvitationDialogDescription": "You are about to renew the invitation to {{ email }}. The user will be able to join the team.",
|
||||||
|
"renewInvitationErrorTitle": "Sorry, we couldn't renew the invitation.",
|
||||||
|
"renewInvitationErrorDescription": "We encountered an error renewing the invitation. Please try again.",
|
||||||
|
"signInWithDifferentAccount": "Sign in with a different account",
|
||||||
|
"signInWithDifferentAccountDescription": "If you wish to accept the invitation with a different account, please sign out and back in with the account you wish to use.",
|
||||||
|
"acceptInvitationHeading": "Accept Invitation to join {{accountName}}",
|
||||||
|
"acceptInvitationDescription": "You have been invited to join the team {{accountName}}. If you wish to accept the invitation, please click the button below.",
|
||||||
|
"continueAs": "Continue as {{email}}",
|
||||||
|
"joinTeamAccount": "Join Team",
|
||||||
|
"joiningTeam": "Joining team...",
|
||||||
|
"leaveTeamInputLabel": "Please type LEAVE to confirm leaving the team.",
|
||||||
|
"leaveTeamInputDescription": "By leaving the team, you will no longer have access to it.",
|
||||||
|
"reservedNameError": "This name is reserved. Please choose a different one.",
|
||||||
|
"specialCharactersError": "This name cannot contain special characters. Please choose a different one."
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
font-feature-settings: "rlig" 1, "calt" 1;
|
font-feature-settings: "rlig" 1, "calt" 1;
|
||||||
|
/* @apply font-sans */
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
@@ -46,4 +47,10 @@
|
|||||||
textarea::placeholder {
|
textarea::placeholder {
|
||||||
color: theme(--color-muted-foreground);
|
color: theme(--color-muted-foreground);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
@apply font-heading text-foreground text-2xl font-semibold tracking-tight
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,38 +8,39 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
||||||
--font-heading: var(--font-sans);
|
--font-sans: var(--font-sans) -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
--font-heading: var(--font-heading);
|
||||||
|
|
||||||
--background: var(--color-white);
|
--background: var(--color-white);
|
||||||
--foreground: var(--color-neutral-950);
|
--foreground: hsla(240, 10%, 4%, 1);
|
||||||
|
|
||||||
--card: var(--color-white);
|
--card: var(--color-white);
|
||||||
--card-foreground: var(--color-neutral-950);
|
--card-foreground: var(--color-neutral-950);
|
||||||
|
|
||||||
--popover: var(--color-white);
|
--popover: var(--color-white);
|
||||||
--popover-foreground: var(--color-neutral-950);
|
--popover-foreground: hsla(240, 10%, 4%, 1);
|
||||||
|
|
||||||
--primary: var(--color-neutral-950);
|
--primary: hsla(145, 78%, 18%, 1);
|
||||||
--primary-foreground: var(--color-white);
|
--primary-foreground: hsla(356, 100%, 97%, 1);
|
||||||
|
|
||||||
--secondary: oklch(96.76% 0.0013 286.38);
|
--secondary: hsla(240, 5%, 96%, 1);
|
||||||
--secondary-foreground: oklch(21.03% 0.0318 264.65);
|
--secondary-foreground: hsla(240, 6%, 10%, 1);
|
||||||
|
|
||||||
--muted: oklch(96.71% 0.0029 264.54);
|
--muted: hsla(240, 5%, 96%, 1);
|
||||||
--muted-foreground: oklch(55.13% 0.0233 264.36);
|
--muted-foreground: hsla(240, 4%, 41%, 1);
|
||||||
|
|
||||||
--accent: oklch(96.76% 0.0013 286.38);
|
--accent: hsla(240, 5%, 96%, 1);
|
||||||
--accent-foreground: oklch(21.03% 0.0318 264.65);
|
--accent-foreground: hsla(240, 6%, 10%, 1);
|
||||||
|
|
||||||
--destructive: var(--color-red-500);
|
--destructive: hsla(0, 84%, 60%, 1);
|
||||||
--destructive-foreground: var(--color-white);
|
--destructive-foreground: hsla(0, 0%, 98%, 1);
|
||||||
|
|
||||||
--border: var(--color-gray-100);
|
--border: hsla(240, 6%, 90%, 1);
|
||||||
--input: var(--color-gray-200);
|
--input: hsla(240, 6%, 90%, 1);
|
||||||
--ring: var(--color-neutral-800);
|
--ring: var(--color-neutral-800);
|
||||||
|
|
||||||
--radius: 0.5rem;
|
--radius: 1rem;
|
||||||
|
|
||||||
--chart-1: var(--color-orange-400);
|
--chart-1: var(--color-orange-400);
|
||||||
--chart-2: var(--color-teal-600);
|
--chart-2: var(--color-teal-600);
|
||||||
@@ -55,6 +56,7 @@
|
|||||||
--sidebar-accent-foreground: var(--color-neutral-950);
|
--sidebar-accent-foreground: var(--color-neutral-950);
|
||||||
--sidebar-border: var(--border);
|
--sidebar-border: var(--border);
|
||||||
--sidebar-ring: var(--color-blue-500);
|
--sidebar-ring: var(--color-blue-500);
|
||||||
|
/* --foreground: 240 10% 4%; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
@@ -74,7 +76,7 @@
|
|||||||
--secondary-foreground: oklch(98.43% 0.0017 247.84);
|
--secondary-foreground: oklch(98.43% 0.0017 247.84);
|
||||||
|
|
||||||
--muted: var(--color-neutral-800);
|
--muted: var(--color-neutral-800);
|
||||||
--muted-foreground: oklch(71.19% 0.0129 286.07);
|
--muted-foreground: hsla(240, 4%, 41%, 1);
|
||||||
|
|
||||||
--accent: var(--color-neutral-800);
|
--accent: var(--color-neutral-800);
|
||||||
--accent-foreground: oklch(98.48% 0 0);
|
--accent-foreground: oklch(98.48% 0 0);
|
||||||
|
|||||||
@@ -66,6 +66,16 @@
|
|||||||
--animate-accordion-down: accordion-down 0.2s ease-out;
|
--animate-accordion-down: accordion-down 0.2s ease-out;
|
||||||
--animate-accordion-up: accordion-up 0.2s ease-out;
|
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||||
|
|
||||||
|
--breakpoint-xs: 30rem;
|
||||||
|
--breakpoint-sm: 48rem;
|
||||||
|
--breakpoint-md: 70rem;
|
||||||
|
--breakpoint-lg: 80rem;
|
||||||
|
--breakpoint-xl: 96rem;
|
||||||
|
--breakpoint-2xl: 100rem;
|
||||||
|
--breakpoint-3xl: 120rem;
|
||||||
|
|
||||||
|
--container-max-width: 80rem;
|
||||||
|
|
||||||
@keyframes accordion-down {
|
@keyframes accordion-down {
|
||||||
from {
|
from {
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ enabled = true
|
|||||||
port = 54321
|
port = 54321
|
||||||
# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
|
# Schemas to expose in your API. Tables, views and stored procedures in this schema will get API
|
||||||
# endpoints. `public` and `graphql_public` schemas are included by default.
|
# endpoints. `public` and `graphql_public` schemas are included by default.
|
||||||
schemas = ["public", "graphql_public"]
|
schemas = ["public", "graphql_public", "audit"]
|
||||||
# Extra schemas to add to the search_path of every request.
|
# Extra schemas to add to the search_path of every request.
|
||||||
extra_search_path = ["public", "extensions"]
|
extra_search_path = ["public", "extensions"]
|
||||||
# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
|
# The maximum number of rows returns from a view, table, or stored procedure. Limits payload size
|
||||||
|
|||||||
1285
supabase/database.types.ts
Normal file
1285
supabase/database.types.ts
Normal file
File diff suppressed because it is too large
Load Diff
206
supabase/migrations/20250602164242_create_medipost_tables.sql
Normal file
206
supabase/migrations/20250602164242_create_medipost_tables.sql
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
create table "public"."analyses" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"analysis_id_oid" text not null,
|
||||||
|
"analysis_id_original" text not null,
|
||||||
|
"tehik_short_loinc" text,
|
||||||
|
"tehik_loinc_name" text,
|
||||||
|
"analysis_name_lab" text,
|
||||||
|
"order" smallint,
|
||||||
|
"created_at" timestamp with time zone not null default now(),
|
||||||
|
"updated_at" timestamp with time zone default now(),
|
||||||
|
"parent_analysis_element_id" bigint not null
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
alter table "public"."analyses" enable row level security;
|
||||||
|
|
||||||
|
create table "public"."analysis_elements" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"analysis_id_oid" text,
|
||||||
|
"analysis_id_original" text not null,
|
||||||
|
"tehik_short_loinc" text,
|
||||||
|
"tehik_loinc_name" text,
|
||||||
|
"analysis_name_lab" text,
|
||||||
|
"order" smallint,
|
||||||
|
"created_at" timestamp with time zone not null default now(),
|
||||||
|
"updated_at" timestamp with time zone default now(),
|
||||||
|
"parent_analysis_group_id" bigint not null,
|
||||||
|
"material_groups" jsonb[]
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
alter table "public"."analysis_elements" enable row level security;
|
||||||
|
|
||||||
|
create table "public"."analysis_groups" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"original_id" text not null,
|
||||||
|
"name" text,
|
||||||
|
"order" smallint,
|
||||||
|
"created_at" timestamp with time zone not null default now(),
|
||||||
|
"updated_at" timestamp with time zone default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
alter table "public"."analysis_groups" enable row level security;
|
||||||
|
|
||||||
|
create table "public"."codes" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"hk_code" text not null,
|
||||||
|
"hk_code_multiplier" bigint not null,
|
||||||
|
"coefficient" double precision not null,
|
||||||
|
"price" double precision not null,
|
||||||
|
"analysis_group_id" bigint,
|
||||||
|
"analysis_element_id" bigint,
|
||||||
|
"analysis_id" bigint,
|
||||||
|
"updated_at" timestamp with time zone default now(),
|
||||||
|
"created_at" timestamp with time zone not null default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
alter table "public"."codes" enable row level security;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_elements_pkey ON public.analysis_elements USING btree (id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_elements_original_id_key ON public.analysis_elements USING btree (analysis_id_original);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_group_original_id_key ON public.analysis_groups USING btree (original_id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_group_pkey ON public.analysis_groups USING btree (id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_pkey ON public.analyses USING btree (id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_original_id_key ON public.analysis_elements USING btree (analysis_id_original);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX codes_pkey ON public.codes USING btree (id);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analyses_analysis_id_original_key ON public.analyses USING btree (analysis_id_original);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX analysis_elements_analysis_id_original_key ON public.analysis_elements USING btree (analysis_id_original);
|
||||||
|
|
||||||
|
alter table "public"."analyses" add constraint "analyses_analysis_id_original_key" UNIQUE using index "analyses_analysis_id_original_key";
|
||||||
|
|
||||||
|
alter table "public"."analysis_elements" add constraint "analysis_elements_analysis_id_original_key" UNIQUE using index "analysis_elements_analysis_id_original_key";
|
||||||
|
|
||||||
|
alter table "public"."analyses" add constraint "analysis_pkey" PRIMARY KEY using index "analysis_pkey";
|
||||||
|
|
||||||
|
alter table "public"."analysis_elements" add constraint "analysis_elements_pkey" PRIMARY KEY using index "analysis_elements_pkey";
|
||||||
|
|
||||||
|
alter table "public"."analysis_groups" add constraint "analysis_group_pkey" PRIMARY KEY using index "analysis_group_pkey";
|
||||||
|
|
||||||
|
alter table "public"."codes" add constraint "codes_pkey" PRIMARY KEY using index "codes_pkey";
|
||||||
|
|
||||||
|
alter table "public"."analyses" add constraint "analyses_parent_analysis_element_id_fkey" FOREIGN KEY (parent_analysis_element_id) REFERENCES analysis_elements(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."analyses" validate constraint "analyses_parent_analysis_element_id_fkey";
|
||||||
|
|
||||||
|
alter table "public"."analysis_elements" add constraint "analysis_elements_parent_analysis_group_id_fkey" FOREIGN KEY (parent_analysis_group_id) REFERENCES analysis_groups(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."analysis_elements" validate constraint "analysis_elements_parent_analysis_group_id_fkey";
|
||||||
|
|
||||||
|
alter table "public"."analysis_groups" add constraint "analysis_group_original_id_key" UNIQUE using index "analysis_group_original_id_key";
|
||||||
|
|
||||||
|
alter table "public"."codes" add constraint "codes_analysis_element_id_fkey" FOREIGN KEY (analysis_element_id) REFERENCES analysis_elements(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."codes" validate constraint "codes_analysis_element_id_fkey";
|
||||||
|
|
||||||
|
alter table "public"."codes" add constraint "codes_analysis_group_id_fkey" FOREIGN KEY (analysis_group_id) REFERENCES analysis_groups(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."codes" validate constraint "codes_analysis_group_id_fkey";
|
||||||
|
|
||||||
|
alter table "public"."codes" add constraint "codes_analysis_id_fkey" FOREIGN KEY (analysis_id) REFERENCES analyses(id) ON UPDATE CASCADE ON DELETE CASCADE not valid;
|
||||||
|
|
||||||
|
alter table "public"."codes" validate constraint "codes_analysis_id_fkey";
|
||||||
|
|
||||||
|
grant delete on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."analyses" to "service_role";
|
||||||
|
|
||||||
|
grant delete on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."analysis_elements" to "service_role";
|
||||||
|
|
||||||
|
grant delete on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."analysis_groups" to "service_role";
|
||||||
|
|
||||||
|
grant delete on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant insert on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant references on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant select on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant trigger on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant truncate on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
grant update on table "public"."codes" to "service_role";
|
||||||
|
|
||||||
|
create policy "analysis_all"
|
||||||
|
on "public"."analyses"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to service_role
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
|
||||||
|
create policy "analysis_elements_all"
|
||||||
|
on "public"."analysis_elements"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to service_role
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
|
||||||
|
create policy "analysis_groups_all"
|
||||||
|
on "public"."analysis_groups"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to service_role
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
|
||||||
|
create policy "codes_all"
|
||||||
|
on "public"."codes"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to service_role
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TRIGGER analysis_change_record_timestamps AFTER INSERT OR DELETE OR UPDATE ON public.analyses FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
|
||||||
|
CREATE TRIGGER analysis_elements_change_record_timestamps AFTER INSERT OR DELETE OR UPDATE ON public.analysis_elements FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
|
||||||
|
CREATE TRIGGER analysis_groups_change_record_timestamps AFTER INSERT OR DELETE OR UPDATE ON public.analysis_groups FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
|
||||||
|
CREATE TRIGGER codes_change_record_timestamps AFTER INSERT OR DELETE OR UPDATE ON public.codes FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamps();
|
||||||
|
|
||||||
87
supabase/migrations/20250604115051_add_audit_schema.sql
Normal file
87
supabase/migrations/20250604115051_add_audit_schema.sql
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
create schema if not exists audit;
|
||||||
|
|
||||||
|
create table if not exists audit.log_entries (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"schema_name" text not null,
|
||||||
|
"table_name" text not null,
|
||||||
|
"record_key" bigint,
|
||||||
|
"operation" text not null,
|
||||||
|
"row_data" jsonb,
|
||||||
|
"changed_data" jsonb,
|
||||||
|
"changed_by" uuid,
|
||||||
|
"changed_by_role" text,
|
||||||
|
"changed_at" timestamptz not null default now()
|
||||||
|
);
|
||||||
|
|
||||||
|
alter table "audit"."log_entries" enable row level security;
|
||||||
|
|
||||||
|
create policy "service_role_all"
|
||||||
|
on "audit"."log_entries"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to service_role
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
create or replace function audit.log_audit_changes()
|
||||||
|
returns trigger
|
||||||
|
language plpgsql
|
||||||
|
as $$
|
||||||
|
declare
|
||||||
|
current_user_id uuid;
|
||||||
|
current_user_role text;
|
||||||
|
begin
|
||||||
|
begin
|
||||||
|
current_user_id := auth.uid();
|
||||||
|
current_user_role := auth.jwt() ->> 'role';
|
||||||
|
end;
|
||||||
|
|
||||||
|
insert into audit.log_entries (
|
||||||
|
schema_name,
|
||||||
|
table_name,
|
||||||
|
record_key,
|
||||||
|
operation,
|
||||||
|
row_data,
|
||||||
|
changed_data,
|
||||||
|
changed_by,
|
||||||
|
changed_by_role
|
||||||
|
)
|
||||||
|
values (
|
||||||
|
tg_table_schema,
|
||||||
|
tg_table_name,
|
||||||
|
case when tg_op in ('DELETE', 'UPDATE') then old.id else null end,
|
||||||
|
tg_op,
|
||||||
|
case when tg_op in ('DELETE', 'UPDATE') then to_jsonb(old) else null end,
|
||||||
|
case when tg_op in ('INSERT', 'UPDATE') then to_jsonb(new) else null end,
|
||||||
|
current_user_id,
|
||||||
|
current_user_role
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
end;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
create table "audit"."sync_entries" (
|
||||||
|
"id" bigint generated by default as identity not null,
|
||||||
|
"status" text not null,
|
||||||
|
"operation" text not null,
|
||||||
|
"comment" text,
|
||||||
|
"created_at" timestamp with time zone not null default now(),
|
||||||
|
"changed_by_role" text not null
|
||||||
|
);
|
||||||
|
|
||||||
|
create type "audit"."sync_status" as enum ('SUCCESS', 'FAIL');
|
||||||
|
|
||||||
|
alter table "audit"."sync_entries" enable row level security;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX sync_entries_pkey ON audit.sync_entries USING btree (id);
|
||||||
|
|
||||||
|
alter table "audit"."sync_entries" add constraint "sync_entries_pkey" PRIMARY KEY using index "sync_entries_pkey";
|
||||||
|
|
||||||
|
create policy "service_role_all"
|
||||||
|
on "audit"."sync_entries"
|
||||||
|
as permissive
|
||||||
|
for all
|
||||||
|
to public
|
||||||
|
using (true);
|
||||||
|
|
||||||
|
GRANT USAGE ON SCHEMA audit TO service_role;
|
||||||
|
GRANT ALL ON ALL TABLES IN SCHEMA audit TO service_role;
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
import type { Config } from "tailwindcss";
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
darkMode: ["class"],
|
|
||||||
content: [
|
|
||||||
"./pages/**/*.{ts,tsx}",
|
|
||||||
"./components/**/*.{ts,tsx}",
|
|
||||||
"./app/**/*.{ts,tsx}",
|
|
||||||
"./src/**/*.{ts,tsx}",
|
|
||||||
],
|
|
||||||
prefix: "",
|
|
||||||
theme: {
|
|
||||||
container: {
|
|
||||||
center: true,
|
|
||||||
padding: "2rem",
|
|
||||||
screens: {
|
|
||||||
"2xl": "1400px",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
extend: {
|
|
||||||
colors: {
|
|
||||||
border: "hsl(var(--border))",
|
|
||||||
input: "hsl(var(--input))",
|
|
||||||
ring: "hsl(var(--ring))",
|
|
||||||
background: "hsl(var(--background))",
|
|
||||||
foreground: "hsl(var(--foreground))",
|
|
||||||
primary: {
|
|
||||||
DEFAULT: "hsl(var(--primary))",
|
|
||||||
foreground: "hsl(var(--primary-foreground))",
|
|
||||||
},
|
|
||||||
secondary: {
|
|
||||||
DEFAULT: "hsl(var(--secondary))",
|
|
||||||
foreground: "hsl(var(--secondary-foreground))",
|
|
||||||
},
|
|
||||||
destructive: {
|
|
||||||
DEFAULT: "hsl(var(--destructive))",
|
|
||||||
foreground: "hsl(var(--destructive-foreground))",
|
|
||||||
},
|
|
||||||
muted: {
|
|
||||||
DEFAULT: "hsl(var(--muted))",
|
|
||||||
foreground: "hsl(var(--muted-foreground))",
|
|
||||||
},
|
|
||||||
accent: {
|
|
||||||
DEFAULT: "hsl(var(--accent))",
|
|
||||||
foreground: "hsl(var(--accent-foreground))",
|
|
||||||
},
|
|
||||||
popover: {
|
|
||||||
DEFAULT: "hsl(var(--popover))",
|
|
||||||
foreground: "hsl(var(--popover-foreground))",
|
|
||||||
},
|
|
||||||
card: {
|
|
||||||
DEFAULT: "hsl(var(--card))",
|
|
||||||
foreground: "hsl(var(--card-foreground))",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
borderRadius: {
|
|
||||||
lg: "var(--radius)",
|
|
||||||
md: "calc(var(--radius) - 2px)",
|
|
||||||
sm: "calc(var(--radius) - 4px)",
|
|
||||||
},
|
|
||||||
keyframes: {
|
|
||||||
"accordion-down": {
|
|
||||||
from: { height: "0" },
|
|
||||||
to: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
},
|
|
||||||
"accordion-up": {
|
|
||||||
from: { height: "var(--radix-accordion-content-height)" },
|
|
||||||
to: { height: "0" },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
animation: {
|
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [require("tailwindcss-animate")],
|
|
||||||
} satisfies Config;
|
|
||||||
|
|
||||||
export default config;
|
|
||||||
Reference in New Issue
Block a user