Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
368d1afe27 | ||
|
|
2069fd7248 | ||
|
|
7ed21b692e | ||
|
|
4fcdc7bf5c | ||
|
|
2a0a293f8c | ||
|
|
1b15b71a24 | ||
|
|
5d9889a90c | ||
|
|
a7ee3366eb | ||
|
|
c68e7595fe | ||
|
|
3f6be3b2c0 | ||
|
|
f1647248a2 | ||
|
|
d7db1ad303 | ||
|
|
bd48fd01b1 | ||
|
|
fabf692a08 | ||
|
|
ab62fc5d47 | ||
|
|
0c4cb2e2b0 | ||
|
|
7d77132102 | ||
|
|
50ac5f2892 | ||
|
|
fd12fcc4b8 | ||
|
+2 |
58453d0f2f | ||
|
|
44fd1b9fef | ||
|
|
0098591a56 | ||
|
|
41c1e960f8 | ||
|
|
4e49d32c61 | ||
|
+9 |
0b29c5063a | ||
|
|
95a92567cb | ||
|
+7 |
9e183e6ad1 | ||
|
|
7900f8bab5 | ||
|
|
50904d2588 | ||
|
|
6f811f4f0a | ||
|
|
d9000d0cbe | ||
|
|
ff78e66051 | ||
|
|
7c30f8ca4b | ||
|
|
0ebce77a7b | ||
|
|
4282adac4b | ||
|
|
ef611e2360 | ||
|
|
10ab86b332 | ||
|
|
f04cfef0af | ||
|
|
50151403c4 | ||
|
|
7aa131f349 | ||
|
|
d88bdc368b | ||
|
|
255938fda0 | ||
|
|
5766d6f5f4 | ||
|
|
9d299c6d5f | ||
|
|
f49783b453 | ||
|
|
246fce3ab8 | ||
|
|
82f262f60d | ||
|
|
da8d2da368 | ||
|
|
f01058e073 | ||
|
|
8e369d3fb5 | ||
|
|
11c44db609 | ||
|
|
9d911cbb59 | ||
|
|
30a887df6f | ||
|
|
62fea25eb9 | ||
|
|
d43d8700d0 | ||
|
|
e7ed20ea27 | ||
|
|
5e12b5defe | ||
|
|
d241a522fb | ||
|
+2 |
ae929f27b0 | ||
|
|
369d7c4e28 | ||
|
|
4438ca2a63 | ||
|
|
75589db569 | ||
|
|
3752ac767a | ||
|
+3 |
f3e2cf5075 | ||
|
|
92a29593aa | ||
|
|
367c5d89cc | ||
|
|
f21f36547c | ||
|
|
d3f8d954e7 | ||
|
|
27372d624d | ||
|
|
a5d2f2444a | ||
|
|
6d45e1c7c7 | ||
|
|
48419469a6 | ||
|
|
045ebb6e01 | ||
|
|
c78ea5de0b | ||
|
|
d1a787315c | ||
|
|
ce1f1f3c47 | ||
|
|
2f8bd3c07a | ||
|
|
d2f27a0463 | ||
|
|
9134ad8c5e | ||
|
|
506036e751 | ||
|
|
5e80f5056d | ||
|
|
9304ca1415 | ||
|
|
fb246fdee6 | ||
|
|
7b9e77f43a | ||
|
|
47df21322d | ||
|
|
6017806763 | ||
|
|
b347f29d6c | ||
|
|
c26cf74aec | ||
|
|
760ed74a11 | ||
|
|
145fb09b73 | ||
|
|
dd14e827e1 | ||
|
|
246c90c10f | ||
|
|
a42f703c1d | ||
|
|
7256dbf84f | ||
|
|
f5faebad67 | ||
|
+3 |
be15affa5d | ||
|
|
58dd5308ac | ||
|
|
14a6c5a03f | ||
|
|
5af20f5a7b | ||
|
|
8478363a23 | ||
|
|
19b3157c94 | ||
|
|
d4dd451c26 | ||
|
|
6c046f6507 | ||
|
|
a792d31939 | ||
|
|
fc997739b4 | ||
|
|
542d9aa3c6 | ||
|
|
8f3e088db7 | ||
|
|
699313ac70 | ||
|
|
fca7087e7d | ||
|
|
a6b16490c0 | ||
|
|
5da735c418 | ||
|
|
f9ef883f3d | ||
|
|
9ddbaf0966 | ||
|
|
0695ce7edb | ||
|
|
74f0d39997 | ||
|
|
85ab3fb164 | ||
|
|
ab417ac267 | ||
|
|
24635af730 | ||
|
|
682f0c66ff | ||
|
|
ace27ca84e | ||
|
|
ce41397517 | ||
|
|
81aba55710 | ||
|
|
c5fc3a7e8e | ||
|
|
f628ac4366 | ||
|
|
6e2e252c49 | ||
|
|
10d3a126aa | ||
|
|
341c39cb6b | ||
|
|
91909281bc | ||
|
|
f14b13a1ba | ||
|
|
ca859c871c | ||
|
|
6e49a3e1c3 | ||
|
|
830f42bf9a | ||
|
|
0830523b84 | ||
|
|
612b293a70 | ||
|
|
3ecfa75f86 | ||
|
|
631e974769 | ||
|
|
42c128b790 | ||
|
|
7d1065d228 | ||
|
|
e2747f89d0 | ||
|
|
a1d4589e66 | ||
|
|
7d2f87a13e | ||
|
|
4e7200a44b | ||
|
|
52959fe257 | ||
|
|
61b010a60a | ||
|
|
4e6e484d8b | ||
|
|
0a2de203a6 | ||
|
|
48ee7a956c | ||
|
|
ae46d615ef | ||
|
|
9b6d5d2ff8 | ||
|
|
ec0352da20 | ||
|
|
7e65d5d61d | ||
|
|
f855f24d5c | ||
|
|
c2057c4cc2 | ||
|
|
1640264e40 | ||
|
|
579fd399c3 | ||
|
|
1de00d46bf | ||
|
|
01db3ad14e | ||
|
|
c1cb02a9d1 | ||
|
|
344710d1f9 | ||
|
|
6f0b4f94e6 | ||
|
|
c6ad2de2f9 | ||
|
|
9ae3a0eaba | ||
|
|
2f3d7318a4 | ||
|
|
6e71de7ca3 | ||
|
|
7d277ad89f | ||
|
|
ac276a9654 | ||
|
|
588748d78e | ||
|
|
25711ef18e | ||
|
|
440f53714b | ||
|
|
22f6d8ab9b | ||
|
|
57f0d115cf | ||
|
|
23bc6aa600 | ||
|
|
abdb196f56 |
No files matched your search
@@ -97,7 +97,7 @@ LARK_OPEN_VERIFICATION_TOKEN=""
|
|||||||
|
|
||||||
# - WEB3
|
# - WEB3
|
||||||
# Used for the Web3 plugin
|
# Used for the Web3 plugin
|
||||||
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/web3/README.md
|
# @see https://github.com/calcom/cal.com/blob/main/packages/app-store/rainbow/README.md
|
||||||
ALCHEMY_API_KEY=""
|
ALCHEMY_API_KEY=""
|
||||||
INFURA_API_KEY=""
|
INFURA_API_KEY=""
|
||||||
# *********************************************************************************************************
|
# *********************************************************************************************************
|
||||||
Vendored
+1
-1
@@ -6,5 +6,5 @@
|
|||||||
},
|
},
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative",
|
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||||
"spellright.language": ["en"],
|
"spellright.language": ["en"],
|
||||||
"spellright.documentTypes": ["markdown"]
|
"spellright.documentTypes": ["markdown", "typescript"]
|
||||||
}
|
}
|
||||||
@@ -4,23 +4,6 @@ Contributions are what make the open source community such an amazing place to l
|
|||||||
|
|
||||||
- Before jumping into a PR be sure to search [existing PRs](https://github.com/calcom/cal.com/pulls) or [issues](https://github.com/calcom/cal.com/issues) for an open or closed item that relates to your submission.
|
- Before jumping into a PR be sure to search [existing PRs](https://github.com/calcom/cal.com/pulls) or [issues](https://github.com/calcom/cal.com/issues) for an open or closed item that relates to your submission.
|
||||||
|
|
||||||
## Areas of expertise
|
|
||||||
|
|
||||||
### Legend
|
|
||||||
|
|
||||||
✅ = has knowledge
|
|
||||||
|
|
||||||
🥇 = is their main priority
|
|
||||||
|
|
||||||
⚠️ = is the only one with knowledge
|
|
||||||
|
|
||||||
👀 = has no knowledge but wants to be onboarded
|
|
||||||
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="https://dynamic-svgs.vercel.app/image.svg?dark">
|
|
||||||
<img alt="Areas of expertise table" src="https://dynamic-svgs.vercel.app/image.svg">
|
|
||||||
</picture>
|
|
||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
The development branch is `main`. This is the branch that all pull
|
The development branch is `main`. This is the branch that all pull
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<a href="https://news.ycombinator.com/item?id=26817795"><img src="https://img.shields.io/badge/Hacker%20News-311-%23FF6600" alt="Hacker News"></a>
|
<a href="https://news.ycombinator.com/item?id=26817795"><img src="https://img.shields.io/badge/Hacker%20News-311-%23FF6600" alt="Hacker News"></a>
|
||||||
<a href="https://github.com/calcom/cal.com/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPLv3-purple" alt="License"></a>
|
<a href="https://github.com/calcom/cal.com/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-AGPLv3-purple" alt="License"></a>
|
||||||
<a href="https://github.com/calcom/cal.com/pulse"><img src="https://img.shields.io/github/commit-activity/m/calcom/cal.com" alt="Commits-per-month"></a>
|
<a href="https://github.com/calcom/cal.com/pulse"><img src="https://img.shields.io/github/commit-activity/m/calcom/cal.com" alt="Commits-per-month"></a>
|
||||||
<a href="https://cal.com/pricing"><img src="https://img.shields.io/badge/Pricing-%2412%2Fmonth-brightgreen" alt="Pricing"></a>
|
<a href="https://cal.com/pricing"><img src="https://img.shields.io/badge/Pricing-Free-brightgreen" alt="Pricing"></a>
|
||||||
<a href="https://jitsu.com?utm_source=github/calcom/cal.com"><img src="https://img.shields.io/badge/Metrics_tracked_by-JITSU-AA00FF?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACKSURBVHgBrZDRCYAwDEQv6gCOoKO4hOCXI9QVnEZwiY5iF5GaVClaBNtioCSUvCR3tMJaxIfZgW4AGUoEPVwgPZoS0Dmgg3NBVDFNbMIsmYCak3J1jDk9iCQvsKJvkzr71N81Gj6vDT/LU2P6RhY63jcafk3YJEbgeZpiFyc/5HJKv8Ef273NSfABGbQfUZhnOSAAAAAASUVORK5CYII=" alt="Jitsu Tracked"></a>
|
<a href="https://jitsu.com?utm_source=github/calcom/cal.com"><img src="https://img.shields.io/badge/Metrics_tracked_by-JITSU-AA00FF?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACKSURBVHgBrZDRCYAwDEQv6gCOoKO4hOCXI9QVnEZwiY5iF5GaVClaBNtioCSUvCR3tMJaxIfZgW4AGUoEPVwgPZoS0Dmgg3NBVDFNbMIsmYCak3J1jDk9iCQvsKJvkzr71N81Gj6vDT/LU2P6RhY63jcafk3YJEbgeZpiFyc/5HJKv8Ef273NSfABGbQfUZhnOSAAAAAASUVORK5CYII=" alt="Jitsu Tracked"></a>
|
||||||
<img src="https://api.checklyhq.com/v1/badges/checks/5e048048-1b51-47ba-9209-60607507622e?responseTime=true" alt="Checkly Availability" />
|
<img src="https://api.checklyhq.com/v1/badges/checks/5e048048-1b51-47ba-9209-60607507622e?responseTime=true" alt="Checkly Availability" />
|
||||||
<a href="https://hub.docker.com/r/calendso/calendso"><img src="https://img.shields.io/docker/pulls/calendso/calendso"></a>
|
<a href="https://hub.docker.com/r/calendso/calendso"><img src="https://img.shields.io/docker/pulls/calendso/calendso"></a>
|
||||||
|
|||||||
+1
-1
Submodule apps/api updated: a36b6fa923...7e9226fabc.
@@ -15,14 +15,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@calcom/dayjs": "*",
|
"@calcom/dayjs": "*",
|
||||||
"@calcom/ui": "*",
|
"@calcom/ui": "*",
|
||||||
"@radix-ui/react-avatar": "^0.1.4",
|
"@radix-ui/react-avatar": "^1.0.0",
|
||||||
"@radix-ui/react-collapsible": "^0.1.0",
|
"@radix-ui/react-collapsible": "^1.0.0",
|
||||||
"@radix-ui/react-dialog": "^0.1.0",
|
"@radix-ui/react-dialog": "^1.0.0",
|
||||||
"@radix-ui/react-dropdown-menu": "^0.1.1",
|
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
||||||
"@radix-ui/react-id": "^0.1.0",
|
"@radix-ui/react-id": "^1.0.0",
|
||||||
"@radix-ui/react-radio-group": "^0.1.1",
|
"@radix-ui/react-popover": "^1.0.0",
|
||||||
"@radix-ui/react-slider": "^0.1.1",
|
"@radix-ui/react-radio-group": "^1.0.0",
|
||||||
"@radix-ui/react-switch": "^0.1.1",
|
"@radix-ui/react-slider": "^1.0.0",
|
||||||
|
"@radix-ui/react-switch": "^1.0.0",
|
||||||
"@radix-ui/react-tooltip": "^1.0.0",
|
"@radix-ui/react-tooltip": "^1.0.0",
|
||||||
"next": "^12.2.5",
|
"next": "^12.2.5",
|
||||||
"next-transpile-modules": "^9.0.0",
|
"next-transpile-modules": "^9.0.0",
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ paths:
|
|||||||
- installed: true
|
- installed: true
|
||||||
type: caldav_calendar
|
type: caldav_calendar
|
||||||
credential: null
|
credential: null
|
||||||
title: CalDav Server
|
title: CalDav (Beta)
|
||||||
imageSrc: integrations/caldav.svg
|
imageSrc: integrations/caldav.svg
|
||||||
description: For personal and business calendars
|
description: For personal and business calendars
|
||||||
__N_SSP: true
|
__N_SSP: true
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@radix-ui/react-collapsible";
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@radix-ui/react-collapsible";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useRouter } from "next/router";
|
import { NextRouter, useRouter } from "next/router";
|
||||||
import { createRef, forwardRef, MutableRefObject, RefObject, useRef, useState } from "react";
|
import { createRef, forwardRef, MutableRefObject, RefObject, useRef, useState } from "react";
|
||||||
import { components, ControlProps } from "react-select";
|
import { components, ControlProps } from "react-select";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { Dialog, DialogClose, DialogContent } from "@calcom/ui/Dialog";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import { InputLeading, Label, TextArea, TextField } from "@calcom/ui/form/fields";
|
import { InputLeading, Label, TextArea, TextField } from "@calcom/ui/form/fields";
|
||||||
import { HorizontalTabs, showToast } from "@calcom/ui/v2";
|
import { Button, HorizontalTabs, showToast, Switch } from "@calcom/ui/v2";
|
||||||
import { Button, Switch } from "@calcom/ui/v2";
|
import { Dialog, DialogClose, DialogContent } from "@calcom/ui/v2/core/Dialog";
|
||||||
|
|
||||||
import { EMBED_LIB_URL, WEBAPP_URL } from "@lib/config/constants";
|
import { EMBED_LIB_URL, WEBAPP_URL } from "@lib/config/constants";
|
||||||
|
|
||||||
@@ -46,6 +45,23 @@ const getDimension = (dimension: string) => {
|
|||||||
return dimension;
|
return dimension;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const goto = (router: NextRouter, searchParams: Record<string, string>) => {
|
||||||
|
const newQuery = new URLSearchParams(router.asPath.split("?")[1]);
|
||||||
|
Object.keys(searchParams).forEach((key) => {
|
||||||
|
newQuery.set(key, searchParams[key]);
|
||||||
|
});
|
||||||
|
router.push(`${router.asPath.split("?")[0]}?${newQuery.toString()}`, undefined, {
|
||||||
|
shallow: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeQueryParams = (router: NextRouter, queryParams: string[]) => {
|
||||||
|
queryParams.forEach((param) => {
|
||||||
|
delete router.query[param];
|
||||||
|
});
|
||||||
|
router.push(`${router.asPath.split("?")[0]}?${router.query.toString()}`);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It allows us to show code with certain reusable blocks indented according to the block variable placement
|
* It allows us to show code with certain reusable blocks indented according to the block variable placement
|
||||||
* So, if you add a variable ${abc} with indentation of 4 spaces, it will automatically indent all newlines in `abc` with the same indent before constructing the final string
|
* So, if you add a variable ${abc} with indentation of 4 spaces, it will automatically indent all newlines in `abc` with the same indent before constructing the final string
|
||||||
@@ -452,7 +468,7 @@ const embeds: {
|
|||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
name: "HTML",
|
name: "HTML",
|
||||||
embedTabName: "embed-code",
|
href: "embedTabName=embed-code",
|
||||||
icon: Icon.FiCode,
|
icon: Icon.FiCode,
|
||||||
type: "code",
|
type: "code",
|
||||||
Component: forwardRef<
|
Component: forwardRef<
|
||||||
@@ -503,7 +519,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "HTML", embedType, calLink, previ
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "React",
|
name: "React",
|
||||||
embedTabName: "embed-react",
|
href: "embedTabName=embed-react",
|
||||||
icon: Icon.FiCode,
|
icon: Icon.FiCode,
|
||||||
type: "code",
|
type: "code",
|
||||||
Component: forwardRef<
|
Component: forwardRef<
|
||||||
@@ -543,8 +559,8 @@ ${getEmbedTypeSpecificString({ embedFramework: "react", embedType, calLink, prev
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Preview",
|
name: "Preview",
|
||||||
embedTabName: "embed-preview",
|
href: "embedTabName=embed-preview",
|
||||||
icon: Icon.FiEye,
|
icon: Icon.FiTrello,
|
||||||
type: "iframe",
|
type: "iframe",
|
||||||
Component: forwardRef<
|
Component: forwardRef<
|
||||||
HTMLIFrameElement | HTMLTextAreaElement | null,
|
HTMLIFrameElement | HTMLTextAreaElement | null,
|
||||||
@@ -590,7 +606,7 @@ const ChooseEmbedTypesDialogContent = () => {
|
|||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<DialogContent size="lg">
|
<DialogContent type="creation" useOwnActionButtons size="lg">
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<h3 className="text-lg font-bold leading-6 text-gray-900" id="modal-title">
|
<h3 className="text-lg font-bold leading-6 text-gray-900" id="modal-title">
|
||||||
{t("how_you_want_add_cal_site")}
|
{t("how_you_want_add_cal_site")}
|
||||||
@@ -606,11 +622,8 @@ const ChooseEmbedTypesDialogContent = () => {
|
|||||||
key={index}
|
key={index}
|
||||||
data-testid={embed.type}
|
data-testid={embed.type}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push({
|
goto(router, {
|
||||||
query: {
|
embedType: embed.type,
|
||||||
...router.query,
|
|
||||||
embedType: embed.type,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}}>
|
}}>
|
||||||
<div className="order-none box-border flex-none rounded-sm border border-solid bg-white">
|
<div className="order-none box-border flex-none rounded-sm border border-solid bg-white">
|
||||||
@@ -635,6 +648,13 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
|||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||||
|
const s = (href: string) => {
|
||||||
|
const searchParams = new URLSearchParams(router.asPath.split("?")[1] || "");
|
||||||
|
const [a, b] = href.split("=");
|
||||||
|
searchParams.set(a, b);
|
||||||
|
return `${router.asPath.split("?")[0]}?${searchParams.toString()}`;
|
||||||
|
};
|
||||||
|
const parsedTabs = tabs.map((t) => ({ ...t, href: s(t.href) }));
|
||||||
const embedCodeRefs: Record<typeof tabs[0]["name"], RefObject<HTMLTextAreaElement>> = {};
|
const embedCodeRefs: Record<typeof tabs[0]["name"], RefObject<HTMLTextAreaElement>> = {};
|
||||||
tabs
|
tabs
|
||||||
.filter((tab) => tab.type === "code")
|
.filter((tab) => tab.type === "code")
|
||||||
@@ -661,28 +681,13 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const close = () => {
|
const close = () => {
|
||||||
const noPopupQuery = {
|
removeQueryParams(router, ["dialog", ...queryParamsForDialog]);
|
||||||
...router.query,
|
|
||||||
};
|
|
||||||
|
|
||||||
delete noPopupQuery.dialog;
|
|
||||||
|
|
||||||
queryParamsForDialog.forEach((queryParam) => {
|
|
||||||
delete noPopupQuery[queryParam];
|
|
||||||
});
|
|
||||||
|
|
||||||
router.push({
|
|
||||||
query: noPopupQuery,
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use embed-code as default tab
|
// Use embed-code as default tab
|
||||||
if (!router.query.embedTabName) {
|
if (!router.query.embedTabName) {
|
||||||
router.query.embedTabName = "embed-code";
|
goto(router, {
|
||||||
router.push({
|
embedTabName: "embed-code",
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,20 +784,13 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DialogContent size="lg">
|
<DialogContent size="xl" className="p-0.5" type="creation" useOwnActionButtons>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="flex w-1/3 flex-col bg-white p-6">
|
<div className="flex w-1/3 flex-col bg-gray-50 p-8">
|
||||||
<h3 className="mb-2 flex text-xl font-bold leading-6 text-gray-900" id="modal-title">
|
<h3 className="mb-2 flex text-xl font-bold leading-6 text-gray-900" id="modal-title">
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const newQuery = { ...router.query };
|
removeQueryParams(router, ["embedType", "embedTabName"]);
|
||||||
delete newQuery.embedType;
|
|
||||||
delete newQuery.embedTabName;
|
|
||||||
router.push({
|
|
||||||
query: {
|
|
||||||
...newQuery,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}>
|
}}>
|
||||||
<Icon.FiArrowLeft className="mr-4 w-4" />
|
<Icon.FiArrowLeft className="mr-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
@@ -1040,14 +1038,14 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
|||||||
</Collapsible>
|
</Collapsible>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-2/3 flex-col p-6">
|
<div className="flex w-2/3 flex-col p-8">
|
||||||
<HorizontalTabs tabNameKey="embedTabName" data-testid="embed-tabs" tabs={tabs} />
|
<HorizontalTabs data-testid="embed-tabs" tabs={parsedTabs} linkProps={{ shallow: true }} />
|
||||||
{tabs.map((tab) => {
|
{tabs.map((tab) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={tab.embedTabName}
|
key={tab.href}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
router.query.embedTabName === tab.embedTabName ? "flex flex-grow flex-col" : "hidden"
|
router.query.embedTabName === tab.href.split("=")[1] ? "flex flex-grow flex-col" : "hidden"
|
||||||
)}>
|
)}>
|
||||||
<div className="flex h-[55vh] flex-grow flex-col">
|
<div className="flex h-[55vh] flex-grow flex-col">
|
||||||
{tab.type === "code" ? (
|
{tab.type === "code" ? (
|
||||||
@@ -1133,19 +1131,10 @@ export const EmbedButton = <T extends React.ElementType>({
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
className = classNames(className, "hidden lg:inline-flex");
|
className = classNames(className, "hidden lg:inline-flex");
|
||||||
const openEmbedModal = () => {
|
const openEmbedModal = () => {
|
||||||
const query = {
|
goto(router, {
|
||||||
...router.query,
|
|
||||||
dialog: "embed",
|
dialog: "embed",
|
||||||
embedUrl,
|
embedUrl,
|
||||||
};
|
});
|
||||||
router.push(
|
|
||||||
{
|
|
||||||
pathname: router.pathname,
|
|
||||||
query,
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
{ shallow: true }
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
const Component = as ?? Button;
|
const Component = as ?? Button;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ export function useViewerI18n() {
|
|||||||
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
||||||
* We intend to not cache i18n query
|
* We intend to not cache i18n query
|
||||||
**/
|
**/
|
||||||
context: { skipBatch: true },
|
trpc: {
|
||||||
|
context: { skipBatch: true },
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type AvailableTimesProps = {
|
|||||||
eventTypeId: number;
|
eventTypeId: number;
|
||||||
recurringCount: number | undefined;
|
recurringCount: number | undefined;
|
||||||
eventTypeSlug: string;
|
eventTypeSlug: string;
|
||||||
date: Dayjs;
|
date?: Dayjs;
|
||||||
seatsPerTimeSlot?: number | null;
|
seatsPerTimeSlot?: number | null;
|
||||||
slots?: Slot[];
|
slots?: Slot[];
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
@@ -44,8 +44,10 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
|
|||||||
setBrand(getComputedStyle(document.documentElement).getPropertyValue("--brand-color").trim());
|
setBrand(getComputedStyle(document.documentElement).getPropertyValue("--brand-color").trim());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (!date) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dark:bg-darkgray-100 mt-8 flex flex-col px-4 text-center sm:mt-0 sm:w-1/3 sm:p-5 md:-mb-5">
|
<div className="dark:bg-darkgray-100 mt-8 flex h-full w-full flex-col px-4 text-center sm:mt-0 sm:p-5 md:-mb-5 md:min-w-[200px] lg:min-w-[300px]">
|
||||||
<div className="mb-4 text-left text-base">
|
<div className="mb-4 text-left text-base">
|
||||||
<span className="text-bookingdarker dark:text-darkgray-800 mb-8 w-1/2 break-words font-semibold text-gray-900">
|
<span className="text-bookingdarker dark:text-darkgray-800 mb-8 w-1/2 break-words font-semibold text-gray-900">
|
||||||
{nameOfDay(i18n.language, Number(date.format("d")))}
|
{nameOfDay(i18n.language, Number(date.format("d")))}
|
||||||
@@ -150,4 +152,6 @@ const AvailableTimes: FC<AvailableTimesProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AvailableTimes.displayName = "AvailableTimes";
|
||||||
|
|
||||||
export default AvailableTimes;
|
export default AvailableTimes;
|
||||||
@@ -29,7 +29,7 @@ type BookingItem = inferQueryOutput<"viewer.bookings">["bookings"][number];
|
|||||||
|
|
||||||
type BookingItemProps = BookingItem & {
|
type BookingItemProps = BookingItem & {
|
||||||
listingStatus: BookingListingStatus;
|
listingStatus: BookingListingStatus;
|
||||||
recurringBookings?: BookingItem[];
|
recurringBookings: inferQueryOutput<"viewer.bookings">["recurringInfo"];
|
||||||
};
|
};
|
||||||
|
|
||||||
function BookingListItem(booking: BookingItemProps) {
|
function BookingListItem(booking: BookingItemProps) {
|
||||||
@@ -44,10 +44,25 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
const mutation = trpc.useMutation(["viewer.bookings.confirm"], {
|
const mutation = trpc.useMutation(["viewer.bookings.confirm"], {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
setRejectionDialogIsOpen(false);
|
setRejectionDialogIsOpen(false);
|
||||||
|
showToast(t("booking_confirmation_success"), "success");
|
||||||
|
utils.invalidateQueries("viewer.bookings");
|
||||||
|
},
|
||||||
|
onError: () => {
|
||||||
|
showToast(t("booking_confirmation_failed"), "error");
|
||||||
utils.invalidateQueries("viewer.bookings");
|
utils.invalidateQueries("viewer.bookings");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isUpcoming = new Date(booking.endTime) >= new Date();
|
||||||
|
const isPast = new Date(booking.endTime) < new Date();
|
||||||
|
const isCancelled = booking.status === BookingStatus.CANCELLED;
|
||||||
|
const isConfirmed = booking.status === BookingStatus.ACCEPTED;
|
||||||
|
const isRejected = booking.status === BookingStatus.REJECTED;
|
||||||
|
const isPending = booking.status === BookingStatus.PENDING;
|
||||||
|
const isRecurring = booking.recurringEventId !== null;
|
||||||
|
const isTabRecurring = booking.listingStatus === "recurring";
|
||||||
|
const isTabUnconfirmed = booking.listingStatus === "unconfirmed";
|
||||||
|
|
||||||
const bookingConfirm = async (confirm: boolean) => {
|
const bookingConfirm = async (confirm: boolean) => {
|
||||||
let body = {
|
let body = {
|
||||||
bookingId: booking.id,
|
bookingId: booking.id,
|
||||||
@@ -56,28 +71,18 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Only pass down the recurring event id when we need to confirm the entire series, which happens in
|
* Only pass down the recurring event id when we need to confirm the entire series, which happens in
|
||||||
* the "Recurring" tab, to support confirming discretionally in the "Recurring" tab.
|
* the "Recurring" tab and "Unconfirmed" tab, to support confirming discretionally in the "Recurring" tab.
|
||||||
*/
|
*/
|
||||||
if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) {
|
if ((isTabRecurring || isTabUnconfirmed) && isRecurring) {
|
||||||
body = Object.assign({}, body, { recurringEventId: booking.recurringEventId });
|
body = Object.assign({}, body, { recurringEventId: booking.recurringEventId });
|
||||||
}
|
}
|
||||||
mutation.mutate(body);
|
mutation.mutate(body);
|
||||||
};
|
};
|
||||||
|
|
||||||
const isUpcoming = new Date(booking.endTime) >= new Date();
|
|
||||||
const isPast = new Date(booking.endTime) < new Date();
|
|
||||||
const isCancelled = booking.status === BookingStatus.CANCELLED;
|
|
||||||
const isConfirmed = booking.status === BookingStatus.ACCEPTED;
|
|
||||||
const isRejected = booking.status === BookingStatus.REJECTED;
|
|
||||||
const isPending = booking.status === BookingStatus.PENDING;
|
|
||||||
|
|
||||||
const pendingActions: ActionType[] = [
|
const pendingActions: ActionType[] = [
|
||||||
{
|
{
|
||||||
id: "reject",
|
id: "reject",
|
||||||
label:
|
label: (isTabRecurring || isTabUnconfirmed) && isRecurring ? t("reject_all") : t("reject"),
|
||||||
booking.listingStatus === "recurring" && booking.recurringEventId !== null
|
|
||||||
? t("reject_all")
|
|
||||||
: t("reject"),
|
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
setRejectionDialogIsOpen(true);
|
setRejectionDialogIsOpen(true);
|
||||||
},
|
},
|
||||||
@@ -86,10 +91,7 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "confirm",
|
id: "confirm",
|
||||||
label:
|
label: (isTabRecurring || isTabUnconfirmed) && isRecurring ? t("confirm_all") : t("confirm"),
|
||||||
booking.listingStatus === "recurring" && booking.recurringEventId !== null
|
|
||||||
? t("confirm_all")
|
|
||||||
: t("confirm"),
|
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
bookingConfirm(true);
|
bookingConfirm(true);
|
||||||
},
|
},
|
||||||
@@ -102,23 +104,15 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
let bookedActions: ActionType[] = [
|
let bookedActions: ActionType[] = [
|
||||||
{
|
{
|
||||||
id: "cancel",
|
id: "cancel",
|
||||||
label:
|
label: isTabRecurring && isRecurring ? t("cancel_all_remaining") : t("cancel"),
|
||||||
booking.listingStatus === "recurring" && booking.recurringEventId !== null
|
|
||||||
? t("cancel_all_remaining")
|
|
||||||
: t("cancel"),
|
|
||||||
/* When cancelling we need to let the UI and the API know if the intention is to
|
/* When cancelling we need to let the UI and the API know if the intention is to
|
||||||
cancel all remaining bookings or just that booking instance. */
|
cancel all remaining bookings or just that booking instance. */
|
||||||
href: `/cancel/${booking.uid}${
|
href: `/cancel/${booking.uid}${isTabRecurring && isRecurring ? "?allRemainingBookings=true" : ""}`,
|
||||||
booking.listingStatus === "recurring" && booking.recurringEventId !== null
|
|
||||||
? "?allRemainingBookings=true"
|
|
||||||
: ""
|
|
||||||
}`,
|
|
||||||
icon: Icon.FiX,
|
icon: Icon.FiX,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "edit_booking",
|
id: "edit_booking",
|
||||||
label: t("edit_booking"),
|
label: t("edit"),
|
||||||
icon: Icon.FiEdit,
|
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
id: "reschedule",
|
id: "reschedule",
|
||||||
@@ -147,7 +141,7 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if (booking.listingStatus === "recurring" && booking.recurringEventId !== null) {
|
if (isTabRecurring && isRecurring) {
|
||||||
bookedActions = bookedActions.filter((action) => action.id !== "edit_booking");
|
bookedActions = bookedActions.filter((action) => action.id !== "edit_booking");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,12 +178,8 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
let recurringStrings: string[] = [];
|
let recurringStrings: string[] = [];
|
||||||
let recurringDates: Date[] = [];
|
let recurringDates: Date[] = [];
|
||||||
|
|
||||||
if (booking.recurringBookings && booking.eventType.recurringEvent?.freq !== undefined) {
|
if (booking.recurringBookings !== undefined && booking.eventType.recurringEvent?.freq !== undefined) {
|
||||||
[recurringStrings, recurringDates] = extractRecurringDates(
|
[recurringStrings, recurringDates] = extractRecurringDates(booking, user?.timeZone, i18n);
|
||||||
booking.recurringBookings,
|
|
||||||
user?.timeZone,
|
|
||||||
i18n
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const location = booking.location || "";
|
const location = booking.location || "";
|
||||||
@@ -262,73 +252,89 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
<tr className="flex hover:bg-neutral-50">
|
<tr className="flex flex-col hover:bg-neutral-50 sm:flex-row">
|
||||||
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:w-48" onClick={onClick}>
|
<td className="hidden align-top ltr:pl-6 rtl:pr-6 sm:table-cell sm:min-w-[10rem]" onClick={onClick}>
|
||||||
<div className="cursor-pointer py-4">
|
<div className="cursor-pointer py-4">
|
||||||
<div className="text-sm leading-6 text-gray-900">{startTime}</div>
|
<div className="text-sm leading-6 text-gray-900">{startTime}</div>
|
||||||
<div className="text-sm text-gray-500">
|
<div className="text-sm text-gray-500">
|
||||||
{dayjs(booking.startTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")} -{" "}
|
{dayjs(booking.startTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")} -{" "}
|
||||||
{dayjs(booking.endTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")}
|
{dayjs(booking.endTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-gray-400">
|
|
||||||
{booking.recurringBookings &&
|
{isPending && (
|
||||||
booking.eventType?.recurringEvent?.freq &&
|
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
|
||||||
(booking.listingStatus === "recurring" || booking.listingStatus === "cancelled") && (
|
{t("unconfirmed")}
|
||||||
<div className="underline decoration-gray-400 decoration-dashed underline-offset-2">
|
</Badge>
|
||||||
<div className="flex">
|
)}
|
||||||
<Tooltip
|
|
||||||
content={recurringStrings.map((aDate, key) => (
|
{booking.eventType?.team && (
|
||||||
<p key={key}>{aDate}</p>
|
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
|
||||||
))}>
|
{booking.eventType.team.name}
|
||||||
<div className="text-gray-600 dark:text-white">
|
</Badge>
|
||||||
<Icon.FiRefreshCcw
|
)}
|
||||||
strokeWidth="3"
|
|
||||||
className="float-left mr-1 mt-1.5 inline-block h-3 w-3 text-gray-400"
|
|
||||||
/>
|
|
||||||
<p className="mt-1 pl-5 text-xs">
|
|
||||||
{booking.status === BookingStatus.ACCEPTED
|
|
||||||
? `${t("event_remaining", {
|
|
||||||
count: recurringDates.length,
|
|
||||||
})}`
|
|
||||||
: getEveryFreqFor({
|
|
||||||
t,
|
|
||||||
recurringEvent: booking.eventType.recurringEvent,
|
|
||||||
recurringCount: booking.recurringBookings.length,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td className={"flex-1 px-4" + (isRejected ? " line-through" : "")} onClick={onClick}>
|
|
||||||
<div className="cursor-pointer py-4">
|
|
||||||
{!!booking?.eventType?.price && !booking.paid && (
|
{!!booking?.eventType?.price && !booking.paid && (
|
||||||
<Badge variant="orange" className="mb-2 ltr:mr-2 rtl:ml-2">
|
<Badge className="ltr:mr-2 rtl:ml-2" variant="orange">
|
||||||
{t("pending_payment")}
|
{t("pending_payment")}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className="mt-2 text-sm text-gray-400">
|
||||||
|
<RecurringBookingsTooltip
|
||||||
|
booking={booking}
|
||||||
|
recurringStrings={recurringStrings}
|
||||||
|
recurringDates={recurringDates}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className={"w-full px-4" + (isRejected ? " line-through" : "")} onClick={onClick}>
|
||||||
|
{/* Time and Badges for mobile */}
|
||||||
|
<div className="w-full pt-4 pb-2 sm:hidden">
|
||||||
|
<div className="flex w-full items-center justify-between sm:hidden">
|
||||||
|
<div className="text-sm leading-6 text-gray-900">{startTime}</div>
|
||||||
|
<div className="pr-2 text-sm text-gray-500">
|
||||||
|
{dayjs(booking.startTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")} -{" "}
|
||||||
|
{dayjs(booking.endTime).format(user && user.timeFormat === 12 ? "h:mma" : "HH:mm")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isPending && (
|
||||||
|
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange">
|
||||||
|
{t("unconfirmed")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{booking.eventType?.team && (
|
||||||
|
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="gray">
|
||||||
|
{booking.eventType.team.name}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{!!booking?.eventType?.price && !booking.paid && (
|
||||||
|
<Badge className="ltr:mr-2 rtl:ml-2 sm:hidden" variant="orange">
|
||||||
|
{t("pending_payment")}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
<div className="text-sm text-gray-400 sm:hidden">
|
||||||
|
<RecurringBookingsTooltip
|
||||||
|
booking={booking}
|
||||||
|
recurringStrings={recurringStrings}
|
||||||
|
recurringDates={recurringDates}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="cursor-pointer py-4">
|
||||||
<div
|
<div
|
||||||
title={booking.title}
|
title={booking.title}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"max-w-56 truncate text-sm font-medium leading-6 text-neutral-900 md:max-w-max",
|
"max-w-10/12 sm:max-w-56 text-sm font-medium leading-6 text-neutral-900 md:max-w-full",
|
||||||
isCancelled ? "line-through" : ""
|
isCancelled ? "line-through" : ""
|
||||||
)}>
|
)}>
|
||||||
{booking.title}
|
{booking.title}
|
||||||
<span> </span>
|
<span> </span>
|
||||||
{booking.eventType?.team && <Badge variant="gray">{booking.eventType.team.name}</Badge>}
|
|
||||||
|
|
||||||
{!!booking?.eventType?.price && !booking.paid && (
|
{!!booking?.eventType?.price && !booking.paid && (
|
||||||
<Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">Pending payment</Tag>
|
<Tag className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">Pending payment</Tag>
|
||||||
)}
|
)}
|
||||||
{isPending && (
|
|
||||||
<Badge variant="orange" className="hidden ltr:ml-2 rtl:mr-2 sm:inline-flex">
|
|
||||||
{t("unconfirmed")}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
{booking.description && (
|
{booking.description && (
|
||||||
<div
|
<div
|
||||||
@@ -351,8 +357,7 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td className="py-4 pl-4 text-right text-sm font-medium ltr:pr-4 rtl:pl-4 sm:pl-0">
|
||||||
<td className="whitespace-nowrap py-4 text-right text-sm font-medium ltr:pr-4 rtl:pl-4">
|
|
||||||
{isUpcoming && !isCancelled ? (
|
{isUpcoming && !isCancelled ? (
|
||||||
<>
|
<>
|
||||||
{isPending && user?.id === booking.user?.id && <TableActions actions={pendingActions} />}
|
{isPending && user?.id === booking.user?.id && <TableActions actions={pendingActions} />}
|
||||||
@@ -372,6 +377,61 @@ function BookingListItem(booking: BookingItemProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RecurringBookingsTooltipProps {
|
||||||
|
booking: BookingItemProps;
|
||||||
|
recurringStrings: string[];
|
||||||
|
recurringDates: Date[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const RecurringBookingsTooltip = ({
|
||||||
|
booking,
|
||||||
|
recurringStrings,
|
||||||
|
recurringDates,
|
||||||
|
}: RecurringBookingsTooltipProps) => {
|
||||||
|
const { t } = useLocale();
|
||||||
|
const now = new Date();
|
||||||
|
|
||||||
|
return (
|
||||||
|
(booking.recurringBookings &&
|
||||||
|
booking.eventType?.recurringEvent?.freq &&
|
||||||
|
(booking.listingStatus === "recurring" ||
|
||||||
|
booking.listingStatus === "unconfirmed" ||
|
||||||
|
booking.listingStatus === "cancelled") && (
|
||||||
|
<div className="underline decoration-gray-400 decoration-dashed underline-offset-2">
|
||||||
|
<div className="flex">
|
||||||
|
<Tooltip
|
||||||
|
content={recurringStrings.map((aDate, key) => (
|
||||||
|
<p key={key} className={classNames(recurringDates[key] < now && "line-through")}>
|
||||||
|
{aDate}
|
||||||
|
</p>
|
||||||
|
))}>
|
||||||
|
<div className="text-gray-600 dark:text-white">
|
||||||
|
<Icon.FiRefreshCcw
|
||||||
|
strokeWidth="3"
|
||||||
|
className="float-left mr-1 mt-1.5 inline-block h-3 w-3 text-gray-400"
|
||||||
|
/>
|
||||||
|
<p className="mt-1 pl-5 text-xs">
|
||||||
|
{booking.status === BookingStatus.ACCEPTED
|
||||||
|
? `${t("event_remaining", {
|
||||||
|
count: recurringDates.length,
|
||||||
|
})}`
|
||||||
|
: getEveryFreqFor({
|
||||||
|
t,
|
||||||
|
recurringEvent: booking.eventType.recurringEvent,
|
||||||
|
recurringCount: recurringDates.filter((date) => {
|
||||||
|
return date >= now;
|
||||||
|
}).length,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)) ||
|
||||||
|
null
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface UserProps {
|
interface UserProps {
|
||||||
id: number;
|
id: number;
|
||||||
name: string | null;
|
name: string | null;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { FC, useEffect, useState } from "react";
|
import { FC, useEffect, useState } from "react";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import TimezoneSelect, { ITimezoneOption } from "@calcom/ui/form/TimezoneSelect";
|
|
||||||
import { Switch } from "@calcom/ui/v2";
|
import { Switch } from "@calcom/ui/v2";
|
||||||
|
import TimezoneSelect, { ITimezoneOption } from "@calcom/ui/v2/core/TimezoneSelect";
|
||||||
|
|
||||||
import { is24h, timeZone } from "../../lib/clock";
|
import { is24h, timeZone } from "../../lib/clock";
|
||||||
|
|
||||||
@@ -10,9 +10,10 @@ type Props = {
|
|||||||
onSelectTimeZone: (selectedTimeZone: string) => void;
|
onSelectTimeZone: (selectedTimeZone: string) => void;
|
||||||
onToggle24hClock: (is24hClock: boolean) => void;
|
onToggle24hClock: (is24hClock: boolean) => void;
|
||||||
timeFormat: string;
|
timeFormat: string;
|
||||||
|
hideTimeFormatToggle?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const TimeOptions: FC<Props> = ({ onToggle24hClock, onSelectTimeZone, timeFormat }) => {
|
const TimeOptions: FC<Props> = ({ onToggle24hClock, onSelectTimeZone, timeFormat, hideTimeFormatToggle }) => {
|
||||||
const [selectedTimeZone, setSelectedTimeZone] = useState("");
|
const [selectedTimeZone, setSelectedTimeZone] = useState("");
|
||||||
const [is24hClock, setIs24hClock] = useState(timeFormat === "HH:mm" && true);
|
const [is24hClock, setIs24hClock] = useState(timeFormat === "HH:mm" && true);
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
@@ -33,20 +34,22 @@ const TimeOptions: FC<Props> = ({ onToggle24hClock, onSelectTimeZone, timeFormat
|
|||||||
};
|
};
|
||||||
|
|
||||||
return selectedTimeZone !== "" ? (
|
return selectedTimeZone !== "" ? (
|
||||||
<div className="max-w-80 dark:border-darkgray-300 dark:bg-darkgray-200 absolute z-10 w-full rounded-sm border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm">
|
<div className="dark:border-darkgray-300 dark:bg-darkgray-200 rounded-sm border border-gray-200 bg-white px-4 pt-4 pb-3 shadow-sm">
|
||||||
<div className="mb-4 flex">
|
<div className="mb-4 flex">
|
||||||
<div className="text-sm font-medium text-gray-600 dark:text-white">{t("time_options")}</div>
|
<div className="text-sm font-medium text-gray-600 dark:text-white">{t("time_options")}</div>
|
||||||
<div className="ml-auto flex items-center">
|
{!hideTimeFormatToggle && (
|
||||||
<label className="ltl:mr-3 mr-2 align-text-top text-sm font-medium text-neutral-700 ltr:ml-3 rtl:mr-3 dark:text-white">
|
<div className="ml-auto flex items-center">
|
||||||
{t("am_pm")}
|
<label className="ltl:mr-3 mr-2 align-text-top text-sm font-medium text-neutral-700 ltr:ml-3 rtl:mr-3 dark:text-white">
|
||||||
</label>
|
{t("am_pm")}
|
||||||
<Switch
|
</label>
|
||||||
name="24hClock"
|
<Switch
|
||||||
label={t("24_h")}
|
name="24hClock"
|
||||||
defaultChecked={is24hClock}
|
label={t("24_h")}
|
||||||
onCheckedChange={handle24hClockToggle}
|
defaultChecked={is24hClock}
|
||||||
/>
|
onCheckedChange={handle24hClockToggle}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<TimezoneSelect
|
<TimezoneSelect
|
||||||
id="timeZone"
|
id="timeZone"
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
// Get router variables
|
// Get router variables
|
||||||
|
import autoAnimate from "@formkit/auto-animate";
|
||||||
import { EventType } from "@prisma/client";
|
import { EventType } from "@prisma/client";
|
||||||
import { SchedulingType } from "@prisma/client";
|
import { SchedulingType } from "@prisma/client";
|
||||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
import * as Popover from "@radix-ui/react-popover";
|
||||||
import { TFunction } from "next-i18next";
|
import { TFunction } from "next-i18next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useReducer, useEffect, useMemo, useState } from "react";
|
import { useReducer, useEffect, useMemo, useState, useRef } from "react";
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
import { FormattedNumber, IntlProvider } from "react-intl";
|
import { FormattedNumber, IntlProvider } from "react-intl";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
@@ -24,8 +25,7 @@ import useTheme from "@calcom/lib/hooks/useTheme";
|
|||||||
import notEmpty from "@calcom/lib/notEmpty";
|
import notEmpty from "@calcom/lib/notEmpty";
|
||||||
import { getRecurringFreq } from "@calcom/lib/recurringStrings";
|
import { getRecurringFreq } from "@calcom/lib/recurringStrings";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||||
import { detectBrowserTimeFormat } from "@calcom/lib/timeFormat";
|
import { detectBrowserTimeFormat, getIs24hClockFromLocalStorage } from "@calcom/lib/timeFormat";
|
||||||
import { localStorage } from "@calcom/lib/webstorage";
|
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import DatePicker from "@calcom/ui/v2/modules/booker/DatePicker";
|
import DatePicker from "@calcom/ui/v2/modules/booker/DatePicker";
|
||||||
@@ -79,7 +79,7 @@ const useSlots = ({
|
|||||||
usernameList: string[];
|
usernameList: string[];
|
||||||
timeZone?: string;
|
timeZone?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const { data, isLoading, isIdle } = trpc.useQuery(
|
const { data, isLoading, isPaused } = trpc.useQuery(
|
||||||
[
|
[
|
||||||
"viewer.public.slots.getSchedule",
|
"viewer.public.slots.getSchedule",
|
||||||
{
|
{
|
||||||
@@ -101,8 +101,8 @@ const useSlots = ({
|
|||||||
}
|
}
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
// The very first time isIdle is set if auto-fetch is disabled, so isIdle should also be considered a loading state.
|
// The very first time isPaused is set if auto-fetch is disabled, so isPaused should also be considered a loading state.
|
||||||
return { slots: cachedSlots, isLoading: isLoading || isIdle };
|
return { slots: cachedSlots, isLoading: isLoading || isPaused };
|
||||||
};
|
};
|
||||||
|
|
||||||
const SlotPicker = ({
|
const SlotPicker = ({
|
||||||
@@ -129,6 +129,11 @@ const SlotPicker = ({
|
|||||||
const { date, setQuery: setDate } = useRouterQuery("date");
|
const { date, setQuery: setDate } = useRouterQuery("date");
|
||||||
const { month, setQuery: setMonth } = useRouterQuery("month");
|
const { month, setQuery: setMonth } = useRouterQuery("month");
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const slotPickerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
slotPickerRef.current && autoAnimate(slotPickerRef.current);
|
||||||
|
}, [slotPickerRef]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!router.isReady) return;
|
if (!router.isReady) return;
|
||||||
@@ -176,10 +181,8 @@ const SlotPicker = ({
|
|||||||
<DatePicker
|
<DatePicker
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"mt-8 w-full px-4 sm:mt-0 sm:min-w-[455px] md:px-5",
|
"mt-8 px-4 pb-4 sm:mt-0 md:min-w-[300px] md:px-5 lg:min-w-[455px]",
|
||||||
selectedDate
|
selectedDate ? "sm:dark:border-darkgray-200 border-gray-200 sm:border-r sm:p-4 sm:pr-6" : "sm:p-4"
|
||||||
? "sm:dark:border-darkgray-200 border-gray-200 sm:w-1/2 sm:border-r sm:p-4 sm:pr-6 md:w-1/3"
|
|
||||||
: "sm:p-4"
|
|
||||||
)}
|
)}
|
||||||
includedDates={Object.keys(slots).filter((k) => slots[k].length > 0)}
|
includedDates={Object.keys(slots).filter((k) => slots[k].length > 0)}
|
||||||
locale={isLocaleReady ? i18n.language : "en"}
|
locale={isLocaleReady ? i18n.language : "en"}
|
||||||
@@ -194,10 +197,10 @@ const SlotPicker = ({
|
|||||||
weekStart={weekStart}
|
weekStart={weekStart}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedDate && (
|
<div ref={slotPickerRef}>
|
||||||
<AvailableTimes
|
<AvailableTimes
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
slots={slots[selectedDate.format("YYYY-MM-DD")]}
|
slots={selectedDate && slots[selectedDate.format("YYYY-MM-DD")]}
|
||||||
date={selectedDate}
|
date={selectedDate}
|
||||||
timeFormat={timeFormat}
|
timeFormat={timeFormat}
|
||||||
eventTypeId={eventType.id}
|
eventTypeId={eventType.id}
|
||||||
@@ -206,7 +209,7 @@ const SlotPicker = ({
|
|||||||
recurringCount={recurringEventCount}
|
recurringCount={recurringEventCount}
|
||||||
ethSignature={ethSignature}
|
ethSignature={ethSignature}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -216,16 +219,18 @@ function TimezoneDropdown({
|
|||||||
onChangeTimeZone,
|
onChangeTimeZone,
|
||||||
timeZone,
|
timeZone,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
|
hideTimeFormatToggle,
|
||||||
}: {
|
}: {
|
||||||
onChangeTimeFormat: (newTimeFormat: string) => void;
|
onChangeTimeFormat: (newTimeFormat: string) => void;
|
||||||
onChangeTimeZone: (newTimeZone: string) => void;
|
onChangeTimeZone: (newTimeZone: string) => void;
|
||||||
timeZone?: string;
|
timeZone?: string;
|
||||||
timeFormat: string;
|
timeFormat: string;
|
||||||
|
hideTimeFormatToggle?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [isTimeOptionsOpen, setIsTimeOptionsOpen] = useState(false);
|
const [isTimeOptionsOpen, setIsTimeOptionsOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
handleToggle24hClock(localStorage.getItem("timeOption.is24hClock") === "true");
|
handleToggle24hClock(!!getIs24hClockFromLocalStorage());
|
||||||
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
@@ -241,8 +246,8 @@ function TimezoneDropdown({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapsible.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen} className="flex">
|
<Popover.Root open={isTimeOptionsOpen} onOpenChange={setIsTimeOptionsOpen}>
|
||||||
<Collapsible.Trigger className="min-w-32 dark:text-darkgray-600 mb-2 -ml-2 px-2 text-left text-gray-600">
|
<Popover.Trigger className="min-w-32 dark:text-darkgray-600 radix-state-open:bg-gray-200 dark:radix-state-open:bg-darkgray-200 group relative mb-2 -ml-2 inline-block rounded-md px-2 py-2 text-left text-gray-600">
|
||||||
<p className="text-sm font-medium">
|
<p className="text-sm font-medium">
|
||||||
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-[2px] inline-block h-4 w-4" />
|
<Icon.FiGlobe className="mr-[10px] ml-[2px] -mt-[2px] inline-block h-4 w-4" />
|
||||||
{timeZone}
|
{timeZone}
|
||||||
@@ -252,15 +257,21 @@ function TimezoneDropdown({
|
|||||||
<Icon.FiChevronDown className="ml-1 inline-block h-4 w-4" />
|
<Icon.FiChevronDown className="ml-1 inline-block h-4 w-4" />
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</Collapsible.Trigger>
|
</Popover.Trigger>
|
||||||
<Collapsible.Content>
|
<Popover.Portal>
|
||||||
<TimeOptions
|
<Popover.Content
|
||||||
onSelectTimeZone={handleSelectTimeZone}
|
hideWhenDetached
|
||||||
onToggle24hClock={handleToggle24hClock}
|
align="start"
|
||||||
timeFormat={timeFormat}
|
className="animate-fade-in-up absolute left-0 top-2 w-80 max-w-[calc(100vw_-_1.5rem)]">
|
||||||
/>
|
<TimeOptions
|
||||||
</Collapsible.Content>
|
onSelectTimeZone={handleSelectTimeZone}
|
||||||
</Collapsible.Root>
|
onToggle24hClock={handleToggle24hClock}
|
||||||
|
timeFormat={timeFormat}
|
||||||
|
hideTimeFormatToggle={hideTimeFormatToggle}
|
||||||
|
/>
|
||||||
|
</Popover.Content>
|
||||||
|
</Popover.Portal>
|
||||||
|
</Popover.Root>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +300,14 @@ const useRouterQuery = <T extends string>(name: T) => {
|
|||||||
|
|
||||||
export type Props = AvailabilityTeamPageProps | AvailabilityPageProps | DynamicAvailabilityPageProps;
|
export type Props = AvailabilityTeamPageProps | AvailabilityPageProps | DynamicAvailabilityPageProps;
|
||||||
|
|
||||||
|
const timeFormatTotimeFormatString = (timeFormat?: number | null) => {
|
||||||
|
if (!timeFormat) return null;
|
||||||
|
return timeFormat === 24 ? "HH:mm" : "h:mma";
|
||||||
|
};
|
||||||
|
|
||||||
const AvailabilityPage = ({ profile, eventType }: Props) => {
|
const AvailabilityPage = ({ profile, eventType }: Props) => {
|
||||||
|
const { data: user } = trpc.useQuery(["viewer.me"]);
|
||||||
|
const timeFormatFromProfile = timeFormatTotimeFormatString(user?.timeFormat);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isEmbed = useIsEmbed();
|
const isEmbed = useIsEmbed();
|
||||||
const query = dateQuerySchema.parse(router.query);
|
const query = dateQuerySchema.parse(router.query);
|
||||||
@@ -302,8 +320,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
const isBackgroundTransparent = useIsBackgroundTransparent();
|
const isBackgroundTransparent = useIsBackgroundTransparent();
|
||||||
|
|
||||||
const [timeZone, setTimeZone] = useState<string>();
|
const [timeZone, setTimeZone] = useState<string>();
|
||||||
const [timeFormat, setTimeFormat] = useState(detectBrowserTimeFormat);
|
const [timeFormat, setTimeFormat] = useState(timeFormatFromProfile || detectBrowserTimeFormat);
|
||||||
const [isAvailableTimesVisible, setIsAvailableTimesVisible] = useState<boolean>();
|
|
||||||
const [gateState, gateDispatcher] = useReducer(
|
const [gateState, gateDispatcher] = useReducer(
|
||||||
(state: GateState, newState: Partial<GateState>) => ({
|
(state: GateState, newState: Partial<GateState>) => ({
|
||||||
...state,
|
...state,
|
||||||
@@ -316,10 +333,6 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
setTimeZone(localStorageTimeZone() || dayjs.tz.guess());
|
setTimeZone(localStorageTimeZone() || dayjs.tz.guess());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setIsAvailableTimesVisible(!!query.date);
|
|
||||||
}, [query.date]);
|
|
||||||
|
|
||||||
// TODO: Improve this;
|
// TODO: Improve this;
|
||||||
useExposePlanGlobally(eventType.users.length === 1 ? eventType.users[0].plan : "PRO");
|
useExposePlanGlobally(eventType.users.length === 1 ? eventType.users[0].plan : "PRO");
|
||||||
|
|
||||||
@@ -338,14 +351,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
|
|
||||||
// get dynamic user list here
|
// get dynamic user list here
|
||||||
const userList = eventType.users ? eventType.users.map((user) => user.username).filter(notEmpty) : [];
|
const userList = eventType.users ? eventType.users.map((user) => user.username).filter(notEmpty) : [];
|
||||||
// Recurring event sidebar requires more space
|
|
||||||
const maxWidth = isAvailableTimesVisible
|
|
||||||
? recurringEventCount
|
|
||||||
? "max-w-6xl"
|
|
||||||
: "max-w-5xl"
|
|
||||||
: recurringEventCount
|
|
||||||
? "max-w-4xl"
|
|
||||||
: "max-w-3xl";
|
|
||||||
const timezoneDropdown = useMemo(
|
const timezoneDropdown = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<TimezoneDropdown
|
<TimezoneDropdown
|
||||||
@@ -353,9 +359,12 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
onChangeTimeFormat={setTimeFormat}
|
onChangeTimeFormat={setTimeFormat}
|
||||||
timeZone={timeZone}
|
timeZone={timeZone}
|
||||||
onChangeTimeZone={setTimeZone}
|
onChangeTimeZone={setTimeZone}
|
||||||
|
// Currently we don't allow the user to change the timeformat when they're logged in,
|
||||||
|
// the only way to change it is if they go to their profile.
|
||||||
|
hideTimeFormatToggle={!!timeFormatFromProfile}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[timeZone, timeFormat]
|
[timeZone, timeFormat, timeFormatFromProfile]
|
||||||
);
|
);
|
||||||
const rawSlug = profile.slug ? profile.slug.split("/") : [];
|
const rawSlug = profile.slug ? profile.slug.split("/") : [];
|
||||||
if (rawSlug.length > 1) rawSlug.pop(); //team events have team name as slug, but user events have [user]/[type] as slug.
|
if (rawSlug.length > 1) rawSlug.pop(); //team events have team name as slug, but user events have [user]/[type] as slug.
|
||||||
@@ -385,201 +394,109 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
<div>
|
<div>
|
||||||
<main
|
<main
|
||||||
className={classNames(
|
className={classNames(
|
||||||
shouldAlignCentrally ? "mx-auto" : "",
|
"flex flex-col",
|
||||||
isEmbed
|
shouldAlignCentrally ? "items-center" : "items-start",
|
||||||
? classNames(maxWidth)
|
!isEmbed && classNames("mx-auto my-0 ease-in-out md:my-24")
|
||||||
: classNames("transition-max-width mx-auto my-0 duration-500 ease-in-out md:my-24", maxWidth)
|
|
||||||
)}>
|
)}>
|
||||||
<div
|
<div>
|
||||||
style={availabilityDatePickerEmbedStyles}
|
<div
|
||||||
className={classNames(
|
style={availabilityDatePickerEmbedStyles}
|
||||||
isBackgroundTransparent ? "" : "dark:bg-darkgray-100 sm:dark:border-darkgray-300 bg-white",
|
className={classNames(
|
||||||
"border-bookinglightest overflow-hidden rounded-md md:border",
|
isBackgroundTransparent
|
||||||
isEmbed ? "mx-auto" : maxWidth
|
? ""
|
||||||
)}>
|
: "dark:bg-darkgray-100 sm:dark:border-darkgray-300 bg-white pb-4 md:pb-0",
|
||||||
{/* mobile: details */}
|
"border-bookinglightest overflow-hidden rounded-md md:border",
|
||||||
<div className="block px-4 pt-4 sm:p-8 md:hidden">
|
isEmbed && "mx-auto"
|
||||||
<div>
|
)}>
|
||||||
<UserAvatars
|
<div className="overflow-hidden md:flex">
|
||||||
profile={profile}
|
<div
|
||||||
users={eventType.users}
|
className={classNames(
|
||||||
showMembers={eventType.schedulingType !== SchedulingType.ROUND_ROBIN}
|
"sm:dark:border-darkgray-200 flex flex-col border-gray-200 p-5 sm:border-r",
|
||||||
size={9}
|
"min-w-full md:w-[280px] md:min-w-[280px]",
|
||||||
truncateAfter={5}
|
recurringEventCount && "xl:w-[380px] xl:min-w-[380px]"
|
||||||
/>
|
)}>
|
||||||
<div className="mt-4">
|
<UserAvatars
|
||||||
<div className="dark:text-darkgray-900 mt-2 gap-2">
|
profile={profile}
|
||||||
<p className="break-words text-sm font-medium text-gray-600 dark:text-gray-300">
|
users={eventType.users}
|
||||||
{profile.name}
|
showMembers={eventType.schedulingType !== SchedulingType.ROUND_ROBIN}
|
||||||
</p>
|
size={10}
|
||||||
<h1 className="text-bookingdark dark:text-darkgray-900 mb-4 break-words text-xl font-semibold">
|
truncateAfter={3}
|
||||||
{eventType.title}
|
/>
|
||||||
</h1>
|
<h2 className="mt-2 break-words text-sm font-medium text-gray-600 dark:text-gray-300">
|
||||||
<div className="flex flex-col space-y-3">
|
{profile.name}
|
||||||
{eventType?.description && (
|
</h2>
|
||||||
<div className="dark:text-darkgray-600 flex py-1 text-sm font-medium text-gray-600">
|
<h1 className="font-cal dark:text-darkgray-900 mb-6 break-words text-2xl font-semibold text-gray-900">
|
||||||
<div>
|
{eventType.title}
|
||||||
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
|
</h1>
|
||||||
</div>
|
<div className="dark:text-darkgray-600 flex flex-col space-y-3 text-sm font-medium text-gray-600">
|
||||||
<EventTypeDescriptionSafeHTML eventType={eventType} />
|
{eventType?.description && (
|
||||||
|
<div className="flex">
|
||||||
|
<div>
|
||||||
|
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
<EventTypeDescriptionSafeHTML eventType={eventType} />
|
||||||
{eventType?.requiresConfirmation && (
|
</div>
|
||||||
<p className="dark:text-darkgray-600 text-gray-600">
|
)}
|
||||||
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
|
{eventType?.requiresConfirmation && (
|
||||||
{t("requires_confirmation")}
|
<div className="flex items-center">
|
||||||
</p>
|
<div>
|
||||||
)}
|
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
|
||||||
<AvailableEventLocations locations={eventType.locations} />
|
</div>
|
||||||
<p className="dark:text-darkgray-600 text-gray-600">
|
{t("requires_confirmation")}
|
||||||
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
|
</div>
|
||||||
{eventType.length} {t("minutes")}
|
)}
|
||||||
|
<AvailableEventLocations locations={eventType.locations} />
|
||||||
|
<p className="text-sm font-medium">
|
||||||
|
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
|
||||||
|
{eventType.length} {t("minutes")}
|
||||||
|
</p>
|
||||||
|
{!rescheduleUid && eventType.recurringEvent && (
|
||||||
|
<div className="flex items-start text-sm font-medium">
|
||||||
|
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-[7px] ml-[2px] inline-block h-4 w-4 " />
|
||||||
|
<div>
|
||||||
|
<p className="mb-1 -ml-2 inline px-2 py-1">
|
||||||
|
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="1"
|
||||||
|
max={eventType.recurringEvent.count}
|
||||||
|
className="w-15 dark:bg-darkgray-200 h-7 rounded-sm border-gray-300 bg-white text-sm font-medium [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500"
|
||||||
|
defaultValue={eventType.recurringEvent.count}
|
||||||
|
onChange={(event) => {
|
||||||
|
setRecurringEventCount(parseInt(event?.target.value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<p className="inline">
|
||||||
|
{t("occurrence", {
|
||||||
|
count: recurringEventCount,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{eventType.price > 0 && (
|
||||||
|
<p className="-ml-2 px-2 text-sm font-medium">
|
||||||
|
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
|
||||||
|
<IntlProvider locale="en">
|
||||||
|
<FormattedNumber
|
||||||
|
value={eventType.price / 100.0}
|
||||||
|
style="currency"
|
||||||
|
currency={eventType.currency.toUpperCase()}
|
||||||
|
/>
|
||||||
|
</IntlProvider>
|
||||||
</p>
|
</p>
|
||||||
{eventType.price > 0 && (
|
)}
|
||||||
<div className="dark:text-darkgray-600 text-gray-600">
|
{timezoneDropdown}
|
||||||
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
|
|
||||||
<IntlProvider locale="en">
|
|
||||||
<FormattedNumber
|
|
||||||
value={eventType.price / 100.0}
|
|
||||||
style="currency"
|
|
||||||
currency={eventType.currency.toUpperCase()}
|
|
||||||
/>
|
|
||||||
</IntlProvider>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!rescheduleUid && eventType.recurringEvent && (
|
|
||||||
<div className="dark:text-darkgray-600 flex items-center text-gray-600">
|
|
||||||
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-1 ml-[2px] inline-block h-4 w-4 shrink-0 text-gray-500" />
|
|
||||||
<div>
|
|
||||||
<p className="mb-1 -ml-2 inline px-2 py-1">
|
|
||||||
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
|
|
||||||
</p>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max={eventType.recurringEvent.count}
|
|
||||||
className="w-15 dark:text-darkgray-600 h-7 rounded-sm border-gray-300 bg-white text-sm text-gray-600 [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500 dark:bg-gray-600"
|
|
||||||
defaultValue={eventType.recurringEvent.count}
|
|
||||||
onChange={(event) => {
|
|
||||||
setRecurringEventCount(parseInt(event?.target.value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<p className="dark:text-darkgray-600 inline text-gray-600">
|
|
||||||
{t("occurrence", {
|
|
||||||
count: recurringEventCount,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{timezoneDropdown}
|
|
||||||
|
|
||||||
<div className="md:hidden">
|
|
||||||
{/* Temp disabled booking?.startTime && rescheduleUid && (
|
|
||||||
<div>
|
|
||||||
<p
|
|
||||||
className="mt-8 text-gray-600 dark:text-darkgray-600"
|
|
||||||
data-testid="former_time_p_mobile">
|
|
||||||
{t("former_time")}
|
|
||||||
</p>
|
|
||||||
<p className="text-gray-500 line-through dark:text-darkgray-600">
|
|
||||||
<CalendarIcon className="mr-[10px] -mt-1 inline-block h-4 w-4 text-gray-500" />
|
|
||||||
{typeof booking.startTime === "string" &&
|
|
||||||
parseDate(dayjs(booking.startTime), i18n)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)*/}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="overflow-hidden sm:flex">
|
{!isEmbed && (
|
||||||
<div
|
<div className="mt-auto hidden md:block">
|
||||||
className={
|
<GoBackToPreviousPage t={t} />
|
||||||
"sm:dark:border-darkgray-200 hidden overflow-hidden border-gray-200 p-5 sm:border-r md:flex md:flex-col " +
|
|
||||||
(isAvailableTimesVisible ? "sm:w-1/3" : recurringEventCount ? "sm:w-2/3" : "sm:w-1/2")
|
|
||||||
}>
|
|
||||||
<UserAvatars
|
|
||||||
profile={profile}
|
|
||||||
users={eventType.users}
|
|
||||||
showMembers={eventType.schedulingType !== SchedulingType.ROUND_ROBIN}
|
|
||||||
size={10}
|
|
||||||
truncateAfter={3}
|
|
||||||
/>
|
|
||||||
<h2 className="break-words text-sm font-medium text-gray-600 dark:text-gray-300 lg:mt-2">
|
|
||||||
{profile.name}
|
|
||||||
</h2>
|
|
||||||
<h1 className="font-cal dark:text-darkgray-900 mb-6 break-words text-2xl text-gray-900">
|
|
||||||
{eventType.title}
|
|
||||||
</h1>
|
|
||||||
<div className="dark:text-darkgray-600 flex flex-col space-y-3 text-sm font-medium text-gray-600">
|
|
||||||
{eventType?.description && (
|
|
||||||
<div className="flex">
|
|
||||||
<div>
|
|
||||||
<Icon.FiInfo className="mr-[10px] ml-[2px] inline-block h-4 w-4" />
|
|
||||||
</div>
|
|
||||||
<EventTypeDescriptionSafeHTML eventType={eventType} />
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{eventType?.requiresConfirmation && (
|
|
||||||
<div className="flex items-center">
|
|
||||||
<div>
|
|
||||||
<Icon.FiCheckSquare className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 " />
|
|
||||||
</div>
|
|
||||||
{t("requires_confirmation")}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<AvailableEventLocations locations={eventType.locations} />
|
|
||||||
<p className="text-sm font-medium">
|
|
||||||
<Icon.FiClock className="mr-[10px] -mt-1 ml-[2px] inline-block h-4 w-4" />
|
|
||||||
{eventType.length} {t("minutes")}
|
|
||||||
</p>
|
|
||||||
{!rescheduleUid && eventType.recurringEvent && (
|
|
||||||
<div className="flex items-start text-sm font-medium">
|
|
||||||
<Icon.FiRefreshCcw className="float-left mr-[10px] mt-[7px] ml-[2px] inline-block h-4 w-4 " />
|
|
||||||
<div>
|
|
||||||
<p className="mb-1 -ml-2 inline px-2 py-1">
|
|
||||||
{getRecurringFreq({ t, recurringEvent: eventType.recurringEvent })}
|
|
||||||
</p>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
max={eventType.recurringEvent.count}
|
|
||||||
className="w-15 dark:bg-darkgray-200 h-7 rounded-sm border-gray-300 bg-white text-sm font-medium [appearance:textfield] ltr:mr-2 rtl:ml-2 dark:border-gray-500"
|
|
||||||
defaultValue={eventType.recurringEvent.count}
|
|
||||||
onChange={(event) => {
|
|
||||||
setRecurringEventCount(parseInt(event?.target.value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<p className="inline">
|
|
||||||
{t("occurrence", {
|
|
||||||
count: recurringEventCount,
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{eventType.price > 0 && (
|
|
||||||
<p className="-ml-2 px-2 text-sm font-medium">
|
|
||||||
<Icon.FiCreditCard className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4" />
|
|
||||||
<IntlProvider locale="en">
|
|
||||||
<FormattedNumber
|
|
||||||
value={eventType.price / 100.0}
|
|
||||||
style="currency"
|
|
||||||
currency={eventType.currency.toUpperCase()}
|
|
||||||
/>
|
|
||||||
</IntlProvider>
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
{timezoneDropdown}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!isEmbed && <GoBackToPreviousPage t={t} />}
|
{/* Temporarily disabled - booking?.startTime && rescheduleUid && (
|
||||||
|
|
||||||
{/* Temporarily disabled - booking?.startTime && rescheduleUid && (
|
|
||||||
<div>
|
<div>
|
||||||
<p
|
<p
|
||||||
className="mt-4 mb-3 text-gray-600 dark:text-darkgray-600"
|
className="mt-4 mb-3 text-gray-600 dark:text-darkgray-600"
|
||||||
@@ -592,26 +509,33 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)*/}
|
)*/}
|
||||||
|
</div>
|
||||||
|
<SlotPicker
|
||||||
|
weekStart={
|
||||||
|
typeof profile.weekStart === "string"
|
||||||
|
? ([
|
||||||
|
"Sunday",
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
].indexOf(profile.weekStart) as 0 | 1 | 2 | 3 | 4 | 5 | 6)
|
||||||
|
: profile.weekStart /* Allows providing weekStart as number */
|
||||||
|
}
|
||||||
|
eventType={eventType}
|
||||||
|
timeFormat={timeFormat}
|
||||||
|
timeZone={timeZone}
|
||||||
|
users={userList}
|
||||||
|
seatsPerTimeSlot={eventType.seatsPerTimeSlot || undefined}
|
||||||
|
recurringEventCount={recurringEventCount}
|
||||||
|
ethSignature={gateState.rainbowToken}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SlotPicker
|
|
||||||
weekStart={
|
|
||||||
typeof profile.weekStart === "string"
|
|
||||||
? (["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].indexOf(
|
|
||||||
profile.weekStart
|
|
||||||
) as 0 | 1 | 2 | 3 | 4 | 5 | 6)
|
|
||||||
: profile.weekStart /* Allows providing weekStart as number */
|
|
||||||
}
|
|
||||||
eventType={eventType}
|
|
||||||
timeFormat={timeFormat}
|
|
||||||
timeZone={timeZone}
|
|
||||||
users={userList}
|
|
||||||
seatsPerTimeSlot={eventType.seatsPerTimeSlot || undefined}
|
|
||||||
recurringEventCount={recurringEventCount}
|
|
||||||
ethSignature={gateState.rainbowToken}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
{(!eventType.users[0] || !isBrandingHidden(eventType.users[0])) && !isEmbed && <PoweredByCal />}
|
||||||
</div>
|
</div>
|
||||||
{(!eventType.users[0] || !isBrandingHidden(eventType.users[0])) && !isEmbed && <PoweredByCal />}
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
<Toaster position="bottom-right" />
|
<Toaster position="bottom-right" />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { EventTypeCustomInputType, WorkflowActions } from "@prisma/client";
|
import { EventTypeCustomInputType, WorkflowActions } from "@prisma/client";
|
||||||
import { SchedulingType } from "@prisma/client";
|
import { SchedulingType } from "@prisma/client";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { isValidPhoneNumber } from "libphonenumber-js";
|
import { isValidPhoneNumber } from "libphonenumber-js";
|
||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
@@ -9,7 +10,6 @@ import { useEffect, useMemo, useState, useReducer } from "react";
|
|||||||
import { Controller, useForm, useWatch } from "react-hook-form";
|
import { Controller, useForm, useWatch } from "react-hook-form";
|
||||||
import { FormattedNumber, IntlProvider } from "react-intl";
|
import { FormattedNumber, IntlProvider } from "react-intl";
|
||||||
import { ReactMultiEmail } from "react-multi-email";
|
import { ReactMultiEmail } from "react-multi-email";
|
||||||
import { useMutation } from "react-query";
|
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@@ -445,7 +445,6 @@ const BookingPage = ({
|
|||||||
<div
|
<div
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"main overflow-hidden",
|
"main overflow-hidden",
|
||||||
isEmbed ? "" : "border border-gray-200",
|
|
||||||
isBackgroundTransparent ? "" : "dark:border-1 dark:bg-darkgray-100 bg-white",
|
isBackgroundTransparent ? "" : "dark:border-1 dark:bg-darkgray-100 bg-white",
|
||||||
"dark:border-darkgray-300 rounded-md sm:border"
|
"dark:border-darkgray-300 rounded-md sm:border"
|
||||||
)}>
|
)}>
|
||||||
@@ -713,83 +712,81 @@ const BookingPage = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{input.type === EventTypeCustomInputType.BOOL && (
|
{input.type === EventTypeCustomInputType.BOOL && (
|
||||||
<div className="flex h-5 items-center">
|
<div className="my-6">
|
||||||
<input
|
<div className="flex">
|
||||||
type="checkbox"
|
<input
|
||||||
{...bookingForm.register(`customInputs.${input.id}`, {
|
type="checkbox"
|
||||||
required: input.required,
|
{...bookingForm.register(`customInputs.${input.id}`, {
|
||||||
})}
|
required: input.required,
|
||||||
required={input.required}
|
})}
|
||||||
id={"custom_" + input.id}
|
required={input.required}
|
||||||
className="h-4 w-4 rounded border-gray-300 text-black focus:ring-black disabled:bg-gray-200 ltr:mr-2 rtl:ml-2 disabled:dark:text-gray-500"
|
id={"custom_" + input.id}
|
||||||
placeholder=""
|
className="h-4 w-4 rounded border-gray-300 text-black focus:ring-black disabled:bg-gray-200 ltr:mr-2 rtl:ml-2 disabled:dark:text-gray-500"
|
||||||
disabled={disabledExceptForOwner}
|
placeholder=""
|
||||||
/>
|
disabled={disabledExceptForOwner}
|
||||||
<label
|
/>
|
||||||
htmlFor={"custom_" + input.id}
|
<label
|
||||||
className="mb-1 block text-sm font-medium text-gray-700 dark:text-white">
|
htmlFor={"custom_" + input.id}
|
||||||
{input.label}
|
className="-mt-px block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
</label>
|
{input.label}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{!eventType.disableGuests && (
|
{!eventType.disableGuests && guestToggle && (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
{guestToggle && (
|
<div>
|
||||||
<div>
|
<label
|
||||||
<label
|
htmlFor="guests"
|
||||||
htmlFor="guests"
|
className="mb-1 block text-sm font-medium text-gray-700 dark:text-white">
|
||||||
className="mb-1 block text-sm font-medium text-gray-700 dark:text-white">
|
{t("guests")}
|
||||||
{t("guests")}
|
</label>
|
||||||
</label>
|
{!disableInput && (
|
||||||
{!disableInput && (
|
<Controller
|
||||||
<Controller
|
control={bookingForm.control}
|
||||||
control={bookingForm.control}
|
name="guests"
|
||||||
name="guests"
|
render={({ field: { onChange, value } }) => (
|
||||||
render={({ field: { onChange, value } }) => (
|
<ReactMultiEmail
|
||||||
<ReactMultiEmail
|
className="relative"
|
||||||
className="relative"
|
placeholder={<span className="dark:text-darkgray-600">guest@example.com</span>}
|
||||||
placeholder={
|
emails={value}
|
||||||
<span className="dark:text-darkgray-600">guest@example.com</span>
|
onChange={onChange}
|
||||||
}
|
getLabel={(
|
||||||
emails={value}
|
email: string,
|
||||||
onChange={onChange}
|
index: number,
|
||||||
getLabel={(
|
removeEmail: (index: number) => void
|
||||||
email: string,
|
) => {
|
||||||
index: number,
|
return (
|
||||||
removeEmail: (index: number) => void
|
<div data-tag key={index} className="cursor-pointer">
|
||||||
) => {
|
{email}
|
||||||
return (
|
{!disableInput && (
|
||||||
<div data-tag key={index} className="cursor-pointer">
|
<span data-tag-handle onClick={() => removeEmail(index)}>
|
||||||
{email}
|
×
|
||||||
{!disableInput && (
|
</span>
|
||||||
<span data-tag-handle onClick={() => removeEmail(index)}>
|
)}
|
||||||
×
|
</div>
|
||||||
</span>
|
);
|
||||||
)}
|
}}
|
||||||
</div>
|
/>
|
||||||
);
|
)}
|
||||||
}}
|
/>
|
||||||
/>
|
)}
|
||||||
)}
|
{/* Custom code when guest emails should not be editable */}
|
||||||
/>
|
{disableInput && guestListEmails && guestListEmails.length > 0 && (
|
||||||
)}
|
<div data-tag className="react-multi-email">
|
||||||
{/* Custom code when guest emails should not be editable */}
|
{/* // @TODO: user owners are appearing as guest here when should be only user input */}
|
||||||
{disableInput && guestListEmails && guestListEmails.length > 0 && (
|
{guestListEmails.map((email, index) => {
|
||||||
<div data-tag className="react-multi-email">
|
return (
|
||||||
{/* // @TODO: user owners are appearing as guest here when should be only user input */}
|
<div key={index} className="cursor-pointer">
|
||||||
{guestListEmails.map((email, index) => {
|
<span data-tag>{email}</span>
|
||||||
return (
|
</div>
|
||||||
<div key={index} className="cursor-pointer">
|
);
|
||||||
<span data-tag>{email}</span>
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
)}
|
||||||
})}
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{isSmsReminderNumberNeeded && selectedLocationType !== LocationType.Phone && (
|
{isSmsReminderNumberNeeded && selectedLocationType !== LocationType.Phone && (
|
||||||
@@ -845,15 +842,16 @@ const BookingPage = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end space-x-2 rtl:space-x-reverse">
|
<div className="flex justify-end space-x-2 rtl:space-x-reverse">
|
||||||
{!guestToggle && (
|
{!eventType.disableGuests && !guestToggle && (
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="secondary"
|
color="minimalSecondary"
|
||||||
|
size="icon"
|
||||||
|
tooltip={t("additional_guests")}
|
||||||
|
StartIcon={Icon.FiUserPlus}
|
||||||
onClick={() => setGuestToggle(!guestToggle)}
|
onClick={() => setGuestToggle(!guestToggle)}
|
||||||
className="dark:bg-darkmodebrand dark:text-darkmodebrandcontrast dark:hover:border-darkmodebrandcontrast mr-auto dark:border-transparent">
|
className="mr-auto"
|
||||||
<Icon.FiUserPlus className="mr-2" />
|
/>
|
||||||
{t("additional_guests")}
|
|
||||||
</Button>
|
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { RescheduleResponse } from "pages/api/book/request-reschedule";
|
import { RescheduleResponse } from "pages/api/book/request-reschedule";
|
||||||
import React, { useState, Dispatch, SetStateAction } from "react";
|
import React, { useState, Dispatch, SetStateAction } from "react";
|
||||||
import { useMutation } from "react-query";
|
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ const CalendarItem = (props: ICalendarItem) => {
|
|||||||
const { title, imageSrc, type } = props;
|
const { title, imageSrc, type } = props;
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-row items-center p-5">
|
<div className="flex flex-row items-center justify-between p-5">
|
||||||
<img src={imageSrc} alt={title} className="h-8 w-8" />
|
<div className="flex items-center space-x-3">
|
||||||
<p className="mx-3 text-sm font-bold">{title}</p>
|
<img src={imageSrc} alt={title} className="h-8 w-8" />
|
||||||
|
<p className="text-sm font-bold">{title}</p>
|
||||||
|
</div>
|
||||||
<InstallAppButtonWithoutPlanCheck
|
<InstallAppButtonWithoutPlanCheck
|
||||||
type={type}
|
type={type}
|
||||||
render={(buttonProps) => (
|
render={(buttonProps) => (
|
||||||
@@ -29,8 +30,7 @@ const CalendarItem = (props: ICalendarItem) => {
|
|||||||
// Save cookie key to return url step
|
// Save cookie key to return url step
|
||||||
document.cookie = `return-to=${window.location.href};path=/;max-age=3600;SameSite=Lax`;
|
document.cookie = `return-to=${window.location.href};path=/;max-age=3600;SameSite=Lax`;
|
||||||
buttonProps && buttonProps.onClick && buttonProps?.onClick(event);
|
buttonProps && buttonProps.onClick && buttonProps?.onClick(event);
|
||||||
}}
|
}}>
|
||||||
className="ml-auto rounded-md border border-gray-200 py-[10px] px-4 text-sm font-bold">
|
|
||||||
{t("connect")}
|
{t("connect")}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMutation } from "react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ const ConnectedCalendars = (props: IConnectCalendarsProps) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Already connected calendars */}
|
{/* Already connected calendars */}
|
||||||
{firstCalendar &&
|
{!queryConnectedCalendars.isLoading &&
|
||||||
|
firstCalendar &&
|
||||||
firstCalendar.integration &&
|
firstCalendar.integration &&
|
||||||
firstCalendar.integration.title &&
|
firstCalendar.integration.title &&
|
||||||
firstCalendar.integration.imageSrc && (
|
firstCalendar.integration.imageSrc && (
|
||||||
@@ -75,7 +76,7 @@ const ConnectedCalendars = (props: IConnectCalendarsProps) => {
|
|||||||
</List>
|
</List>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{queryConnectedCalendars.isLoading && (
|
{queryIntegrations.isLoading && (
|
||||||
<ul className="divide-y divide-gray-200 rounded-md border border-gray-200 bg-white p-0 dark:bg-black">
|
<ul className="divide-y divide-gray-200 rounded-md border border-gray-200 bg-white p-0 dark:bg-black">
|
||||||
{[0, 0, 0, 0].map((_item, index) => {
|
{[0, 0, 0, 0].map((_item, index) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ const UserProfile = (props: IUserProfile) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{errors.bio && (
|
{errors.bio && (
|
||||||
<p data-testid="required" className="text-xs italic text-red-500">
|
<p data-testid="required" className="py-2 text-xs text-red-500">
|
||||||
{t("required")}
|
{t("required")}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ const UserSettings = (props: IUserSettingsProps) => {
|
|||||||
className="w-full rounded-md border border-gray-300 text-sm"
|
className="w-full rounded-md border border-gray-300 text-sm"
|
||||||
/>
|
/>
|
||||||
{errors.name && (
|
{errors.name && (
|
||||||
<p data-testid="required" className="text-xs italic text-red-500">
|
<p data-testid="required" className="py-2 text-xs text-red-500">
|
||||||
{t("required")}
|
{t("required")}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { useMutation } from "react-query";
|
|
||||||
|
|
||||||
import { InstallAppButton } from "@calcom/app-store/components";
|
import { InstallAppButton } from "@calcom/app-store/components";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
@@ -185,8 +185,8 @@ function ConnectedCalendarsList(props: Props) {
|
|||||||
) : (
|
) : (
|
||||||
<Alert
|
<Alert
|
||||||
severity="warning"
|
severity="warning"
|
||||||
title={t("calendar_error")}
|
title={t("something_went_wrong")}
|
||||||
message={item.error?.message}
|
message={t("calendar_error")}
|
||||||
actions={
|
actions={
|
||||||
<DisconnectIntegration
|
<DisconnectIntegration
|
||||||
id={item.credentialId}
|
id={item.credentialId}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useMutation } from "react-query";
|
|
||||||
|
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
import { ButtonBaseProps } from "@calcom/ui/Button";
|
import { ButtonBaseProps } from "@calcom/ui/Button";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import Button from "@calcom/ui/v2/core/Button";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
|
import ButtonGroup from "@calcom/ui/v2/core/ButtonGroup";
|
||||||
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
||||||
import { Dialog, DialogTrigger } from "@calcom/ui/v2/core/Dialog";
|
import { Dialog, DialogTrigger } from "@calcom/ui/v2/core/Dialog";
|
||||||
import Dropdown, {
|
import Dropdown, {
|
||||||
@@ -14,6 +15,7 @@ import Dropdown, {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
|
DropdownItem,
|
||||||
} from "@calcom/ui/v2/core/Dropdown";
|
} from "@calcom/ui/v2/core/Dropdown";
|
||||||
import { Tooltip } from "@calcom/ui/v2/core/Tooltip";
|
import { Tooltip } from "@calcom/ui/v2/core/Tooltip";
|
||||||
import showToast from "@calcom/ui/v2/core/notifications";
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
@@ -135,108 +137,103 @@ export default function TeamListItem(props: Props) {
|
|||||||
{!isInvitee && (
|
{!isInvitee && (
|
||||||
<div className="flex space-x-2 rtl:space-x-reverse">
|
<div className="flex space-x-2 rtl:space-x-reverse">
|
||||||
<TeamRole role={team.role} />
|
<TeamRole role={team.role} />
|
||||||
|
<ButtonGroup combined>
|
||||||
<Tooltip side="top" content={t("copy_link_team")}>
|
<Tooltip content={t("copy_link_team")}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
color="secondary"
|
||||||
navigator.clipboard.writeText(process.env.NEXT_PUBLIC_WEBSITE_URL + "/team/" + team.slug);
|
onClick={() => {
|
||||||
showToast(t("link_copied"), "success");
|
navigator.clipboard.writeText(
|
||||||
}}
|
process.env.NEXT_PUBLIC_WEBSITE_URL + "/team/" + team.slug
|
||||||
className="h-10 w-10 transition-none"
|
);
|
||||||
size="icon"
|
showToast(t("link_copied"), "success");
|
||||||
color="minimal"
|
}}
|
||||||
type="button">
|
size="icon"
|
||||||
<Icon.FiLink className="h-5 w-5 group-hover:text-gray-600" />
|
StartIcon={Icon.FiLink}
|
||||||
</Button>
|
combined
|
||||||
</Tooltip>
|
/>
|
||||||
<Dropdown>
|
</Tooltip>
|
||||||
<DropdownMenuTrigger asChild>
|
<Dropdown>
|
||||||
<Button type="button" color="minimal" size="icon" StartIcon={Icon.FiMoreHorizontal} />
|
<DropdownMenuTrigger asChild>
|
||||||
</DropdownMenuTrigger>
|
<Button type="button" color="secondary" size="icon" StartIcon={Icon.FiMoreHorizontal} />
|
||||||
<DropdownMenuContent hidden={hideDropdown}>
|
</DropdownMenuTrigger>
|
||||||
{isAdmin && (
|
<DropdownMenuContent hidden={hideDropdown}>
|
||||||
|
{isAdmin && (
|
||||||
|
<DropdownMenuItem>
|
||||||
|
<DropdownItem
|
||||||
|
type="button"
|
||||||
|
href={"/settings/teams/" + team.id + "/profile"}
|
||||||
|
StartIcon={Icon.FiEdit2}>
|
||||||
|
{t("edit_team") as string}
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<Link href={"/settings/teams/" + team.id + "/profile"}>
|
<DropdownItem
|
||||||
<a>
|
type="button"
|
||||||
<Button
|
target="_blank"
|
||||||
color="minimal"
|
href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}`}
|
||||||
className="w-full rounded-none font-medium"
|
StartIcon={Icon.FiExternalLink}>
|
||||||
StartIcon={Icon.FiEdit2}>
|
{t("preview_team") as string}
|
||||||
{t("edit_team")}
|
</DropdownItem>
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
)}
|
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
||||||
<DropdownMenuItem>
|
{isOwner && (
|
||||||
<Link href={`${process.env.NEXT_PUBLIC_WEBSITE_URL}/team/${team.slug}`} passHref={true}>
|
<DropdownMenuItem>
|
||||||
<a target="_blank">
|
<Dialog open={hideDropdown} onOpenChange={setHideDropdown}>
|
||||||
<Button
|
<DialogTrigger asChild>
|
||||||
color="minimal"
|
<Button
|
||||||
className="w-full rounded-none font-medium"
|
onClick={(e) => {
|
||||||
StartIcon={Icon.FiExternalLink}>
|
e.stopPropagation();
|
||||||
{t("preview_team")}
|
}}
|
||||||
</Button>
|
color="destructive"
|
||||||
</a>
|
className="rounded-none px-3 font-normal"
|
||||||
</Link>
|
StartIcon={Icon.FiTrash}>
|
||||||
</DropdownMenuItem>
|
{t("disband_team")}
|
||||||
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
</Button>
|
||||||
{isOwner && (
|
</DialogTrigger>
|
||||||
<DropdownMenuItem>
|
<ConfirmationDialogContent
|
||||||
<Dialog open={hideDropdown} onOpenChange={setHideDropdown}>
|
variety="danger"
|
||||||
<DialogTrigger asChild>
|
title={t("disband_team")}
|
||||||
<Button
|
confirmBtnText={t("confirm_disband_team")}
|
||||||
onClick={(e) => {
|
isLoading={props.isLoading}
|
||||||
e.stopPropagation();
|
onConfirm={() => {
|
||||||
}}
|
props.onActionSelect("disband");
|
||||||
color="destructive"
|
|
||||||
className="w-full rounded-none font-medium"
|
|
||||||
StartIcon={Icon.FiTrash}>
|
|
||||||
{t("disband_team")}
|
|
||||||
</Button>
|
|
||||||
</DialogTrigger>
|
|
||||||
<ConfirmationDialogContent
|
|
||||||
variety="danger"
|
|
||||||
title={t("disband_team")}
|
|
||||||
confirmBtnText={t("confirm_disband_team")}
|
|
||||||
isLoading={props.isLoading}
|
|
||||||
onConfirm={() => {
|
|
||||||
props.onActionSelect("disband");
|
|
||||||
}}>
|
|
||||||
{t("disband_team_confirmation_message")}
|
|
||||||
</ConfirmationDialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!isOwner && (
|
|
||||||
<DropdownMenuItem>
|
|
||||||
<Dialog>
|
|
||||||
<DialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
color="destructive"
|
|
||||||
size="lg"
|
|
||||||
StartIcon={Icon.FiLogOut}
|
|
||||||
className="w-full rounded-none"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
}}>
|
}}>
|
||||||
{t("leave_team")}
|
{t("disband_team_confirmation_message")}
|
||||||
</Button>
|
</ConfirmationDialogContent>
|
||||||
</DialogTrigger>
|
</Dialog>
|
||||||
<ConfirmationDialogContent
|
</DropdownMenuItem>
|
||||||
variety="danger"
|
)}
|
||||||
title={t("leave_team")}
|
|
||||||
confirmBtnText={t("confirm_leave_team")}
|
{!isOwner && (
|
||||||
onConfirm={declineInvite}>
|
<DropdownMenuItem>
|
||||||
{t("leave_team_confirmation_message")}
|
<Dialog>
|
||||||
</ConfirmationDialogContent>
|
<DialogTrigger asChild>
|
||||||
</Dialog>
|
<Button
|
||||||
</DropdownMenuItem>
|
type="button"
|
||||||
)}
|
color="destructive"
|
||||||
</DropdownMenuContent>
|
size="lg"
|
||||||
</Dropdown>
|
StartIcon={Icon.FiLogOut}
|
||||||
|
className="w-full rounded-none"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}>
|
||||||
|
{t("leave_team")}
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<ConfirmationDialogContent
|
||||||
|
variety="danger"
|
||||||
|
title={t("leave_team")}
|
||||||
|
confirmBtnText={t("confirm_leave_team")}
|
||||||
|
onConfirm={declineInvite}>
|
||||||
|
{t("leave_team_confirmation_message")}
|
||||||
|
</ConfirmationDialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</Dropdown>
|
||||||
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { TeamPageProps } from "pages/team/[slug]";
|
import { TeamPageProps } from "pages/team/[slug]";
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import Button from "@calcom/ui/Button";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
|
||||||
import { Avatar } from "@calcom/ui/v2";
|
import { Avatar } from "@calcom/ui/v2";
|
||||||
|
|
||||||
import { useLocale } from "@lib/hooks/useLocale";
|
import { useLocale } from "@lib/hooks/useLocale";
|
||||||
@@ -13,46 +10,46 @@ type TeamType = TeamPageProps["team"];
|
|||||||
type MembersType = TeamType["members"];
|
type MembersType = TeamType["members"];
|
||||||
type MemberType = MembersType[number];
|
type MemberType = MembersType[number];
|
||||||
|
|
||||||
const Team = ({ team }: TeamPageProps) => {
|
const Member = ({ member, teamName }: { member: MemberType; teamName: string | null }) => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
const Member = ({ member }: { member: MemberType }) => {
|
return (
|
||||||
return (
|
<Link key={member.id} href={`/${member.username}`}>
|
||||||
<Link key={member.id} href={`/${member.username}`}>
|
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex min-h-full w-[90%] flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
|
||||||
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex h-full flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
|
<Avatar
|
||||||
<Avatar
|
size="md"
|
||||||
size="md"
|
alt={member.name || ""}
|
||||||
alt={member.name || ""}
|
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
|
||||||
imageSrc={WEBAPP_URL + "/" + member.username + "/avatar.png"}
|
/>
|
||||||
/>
|
<section className="line-clamp-4 mt-2 w-full space-y-1">
|
||||||
<section className="line-clamp-4 mt-2 w-full space-y-1">
|
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
|
||||||
<p className="font-medium text-neutral-900 dark:text-white">{member.name}</p>
|
<p className="line-clamp-3 overflow-ellipsis text-sm font-normal text-neutral-500 dark:text-white">
|
||||||
<p className="line-clamp-3 overflow-ellipsis text-sm font-normal text-neutral-500 dark:text-white">
|
{member.bio || t("user_from_team", { user: member.name, team: teamName })}
|
||||||
{member.bio || t("user_from_team", { user: member.name, team: team.name })}
|
</p>
|
||||||
</p>
|
</section>
|
||||||
</section>
|
</div>
|
||||||
</div>
|
</Link>
|
||||||
</Link>
|
);
|
||||||
);
|
};
|
||||||
};
|
|
||||||
|
|
||||||
const Members = ({ members }: { members: MembersType }) => {
|
const Members = ({ members, teamName }: { members: MembersType; teamName: string | null }) => {
|
||||||
if (!members || members.length === 0) {
|
if (!members || members.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="lg:min-w-lg mx-auto flex min-w-full max-w-5xl flex-wrap justify-center gap-x-6 gap-y-6">
|
|
||||||
{members.map((member) => {
|
|
||||||
return member.username !== null && <Member key={member.id} member={member} />;
|
|
||||||
})}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="lg:min-w-lg mx-auto flex min-w-full max-w-5xl flex-wrap justify-center gap-x-6 gap-y-6">
|
||||||
|
{members.map((member) => {
|
||||||
|
return member.username !== null && <Member key={member.id} member={member} teamName={teamName} />;
|
||||||
|
})}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const Team = ({ team }: TeamPageProps) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Members members={team.members} />
|
<Members members={team.members} teamName={team.name} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,50 +1,48 @@
|
|||||||
import { useState } from "react";
|
import classNames from "classnames";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { ControllerRenderProps } from "react-hook-form";
|
||||||
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
|
|
||||||
const EditableHeading = ({
|
const EditableHeading = function EditableHeading({
|
||||||
title,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
placeholder = "",
|
isReady,
|
||||||
readOnly = false,
|
...passThroughProps
|
||||||
}: {
|
}: {
|
||||||
title: string;
|
isReady?: boolean;
|
||||||
onChange?: (value: string) => void;
|
} & Omit<JSX.IntrinsicElements["input"], "name" | "onChange"> &
|
||||||
placeholder?: string;
|
ControllerRenderProps) {
|
||||||
readOnly?: boolean;
|
|
||||||
}) => {
|
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const enableEditing = () => !readOnly && setIsEditing(true);
|
const enableEditing = () => setIsEditing(true);
|
||||||
return (
|
return (
|
||||||
<div className="group relative cursor-pointer" onClick={enableEditing}>
|
<div className="group relative cursor-pointer" onClick={enableEditing}>
|
||||||
{!isEditing ? (
|
<div className="flex items-center">
|
||||||
<>
|
<label className="min-w-8 relative inline-block">
|
||||||
<h1
|
<span className="whitespace-pre text-xl tracking-normal text-transparent">{value} </span>
|
||||||
style={{ fontSize: 22, letterSpacing: "-0.0009em" }}
|
{!isEditing && isReady && (
|
||||||
className="inline pl-0 normal-case text-gray-900 focus:text-black group-hover:text-gray-500">
|
<Icon.FiEdit2 className="ml-1 inline h-4 w-4 align-top text-gray-700 group-hover:text-gray-500" />
|
||||||
{title}
|
)}
|
||||||
</h1>
|
|
||||||
{!readOnly ? (
|
|
||||||
<Icon.FiEdit2 className="ml-1 -mt-1 inline h-4 w-4 text-gray-700 group-hover:text-gray-500" />
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div style={{ marginBottom: -11 }}>
|
|
||||||
<input
|
<input
|
||||||
|
{...passThroughProps}
|
||||||
type="text"
|
type="text"
|
||||||
autoFocus
|
value={value}
|
||||||
style={{ top: -6, fontSize: 22 }}
|
|
||||||
required
|
required
|
||||||
className="relative h-10 w-full cursor-pointer border-none bg-transparent pl-0 text-gray-900 hover:text-gray-700 focus:text-black focus:outline-none focus:ring-0"
|
className={classNames(
|
||||||
placeholder={placeholder}
|
"absolute top-0 left-0 w-full cursor-pointer border-none bg-transparent p-0 align-top text-xl text-gray-900 hover:text-gray-700 focus:text-black focus:outline-none focus:ring-0"
|
||||||
defaultValue={title}
|
)}
|
||||||
|
onFocus={(e) => {
|
||||||
|
setIsEditing(true);
|
||||||
|
passThroughProps.onFocus && passThroughProps.onFocus(e);
|
||||||
|
}}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
onChange && onChange(e.target.value);
|
passThroughProps.onBlur && passThroughProps.onBlur(e);
|
||||||
}}
|
}}
|
||||||
|
onChange={(e) => onChange && onChange(e.target.value)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</label>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
|
|
||||||
import Dropdown, { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@calcom/ui/Dropdown";
|
import Dropdown, {
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
DropdownMenuPortal,
|
||||||
|
} from "@calcom/ui/Dropdown";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import Button from "@calcom/ui/v2/core/Button";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
|
|
||||||
@@ -43,39 +48,36 @@ const DropdownActions = ({
|
|||||||
) : (
|
) : (
|
||||||
<DropdownMenuTrigger asChild>{actionTrigger}</DropdownMenuTrigger>
|
<DropdownMenuTrigger asChild>{actionTrigger}</DropdownMenuTrigger>
|
||||||
)}
|
)}
|
||||||
<DropdownMenuContent portalled>
|
<DropdownMenuPortal>
|
||||||
{actions.map((action) => (
|
<DropdownMenuContent>
|
||||||
<DropdownMenuItem key={action.id} className="focus-visible:outline-none">
|
{actions.map((action) => (
|
||||||
<Button
|
<DropdownMenuItem key={action.id} className="focus-visible:outline-none">
|
||||||
type="button"
|
<Button
|
||||||
color="minimal"
|
type="button"
|
||||||
className="w-full rounded-none font-normal"
|
color="minimal"
|
||||||
href={action.href}
|
className="w-full rounded-none font-normal"
|
||||||
StartIcon={action.icon}
|
href={action.href}
|
||||||
onClick={action.onClick || defaultAction}
|
StartIcon={action.icon}
|
||||||
data-testid={action.id}>
|
onClick={action.onClick || defaultAction}
|
||||||
{action.label}
|
data-testid={action.id}>
|
||||||
</Button>
|
{action.label}
|
||||||
</DropdownMenuItem>
|
</Button>
|
||||||
))}
|
</DropdownMenuItem>
|
||||||
</DropdownMenuContent>
|
))}
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenuPortal>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TableActions: FC<Props> = ({ actions }) => {
|
const TableActions: FC<Props> = ({ actions }) => {
|
||||||
const mobileActions = actions.flatMap((action) => {
|
|
||||||
if (action.actions) {
|
|
||||||
return action.actions;
|
|
||||||
}
|
|
||||||
return action;
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="hidden space-x-2 rtl:space-x-reverse lg:flex">
|
<div className="flex space-x-2 rtl:space-x-reverse">
|
||||||
{actions.map((action) => {
|
{actions.map((action) => {
|
||||||
const button = (
|
const button = (
|
||||||
<Button
|
<Button
|
||||||
|
className="whitespace-nowrap"
|
||||||
key={action.id}
|
key={action.id}
|
||||||
data-testid={action.id}
|
data-testid={action.id}
|
||||||
href={action.href}
|
href={action.href}
|
||||||
@@ -93,9 +95,6 @@ const TableActions: FC<Props> = ({ actions }) => {
|
|||||||
return <DropdownActions key={action.id} actions={action.actions} actionTrigger={button} />;
|
return <DropdownActions key={action.id} actions={action.actions} actionTrigger={button} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className="inline-block text-left lg:hidden">
|
|
||||||
<DropdownActions actions={mobileActions} />
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ import { MutableRefObject, useCallback, useEffect, useState } from "react";
|
|||||||
|
|
||||||
import { getPremiumPlanMode, getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/utils";
|
import { getPremiumPlanMode, getPremiumPlanPriceValue } from "@calcom/app-store/stripepayment/lib/utils";
|
||||||
import { fetchUsername } from "@calcom/lib/fetchUsername";
|
import { fetchUsername } from "@calcom/lib/fetchUsername";
|
||||||
|
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { User } from "@calcom/prisma/client";
|
import { User } from "@calcom/prisma/client";
|
||||||
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||||
import Button from "@calcom/ui/Button";
|
|
||||||
import { Dialog, DialogClose, DialogContent, DialogHeader } from "@calcom/ui/Dialog";
|
import { Dialog, DialogClose, DialogContent, DialogHeader } from "@calcom/ui/Dialog";
|
||||||
import { Icon, StarIconSolid } from "@calcom/ui/Icon";
|
import { Icon, StarIconSolid } from "@calcom/ui/Icon";
|
||||||
|
import { Button } from "@calcom/ui/v2";
|
||||||
import { Input, Label } from "@calcom/ui/v2";
|
import { Input, Label } from "@calcom/ui/v2";
|
||||||
|
|
||||||
export enum UsernameChangeStatusEnum {
|
export enum UsernameChangeStatusEnum {
|
||||||
@@ -25,7 +26,7 @@ interface ICustomUsernameProps {
|
|||||||
currentUsername: string | undefined;
|
currentUsername: string | undefined;
|
||||||
setCurrentUsername: (value: string | undefined) => void;
|
setCurrentUsername: (value: string | undefined) => void;
|
||||||
inputUsernameValue: string | undefined;
|
inputUsernameValue: string | undefined;
|
||||||
usernameRef: MutableRefObject<HTMLInputElement>;
|
usernameRef: MutableRefObject<HTMLInputElement | null>;
|
||||||
setInputUsernameValue: (value: string) => void;
|
setInputUsernameValue: (value: string) => void;
|
||||||
onSuccessMutation?: () => void;
|
onSuccessMutation?: () => void;
|
||||||
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
||||||
@@ -43,9 +44,8 @@ interface ICustomUsernameProps {
|
|||||||
| "plan"
|
| "plan"
|
||||||
| "brandColor"
|
| "brandColor"
|
||||||
| "darkBrandColor"
|
| "darkBrandColor"
|
||||||
| "metadata"
|
|
||||||
| "timeFormat"
|
| "timeFormat"
|
||||||
| "allowDynamicBooking"
|
| "metadata"
|
||||||
>;
|
>;
|
||||||
readonly?: boolean;
|
readonly?: boolean;
|
||||||
}
|
}
|
||||||
@@ -62,24 +62,13 @@ const obtainNewUsernameChangeCondition = ({
|
|||||||
if (!userIsPremium && isNewUsernamePremium && !stripeCustomer?.paidForPremium) {
|
if (!userIsPremium && isNewUsernamePremium && !stripeCustomer?.paidForPremium) {
|
||||||
return UsernameChangeStatusEnum.UPGRADE;
|
return UsernameChangeStatusEnum.UPGRADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userIsPremium && !isNewUsernamePremium && getPremiumPlanMode() === "subscription") {
|
if (userIsPremium && !isNewUsernamePremium && getPremiumPlanMode() === "subscription") {
|
||||||
return UsernameChangeStatusEnum.DOWNGRADE;
|
return UsernameChangeStatusEnum.DOWNGRADE;
|
||||||
}
|
}
|
||||||
return UsernameChangeStatusEnum.NORMAL;
|
return UsernameChangeStatusEnum.NORMAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useIsUsernamePremium = (username: string) => {
|
|
||||||
const [isCurrentUsernamePremium, setIsCurrentUsernamePremium] = useState(false);
|
|
||||||
useEffect(() => {
|
|
||||||
(async () => {
|
|
||||||
if (!username) return;
|
|
||||||
const { data } = await fetchUsername(username);
|
|
||||||
setIsCurrentUsernamePremium(data.premium);
|
|
||||||
})();
|
|
||||||
}, [username]);
|
|
||||||
return isCurrentUsernamePremium;
|
|
||||||
};
|
|
||||||
|
|
||||||
const PremiumTextfield = (props: ICustomUsernameProps) => {
|
const PremiumTextfield = (props: ICustomUsernameProps) => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const {
|
const {
|
||||||
@@ -91,6 +80,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
onSuccessMutation,
|
onSuccessMutation,
|
||||||
onErrorMutation,
|
onErrorMutation,
|
||||||
readonly: disabled,
|
readonly: disabled,
|
||||||
|
user,
|
||||||
} = props;
|
} = props;
|
||||||
const [usernameIsAvailable, setUsernameIsAvailable] = useState(false);
|
const [usernameIsAvailable, setUsernameIsAvailable] = useState(false);
|
||||||
const [markAsError, setMarkAsError] = useState(false);
|
const [markAsError, setMarkAsError] = useState(false);
|
||||||
@@ -98,13 +88,13 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
const { paymentStatus: recentAttemptPaymentStatus } = router.query;
|
const { paymentStatus: recentAttemptPaymentStatus } = router.query;
|
||||||
const [openDialogSaveUsername, setOpenDialogSaveUsername] = useState(false);
|
const [openDialogSaveUsername, setOpenDialogSaveUsername] = useState(false);
|
||||||
const { data: stripeCustomer } = trpc.useQuery(["viewer.stripeCustomer"]);
|
const { data: stripeCustomer } = trpc.useQuery(["viewer.stripeCustomer"]);
|
||||||
const isCurrentUsernamePremium = useIsUsernamePremium(currentUsername || "");
|
const isCurrentUsernamePremium =
|
||||||
|
user && user.metadata && hasKeyInMetadata(user, "isPremium") ? !!user.metadata.isPremium : false;
|
||||||
const [isInputUsernamePremium, setIsInputUsernamePremium] = useState(false);
|
const [isInputUsernamePremium, setIsInputUsernamePremium] = useState(false);
|
||||||
|
|
||||||
const debouncedApiCall = useCallback(
|
const debouncedApiCall = useCallback(
|
||||||
debounce(async (username) => {
|
debounce(async (username: string) => {
|
||||||
const { data } = await fetchUsername(username);
|
const { data } = await fetchUsername(username);
|
||||||
setMarkAsError(!data.available && username !== currentUsername);
|
setMarkAsError(!data.available && !!currentUsername && username !== currentUsername);
|
||||||
setIsInputUsernamePremium(data.premium);
|
setIsInputUsernamePremium(data.premium);
|
||||||
setUsernameIsAvailable(data.available);
|
setUsernameIsAvailable(data.available);
|
||||||
}, 150),
|
}, 150),
|
||||||
@@ -183,7 +173,9 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (currentUsername) {
|
if (currentUsername) {
|
||||||
setInputUsernameValue(currentUsername);
|
setInputUsernameValue(currentUsername);
|
||||||
usernameRef.current.value = currentUsername;
|
if (usernameRef.current) {
|
||||||
|
usernameRef.current.value = currentUsername;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
{t("cancel")}
|
{t("cancel")}
|
||||||
@@ -202,6 +194,20 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let paymentMsg = !currentUsername ? (
|
||||||
|
<span className="text-xs text-orange-400">
|
||||||
|
You need to reserve your premium username for {getPremiumPlanPriceValue()}
|
||||||
|
</span>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
if (recentAttemptPaymentStatus && recentAttemptPaymentStatus !== "paid") {
|
||||||
|
paymentMsg = (
|
||||||
|
<span className="text-sm text-red-500">
|
||||||
|
Your payment could not be completed. Your username is still not reserved
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-items-center">
|
<div className="flex justify-items-center">
|
||||||
@@ -211,7 +217,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
<span
|
<span
|
||||||
className={classNames(
|
className={classNames(
|
||||||
isInputUsernamePremium ? "border-1 border-orange-400 " : "",
|
isInputUsernamePremium ? "border-1 border-orange-400 " : "",
|
||||||
"hidden items-center rounded-l-md border border-r-0 border-gray-300 border-r-gray-300 bg-gray-50 px-3 text-sm text-gray-500 md:inline-flex"
|
"hidden h-9 items-center rounded-l-md border border-r-0 border-gray-300 border-r-gray-300 bg-gray-50 px-3 text-sm text-gray-500 md:inline-flex"
|
||||||
)}>
|
)}>
|
||||||
{process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")}/
|
{process.env.NEXT_PUBLIC_WEBSITE_URL.replace("https://", "").replace("http://", "")}/
|
||||||
</span>
|
</span>
|
||||||
@@ -237,6 +243,8 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
value={inputUsernameValue}
|
value={inputUsernameValue}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
// Reset payment status
|
||||||
|
delete router.query.paymentStatus;
|
||||||
setInputUsernameValue(event.target.value);
|
setInputUsernameValue(event.target.value);
|
||||||
}}
|
}}
|
||||||
data-testid="username-input"
|
data-testid="username-input"
|
||||||
@@ -248,7 +256,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
isInputUsernamePremium ? "text-orange-400" : "",
|
isInputUsernamePremium ? "text-orange-400" : "",
|
||||||
usernameIsAvailable ? "" : ""
|
usernameIsAvailable ? "" : ""
|
||||||
)}>
|
)}>
|
||||||
{isInputUsernamePremium ? <StarIconSolid className="mt-[4px] w-6" /> : <></>}
|
{isInputUsernamePremium ? <StarIconSolid className="mt-[2px] w-6" /> : <></>}
|
||||||
{!isInputUsernamePremium && usernameIsAvailable ? <Icon.FiCheck className="mt-2 w-6" /> : <></>}
|
{!isInputUsernamePremium && usernameIsAvailable ? <Icon.FiCheck className="mt-2 w-6" /> : <></>}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -260,17 +268,7 @@ const PremiumTextfield = (props: ICustomUsernameProps) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{paymentRequired ? (
|
{paymentMsg}
|
||||||
recentAttemptPaymentStatus && recentAttemptPaymentStatus !== "paid" ? (
|
|
||||||
<span className="text-sm text-red-500">
|
|
||||||
Your payment could not be completed. Your username is still not reserved
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span className="text-xs text-orange-400">
|
|
||||||
You need to reserve your premium username for {getPremiumPlanPriceValue()}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
) : null}
|
|
||||||
{markAsError && <p className="mt-1 text-xs text-red-500">Username is already taken</p>}
|
{markAsError && <p className="mt-1 text-xs text-red-500">Username is already taken</p>}
|
||||||
|
|
||||||
{usernameIsAvailable && (
|
{usernameIsAvailable && (
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { AppRouter } from "@calcom/trpc/server/routers/_app";
|
import { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||||
import Button from "@calcom/ui/Button";
|
|
||||||
import { Dialog, DialogClose, DialogContent, DialogHeader } from "@calcom/ui/Dialog";
|
import { Dialog, DialogClose, DialogContent, DialogHeader } from "@calcom/ui/Dialog";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import { Input, Label } from "@calcom/ui/v2";
|
import { Input, Label, Button } from "@calcom/ui/v2";
|
||||||
|
|
||||||
interface ICustomUsernameProps {
|
interface ICustomUsernameProps {
|
||||||
currentUsername: string | undefined;
|
currentUsername: string | undefined;
|
||||||
setCurrentUsername: (value: string | undefined) => void;
|
setCurrentUsername: (value: string | undefined) => void;
|
||||||
inputUsernameValue: string | undefined;
|
inputUsernameValue: string | undefined;
|
||||||
usernameRef: MutableRefObject<HTMLInputElement>;
|
usernameRef: MutableRefObject<HTMLInputElement | null>;
|
||||||
setInputUsernameValue: (value: string) => void;
|
setInputUsernameValue: (value: string) => void;
|
||||||
onSuccessMutation?: () => void;
|
onSuccessMutation?: () => void;
|
||||||
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
onErrorMutation?: (error: TRPCClientErrorLike<AppRouter>) => void;
|
||||||
@@ -73,15 +72,14 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const ActionButtons = (props: { index: string }) => {
|
const ActionButtons = () => {
|
||||||
const { index } = props;
|
|
||||||
return usernameIsAvailable && currentUsername !== inputUsernameValue ? (
|
return usernameIsAvailable && currentUsername !== inputUsernameValue ? (
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
className="mx-2"
|
className="mx-2"
|
||||||
onClick={() => setOpenDialogSaveUsername(true)}
|
onClick={() => setOpenDialogSaveUsername(true)}
|
||||||
data-testid={`update-username-btn-${index}`}>
|
data-testid="update-username-btn">
|
||||||
{t("update")}
|
{t("update")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
@@ -91,7 +89,9 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (currentUsername) {
|
if (currentUsername) {
|
||||||
setInputUsernameValue(currentUsername);
|
setInputUsernameValue(currentUsername);
|
||||||
usernameRef.current.value = currentUsername;
|
if (usernameRef.current) {
|
||||||
|
usernameRef.current.value = currentUsername;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
{t("cancel")}
|
{t("cancel")}
|
||||||
@@ -122,7 +122,7 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
|||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoCorrect="none"
|
autoCorrect="none"
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"mb-0 mt-0 rounded-md rounded-l-none",
|
"mb-0 mt-0 h-6 rounded-md rounded-l-none",
|
||||||
markAsError
|
markAsError
|
||||||
? "focus:shadow-0 focus:ring-shadow-0 border-red-500 focus:border-red-500 focus:outline-none focus:ring-0"
|
? "focus:shadow-0 focus:ring-shadow-0 border-red-500 focus:border-red-500 focus:outline-none focus:ring-0"
|
||||||
: ""
|
: ""
|
||||||
@@ -137,20 +137,20 @@ const UsernameTextfield = (props: ICustomUsernameProps) => {
|
|||||||
{currentUsername !== inputUsernameValue && (
|
{currentUsername !== inputUsernameValue && (
|
||||||
<div className="absolute right-[2px] top-0 flex flex-row">
|
<div className="absolute right-[2px] top-0 flex flex-row">
|
||||||
<span className={classNames("mx-2 py-2")}>
|
<span className={classNames("mx-2 py-2")}>
|
||||||
{usernameIsAvailable ? <Icon.FiCheck className="mt-[4px] w-6" /> : <></>}
|
{usernameIsAvailable ? <Icon.FiCheck className="mt-[2px] w-6" /> : <></>}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden md:inline">
|
<div className="hidden md:inline">
|
||||||
<ActionButtons index="desktop" />
|
<ActionButtons />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{markAsError && <p className="mt-1 text-xs text-red-500">Username is already taken</p>}
|
{markAsError && <p className="mt-1 text-xs text-red-500">Username is already taken</p>}
|
||||||
|
|
||||||
{usernameIsAvailable && currentUsername !== inputUsernameValue && (
|
{usernameIsAvailable && currentUsername !== inputUsernameValue && (
|
||||||
<div className="mt-2 flex justify-end sm:hidden">
|
<div className="mt-2 flex justify-end md:hidden">
|
||||||
<ActionButtons index="mobile" />
|
<ActionButtons />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Dialog open={openDialogSaveUsername}>
|
<Dialog open={openDialogSaveUsername}>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Select from "react-select";
|
|
||||||
import { OptionProps } from "react-select";
|
import { OptionProps } from "react-select";
|
||||||
|
|
||||||
import { InstallAppButton } from "@calcom/app-store/components";
|
import { InstallAppButton } from "@calcom/app-store/components";
|
||||||
@@ -8,6 +7,7 @@ import { trpc } from "@calcom/trpc/react";
|
|||||||
import type { App } from "@calcom/types/App";
|
import type { App } from "@calcom/types/App";
|
||||||
import { Button } from "@calcom/ui";
|
import { Button } from "@calcom/ui";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
|
import { Select } from "@calcom/ui/v2";
|
||||||
|
|
||||||
import { QueryCell } from "@lib/QueryCell";
|
import { QueryCell } from "@lib/QueryCell";
|
||||||
|
|
||||||
@@ -65,23 +65,7 @@ const AdditionalCalendarSelector = ({ isLoading }: AdditionalCalendarSelectorPro
|
|||||||
name="additionalCalendar"
|
name="additionalCalendar"
|
||||||
placeholder={t("install_another")}
|
placeholder={t("install_another")}
|
||||||
options={options}
|
options={options}
|
||||||
styles={{
|
|
||||||
placeholder: (defaultStyles) => {
|
|
||||||
return {
|
|
||||||
...defaultStyles,
|
|
||||||
color: "#3E3E3E",
|
|
||||||
marginLeft: "3px",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
control: (defaultStyles) => {
|
|
||||||
return {
|
|
||||||
...defaultStyles,
|
|
||||||
borderRadius: "6px",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
className="min-w-52 block w-full flex-1 rounded-none rounded-r-sm border-gray-300 text-sm font-medium text-gray-700"
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
components={{ Option: ImageOption }}
|
components={{ Option: ImageOption }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
+206
-219
@@ -1,6 +1,6 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation";
|
import useAddAppMutation from "@calcom/app-store/_utils/useAddAppMutation";
|
||||||
import { InstallAppButton } from "@calcom/app-store/components";
|
import { InstallAppButton } from "@calcom/app-store/components";
|
||||||
@@ -9,9 +9,8 @@ import classNames from "@calcom/lib/classNames";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { App as AppType } from "@calcom/types/App";
|
import { App as AppType } from "@calcom/types/App";
|
||||||
import Badge from "@calcom/ui/Badge";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import { showToast } from "@calcom/ui/v2";
|
import { showToast, SkeletonText } from "@calcom/ui/v2";
|
||||||
import { Button, SkeletonButton, Shell } from "@calcom/ui/v2";
|
import { Button, SkeletonButton, Shell } from "@calcom/ui/v2";
|
||||||
import DisconnectIntegration from "@calcom/ui/v2/modules/integrations/DisconnectIntegration";
|
import DisconnectIntegration from "@calcom/ui/v2/modules/integrations/DisconnectIntegration";
|
||||||
|
|
||||||
@@ -37,7 +36,6 @@ const Component = ({
|
|||||||
images,
|
images,
|
||||||
}: Parameters<typeof App>[0]) => {
|
}: Parameters<typeof App>[0]) => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const { data: user } = trpc.useQuery(["viewer.me"]);
|
|
||||||
const hasImages = images && images.length > 0;
|
const hasImages = images && images.length > 0;
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@@ -66,226 +64,213 @@ const Component = ({
|
|||||||
const allowedMultipleInstalls = categories.indexOf("calendar") > -1;
|
const allowedMultipleInstalls = categories.indexOf("calendar") > -1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="relative flex-1 flex-col items-start justify-start px-4 md:flex md:px-8 lg:flex-row lg:px-0">
|
||||||
<div className="px-4 pb-3 pt-3 md:px-8 lg:px-0 lg:pt-0">
|
{hasImages && (
|
||||||
<Link href="/apps">
|
<div className="flex-2 mb-4 -ml-4 -mr-4 flex min-h-[450px] w-auto snap-x snap-mandatory flex-row overflow-auto whitespace-nowrap bg-gray-100 p-4 md:mb-8 md:-ml-8 md:-mr-8 md:p-8 lg:mx-0 lg:mb-0 lg:max-w-2xl lg:flex-col lg:rounded-md">
|
||||||
<a className="text-md hover:text-brand-400 inline-flex rounded-sm py-2 font-semibold text-gray-900">
|
{images ? (
|
||||||
<Icon.FiArrowLeft className="mr-2 h-6 w-6" /> {t("app_store")}
|
images.map((img) => (
|
||||||
</a>
|
<img
|
||||||
</Link>
|
key={img}
|
||||||
</div>
|
src={img}
|
||||||
|
alt={`Screenshot of app ${name}`}
|
||||||
<div className="relative flex-1 flex-col items-start justify-start px-4 md:flex md:px-8 lg:flex-row lg:px-0">
|
className="mr-4 h-auto max-h-80 max-w-[90%] snap-center rounded-md object-contain last:mb-0 md:max-h-min lg:mb-4 lg:mr-0 lg:max-w-full"
|
||||||
{hasImages && (
|
|
||||||
<div className="flex-2 mb-4 -ml-4 -mr-4 flex w-auto snap-x snap-mandatory flex-row overflow-auto whitespace-nowrap bg-gray-100 p-4 md:mb-8 md:-ml-8 md:-mr-8 md:p-8 lg:mx-0 lg:mb-0 lg:max-w-2xl lg:flex-col lg:rounded-md">
|
|
||||||
{images &&
|
|
||||||
images.map((img) => (
|
|
||||||
<img
|
|
||||||
key={img}
|
|
||||||
src={img}
|
|
||||||
alt={`Screenshot of app ${name}`}
|
|
||||||
className="mr-4 h-auto max-h-80 max-w-[90%] snap-center rounded-md object-contain last:mb-0 md:max-h-min lg:mb-4 lg:mr-0 lg:max-w-full"
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className={classNames(
|
|
||||||
"sticky top-0 -mt-4 max-w-xl flex-1 pb-12 text-sm lg:pb-0",
|
|
||||||
hasImages && "lg:ml-8"
|
|
||||||
)}>
|
|
||||||
<div className="mb-8 flex pt-4">
|
|
||||||
<header>
|
|
||||||
<div className="mb-4 flex items-center">
|
|
||||||
<img className="min-h-16 min-w-16 h-16 w-16" src={logo} alt={name} />
|
|
||||||
<h1 className="font-cal ml-4 text-3xl text-gray-900">{name}</h1>
|
|
||||||
</div>
|
|
||||||
<h2 className="text-sm font-medium text-gray-600">
|
|
||||||
<Link href={`categories/${categories[0]}`}>
|
|
||||||
<a className="rounded-md bg-gray-100 p-1 text-xs capitalize text-gray-800">
|
|
||||||
{categories[0]}
|
|
||||||
</a>
|
|
||||||
</Link>{" "}
|
|
||||||
• {t("published_by", { author })}
|
|
||||||
</h2>
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
{!appCredentials.isLoading ? (
|
|
||||||
isGlobal ||
|
|
||||||
(existingCredentials.length > 0 && allowedMultipleInstalls ? (
|
|
||||||
<div className="flex space-x-3">
|
|
||||||
<Button StartIcon={Icon.FiCheck} color="secondary" disabled>
|
|
||||||
{existingCredentials.length > 0
|
|
||||||
? t("active_install", { count: existingCredentials.length })
|
|
||||||
: t("default")}
|
|
||||||
</Button>
|
|
||||||
{!isGlobal && (
|
|
||||||
<InstallAppButton
|
|
||||||
type={type}
|
|
||||||
isProOnly={isProOnly}
|
|
||||||
render={({ useDefaultComponent, ...props }) => {
|
|
||||||
if (useDefaultComponent) {
|
|
||||||
props = {
|
|
||||||
onClick: () => {
|
|
||||||
mutation.mutate({ type, variant, slug });
|
|
||||||
},
|
|
||||||
loading: mutation.isLoading,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
StartIcon={Icon.FiPlus}
|
|
||||||
{...props}
|
|
||||||
// @TODO: Overriding color and size prevent us from
|
|
||||||
// having to duplicate InstallAppButton for now.
|
|
||||||
color="primary"
|
|
||||||
size="base"
|
|
||||||
data-testid="install-app-button">
|
|
||||||
{t("install_another")}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
) : existingCredentials.length > 0 ? (
|
|
||||||
<DisconnectIntegration
|
|
||||||
label={t("disconnect")}
|
|
||||||
credentialId={existingCredentials[0]}
|
|
||||||
onSuccess={() => {
|
|
||||||
router.replace("/apps/installed");
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<InstallAppButton
|
|
||||||
type={type}
|
|
||||||
isProOnly={isProOnly}
|
|
||||||
render={({ useDefaultComponent, ...props }) => {
|
|
||||||
if (useDefaultComponent) {
|
|
||||||
props = {
|
|
||||||
onClick: () => {
|
|
||||||
mutation.mutate({ type, variant, slug });
|
|
||||||
},
|
|
||||||
loading: mutation.isLoading,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
data-testid="install-app-button"
|
|
||||||
{...props}
|
|
||||||
// @TODO: Overriding color and size prevent us from
|
|
||||||
// having to duplicate InstallAppButton for now.
|
|
||||||
color="primary"
|
|
||||||
size="base">
|
|
||||||
{t("install_app")}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<SkeletonButton className="h-10 w-24" />
|
<SkeletonText />
|
||||||
)}
|
)}
|
||||||
{price !== 0 && (
|
|
||||||
<span className="block text-right">
|
|
||||||
{feeType === "usage-based" ? commission + "% + " + priceInDollar + "/booking" : priceInDollar}
|
|
||||||
{feeType === "monthly" && "/" + t("month")}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="prose prose-sm mt-8 space-x-2">{body}</div>
|
|
||||||
<h4 className="mt-8 font-semibold text-gray-900 ">{t("pricing")}</h4>
|
|
||||||
<span>
|
|
||||||
{price === 0 ? (
|
|
||||||
"Free"
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{Intl.NumberFormat("en-US", {
|
|
||||||
style: "currency",
|
|
||||||
currency: "USD",
|
|
||||||
useGrouping: false,
|
|
||||||
}).format(price)}
|
|
||||||
{feeType === "monthly" && "/" + t("month")}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<h4 className="mt-8 mb-2 font-semibold text-gray-900 ">{t("learn_more")}</h4>
|
|
||||||
<ul className="prose-sm -ml-1 -mr-1 leading-5">
|
|
||||||
{docs && (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="text-sm font-normal text-black no-underline hover:underline"
|
|
||||||
href={docs}>
|
|
||||||
<Icon.FiBookOpen className="mr-1 -mt-1 inline h-4 w-4 text-gray-500" />
|
|
||||||
{t("documentation")}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{website && (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="font-normal text-black no-underline hover:underline"
|
|
||||||
href={website}>
|
|
||||||
<Icon.FiExternalLink className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
|
||||||
{website.replace("https://", "")}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{email && (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="font-normal text-black no-underline hover:underline"
|
|
||||||
href={"mailto:" + email}>
|
|
||||||
<Icon.FiMail className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
|
||||||
|
|
||||||
{email}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{tos && (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="font-normal text-black no-underline hover:underline"
|
|
||||||
href={tos}>
|
|
||||||
<Icon.FiFile className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
|
||||||
{t("terms_of_service")}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
{privacy && (
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
className="font-normal text-black no-underline hover:underline"
|
|
||||||
href={privacy}>
|
|
||||||
<Icon.FiShield className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
|
||||||
{t("privacy_policy")}
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
<hr className="my-8" />
|
|
||||||
<span className="leading-1 block text-xs text-gray-500">
|
|
||||||
Every app published on the Cal.com App Store is open source and thoroughly tested via peer
|
|
||||||
reviews. Nevertheless, Cal.com, Inc. does not endorse or certify these apps unless they are
|
|
||||||
published by Cal.com. If you encounter inappropriate content or behaviour please report it.
|
|
||||||
</span>
|
|
||||||
<a className="mt-2 block text-xs text-red-500" href="mailto:help@cal.com">
|
|
||||||
<Icon.FiFlag className="inline h-3 w-3" /> Report App
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
"sticky top-0 -mt-4 max-w-xl flex-1 pb-12 text-sm lg:pb-0",
|
||||||
|
hasImages && "lg:ml-8"
|
||||||
|
)}>
|
||||||
|
<div className="mb-8 flex pt-4">
|
||||||
|
<header>
|
||||||
|
<div className="mb-4 flex items-center">
|
||||||
|
<img className="min-h-16 min-w-16 h-16 w-16" src={logo} alt={name} />
|
||||||
|
<h1 className="font-cal ml-4 text-3xl text-gray-900">{name}</h1>
|
||||||
|
</div>
|
||||||
|
<h2 className="text-sm font-medium text-gray-600">
|
||||||
|
<Link href={`categories/${categories[0]}`}>
|
||||||
|
<a className="rounded-md bg-gray-100 p-1 text-xs capitalize text-gray-800">{categories[0]}</a>
|
||||||
|
</Link>{" "}
|
||||||
|
• {t("published_by", { author })}
|
||||||
|
</h2>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
{!appCredentials.isLoading ? (
|
||||||
|
isGlobal ||
|
||||||
|
(existingCredentials.length > 0 && allowedMultipleInstalls ? (
|
||||||
|
<div className="flex space-x-3">
|
||||||
|
<Button StartIcon={Icon.FiCheck} color="secondary" disabled>
|
||||||
|
{existingCredentials.length > 0
|
||||||
|
? t("active_install", { count: existingCredentials.length })
|
||||||
|
: t("default")}
|
||||||
|
</Button>
|
||||||
|
{!isGlobal && (
|
||||||
|
<InstallAppButton
|
||||||
|
type={type}
|
||||||
|
isProOnly={isProOnly}
|
||||||
|
render={({ useDefaultComponent, ...props }) => {
|
||||||
|
if (useDefaultComponent) {
|
||||||
|
props = {
|
||||||
|
onClick: () => {
|
||||||
|
mutation.mutate({ type, variant, slug });
|
||||||
|
},
|
||||||
|
loading: mutation.isLoading,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
StartIcon={Icon.FiPlus}
|
||||||
|
{...props}
|
||||||
|
// @TODO: Overriding color and size prevent us from
|
||||||
|
// having to duplicate InstallAppButton for now.
|
||||||
|
color="primary"
|
||||||
|
size="base"
|
||||||
|
data-testid="install-app-button">
|
||||||
|
{t("install_another")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
) : existingCredentials.length > 0 ? (
|
||||||
|
<DisconnectIntegration
|
||||||
|
label={t("disconnect")}
|
||||||
|
credentialId={existingCredentials[0]}
|
||||||
|
onSuccess={() => {
|
||||||
|
router.replace("/apps/installed");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<InstallAppButton
|
||||||
|
type={type}
|
||||||
|
isProOnly={isProOnly}
|
||||||
|
render={({ useDefaultComponent, ...props }) => {
|
||||||
|
if (useDefaultComponent) {
|
||||||
|
props = {
|
||||||
|
onClick: () => {
|
||||||
|
mutation.mutate({ type, variant, slug });
|
||||||
|
},
|
||||||
|
loading: mutation.isLoading,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
data-testid="install-app-button"
|
||||||
|
{...props}
|
||||||
|
// @TODO: Overriding color and size prevent us from
|
||||||
|
// having to duplicate InstallAppButton for now.
|
||||||
|
color="primary"
|
||||||
|
size="base">
|
||||||
|
{t("install_app")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<SkeletonButton className="h-10 w-24" />
|
||||||
|
)}
|
||||||
|
{price !== 0 && (
|
||||||
|
<span className="block text-right">
|
||||||
|
{feeType === "usage-based" ? commission + "% + " + priceInDollar + "/booking" : priceInDollar}
|
||||||
|
{feeType === "monthly" && "/" + t("month")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="prose prose-sm mt-8">{body}</div>
|
||||||
|
<h4 className="mt-8 font-semibold text-gray-900 ">{t("pricing")}</h4>
|
||||||
|
<span>
|
||||||
|
{price === 0 ? (
|
||||||
|
"Free"
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{Intl.NumberFormat("en-US", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "USD",
|
||||||
|
useGrouping: false,
|
||||||
|
}).format(price)}
|
||||||
|
{feeType === "monthly" && "/" + t("month")}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<h4 className="mt-8 mb-2 font-semibold text-gray-900 ">{t("learn_more")}</h4>
|
||||||
|
<ul className="prose-sm -ml-1 -mr-1 leading-5">
|
||||||
|
{docs && (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="text-sm font-normal text-black no-underline hover:underline"
|
||||||
|
href={docs}>
|
||||||
|
<Icon.FiBookOpen className="mr-1 -mt-1 inline h-4 w-4 text-gray-500" />
|
||||||
|
{t("documentation")}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{website && (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="font-normal text-black no-underline hover:underline"
|
||||||
|
href={website}>
|
||||||
|
<Icon.FiExternalLink className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
||||||
|
{website.replace("https://", "")}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{email && (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="font-normal text-black no-underline hover:underline"
|
||||||
|
href={"mailto:" + email}>
|
||||||
|
<Icon.FiMail className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
||||||
|
|
||||||
|
{email}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{tos && (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="font-normal text-black no-underline hover:underline"
|
||||||
|
href={tos}>
|
||||||
|
<Icon.FiFile className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
||||||
|
{t("terms_of_service")}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
{privacy && (
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
className="font-normal text-black no-underline hover:underline"
|
||||||
|
href={privacy}>
|
||||||
|
<Icon.FiShield className="mr-1 -mt-px inline h-4 w-4 text-gray-500" />
|
||||||
|
{t("privacy_policy")}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
<hr className="my-8" />
|
||||||
|
<span className="leading-1 block text-xs text-gray-500">{t("every_app_published")}</span>
|
||||||
|
<a className="mt-2 block text-xs text-red-500" href="mailto:help@cal.com">
|
||||||
|
<Icon.FiFlag className="inline h-3 w-3" /> {t("report_app")}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -312,8 +297,10 @@ export default function App(props: {
|
|||||||
isProOnly: AppType["isProOnly"];
|
isProOnly: AppType["isProOnly"];
|
||||||
images?: string[];
|
images?: string[];
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Shell large isPublic>
|
<Shell large isPublic heading={t("app_store")} backPath="/apps">
|
||||||
{props.licenseRequired ? (
|
{props.licenseRequired ? (
|
||||||
<LicenseRequired>
|
<LicenseRequired>
|
||||||
<Component {...props} />
|
<Component {...props} />
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
import Link from "next/link";
|
||||||
import { Fragment } from "react";
|
import { Fragment } from "react";
|
||||||
import { useMutation } from "react-query";
|
|
||||||
|
|
||||||
import { InstallAppButton } from "@calcom/app-store/components";
|
import { InstallAppButton } from "@calcom/app-store/components";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
@@ -153,7 +154,7 @@ function ConnectedCalendarsList(props: Props) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<List className="flex flex-col gap-6">
|
<List className="flex flex-col gap-6" noBorderTreatment>
|
||||||
{data.connectedCalendars.map((item) => (
|
{data.connectedCalendars.map((item) => (
|
||||||
<Fragment key={item.credentialId}>
|
<Fragment key={item.credentialId}>
|
||||||
{item.calendars ? (
|
{item.calendars ? (
|
||||||
@@ -193,10 +194,16 @@ function ConnectedCalendarsList(props: Props) {
|
|||||||
) : (
|
) : (
|
||||||
<Alert
|
<Alert
|
||||||
severity="warning"
|
severity="warning"
|
||||||
title={t("calendar_error")}
|
title={t("something_went_wrong")}
|
||||||
message={item.error?.message}
|
message={
|
||||||
|
<span>
|
||||||
|
<Link href={"/apps/" + item.integration.slug}>{item.integration.name}</Link>:{" "}
|
||||||
|
{t("calendar_error")}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
iconClassName="h-10 w-10 ml-2 mr-1 mt-0.5"
|
||||||
actions={
|
actions={
|
||||||
<div className="w-32">
|
<div className="flex w-32 justify-end md:pr-1">
|
||||||
<DisconnectIntegration
|
<DisconnectIntegration
|
||||||
credentialId={item.credentialId}
|
credentialId={item.credentialId}
|
||||||
trashIcon
|
trashIcon
|
||||||
@@ -251,7 +258,7 @@ export function CalendarListContainer(props: { heading?: boolean; fromOnboarding
|
|||||||
<ShellSubHeading
|
<ShellSubHeading
|
||||||
title={t("calendar")}
|
title={t("calendar")}
|
||||||
subtitle={t("installed_app_calendar_description")}
|
subtitle={t("installed_app_calendar_description")}
|
||||||
className="flex items-center"
|
className="mb-0 flex flex-wrap items-center gap-4 md:mb-3 md:gap-0"
|
||||||
actions={
|
actions={
|
||||||
<div className="flex flex-col xl:flex-row xl:space-x-5">
|
<div className="flex flex-col xl:flex-row xl:space-x-5">
|
||||||
{!!data.connectedCalendars.length && (
|
{!!data.connectedCalendars.length && (
|
||||||
@@ -263,7 +270,7 @@ export function CalendarListContainer(props: { heading?: boolean; fromOnboarding
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div className="flex justify-between rounded-md border border-gray-200 bg-gray-50 p-4">
|
<div className="flex justify-between rounded-md border border-gray-200 bg-gray-50 p-4">
|
||||||
<div className="flex w-full items-center gap-4">
|
<div className="flex w-full flex-col items-start gap-4 md:flex-row md:items-center">
|
||||||
<div className="relative rounded-md border border-gray-200 bg-white p-1.5">
|
<div className="relative rounded-md border border-gray-200 bg-white p-1.5">
|
||||||
<Icon.FiCalendar className="h-8 w-8" strokeWidth="1" />
|
<Icon.FiCalendar className="h-8 w-8" strokeWidth="1" />
|
||||||
<Icon.FiPlus
|
<Icon.FiPlus
|
||||||
@@ -271,11 +278,11 @@ export function CalendarListContainer(props: { heading?: boolean; fromOnboarding
|
|||||||
strokeWidth="4"
|
strokeWidth="4"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-6/12">
|
<div className="md:w-6/12">
|
||||||
<h1 className="text-sm font-semibold">{t("create_events_on")}</h1>
|
<h1 className="text-sm font-semibold">{t("create_events_on")}</h1>
|
||||||
<p className="text-sm font-normal">{t("set_calendar")}</p>
|
<p className="text-sm font-normal">{t("set_calendar")}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-6/12 justify-end">
|
<div className="flex justify-end md:w-6/12">
|
||||||
<DestinationCalendarSelector
|
<DestinationCalendarSelector
|
||||||
onChange={mutation.mutate}
|
onChange={mutation.mutate}
|
||||||
hidePlaceholder
|
hidePlaceholder
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const DestinationCalendarSelector = ({
|
|||||||
if (selected) {
|
if (selected) {
|
||||||
setSelectedOption({
|
setSelectedOption({
|
||||||
value: `${selected.integration}:${selected.externalId}`,
|
value: `${selected.integration}:${selected.externalId}`,
|
||||||
label: `<span class="font-semibold">${selected.name}</span> (${selected.externalId})` || "",
|
label: `${selected.name} (${selected.externalId})` || "",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [query.data?.connectedCalendars, value]);
|
}, [query.data?.connectedCalendars, value]);
|
||||||
@@ -66,7 +66,7 @@ const DestinationCalendarSelector = ({
|
|||||||
options: (selectedCalendar.calendars ?? [])
|
options: (selectedCalendar.calendars ?? [])
|
||||||
.filter((cal) => cal.readOnly === false)
|
.filter((cal) => cal.readOnly === false)
|
||||||
.map((cal) => ({
|
.map((cal) => ({
|
||||||
label: `<span class="font-semibold">${cal.name}</span> (${cal.externalId})` || "",
|
label: `${cal.name} (${cal.externalId})` || "",
|
||||||
value: `${cal.integration}:${cal.externalId}`,
|
value: `${cal.integration}:${cal.externalId}`,
|
||||||
})),
|
})),
|
||||||
})) ?? [];
|
})) ?? [];
|
||||||
@@ -83,9 +83,6 @@ const DestinationCalendarSelector = ({
|
|||||||
title={`${t("select_destination_calendar")}: ${selectedOption?.label || ""}`}>
|
title={`${t("select_destination_calendar")}: ${selectedOption?.label || ""}`}>
|
||||||
<Select
|
<Select
|
||||||
name="primarySelectedCalendar"
|
name="primarySelectedCalendar"
|
||||||
formatOptionLabel={function (data) {
|
|
||||||
return <span dangerouslySetInnerHTML={{ __html: data.label }} />;
|
|
||||||
}}
|
|
||||||
placeholder={
|
placeholder={
|
||||||
!hidePlaceholder ? (
|
!hidePlaceholder ? (
|
||||||
`${t("select_destination_calendar")}`
|
`${t("select_destination_calendar")}`
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ function IntegrationListItem(props: {
|
|||||||
<ListItem
|
<ListItem
|
||||||
expanded={!!props.children}
|
expanded={!!props.children}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"my-0 flex-col rounded-none border-0 transition-colors duration-500",
|
"my-0 flex-col border transition-colors duration-500 first:rounded-t-md last:rounded-b-md",
|
||||||
highlight ? "bg-yellow-100" : ""
|
highlight ? "bg-yellow-100" : ""
|
||||||
)}>
|
)}>
|
||||||
<div className={classNames("flex w-full flex-1 items-center space-x-2 p-4 rtl:space-x-reverse")}>
|
<div className={classNames("flex w-full flex-1 items-center space-x-2 p-4 rtl:space-x-reverse")}>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { SkeletonText } from "@calcom/ui/v2";
|
import { SkeletonText } from "@calcom/ui/v2";
|
||||||
@@ -32,9 +33,13 @@ function SkeletonItem() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AvailabilitySelectSkeletonLoader = () => {
|
export const SelectSkeletonLoader = ({ className }: { className?: string }) => {
|
||||||
return (
|
return (
|
||||||
<li className="group flex w-full items-center justify-between rounded-sm border border-gray-200 px-[10px] py-3">
|
<li
|
||||||
|
className={classNames(
|
||||||
|
"group flex w-full items-center justify-between rounded-sm border border-gray-200 px-[10px] py-3",
|
||||||
|
className
|
||||||
|
)}>
|
||||||
<div className="flex-grow truncate text-sm">
|
<div className="flex-grow truncate text-sm">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<SkeletonText className="h-4 w-32" />
|
<SkeletonText className="h-4 w-32" />
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import { weekdayNames } from "@calcom/lib/weekday";
|
|||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { Icon } from "@calcom/ui";
|
import { Icon } from "@calcom/ui";
|
||||||
import Button from "@calcom/ui/v2/core/Button";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
import Select from "@calcom/ui/v2/core/form/Select";
|
import Select from "@calcom/ui/v2/core/form/select";
|
||||||
import { SkeletonText } from "@calcom/ui/v2/core/skeleton";
|
import { SkeletonText } from "@calcom/ui/v2/core/skeleton";
|
||||||
|
|
||||||
import { AvailabilitySelectSkeletonLoader } from "@components/v2/availability/SkeletonLoader";
|
import { SelectSkeletonLoader } from "@components/v2/availability/SkeletonLoader";
|
||||||
|
|
||||||
type AvailabilityOption = {
|
type AvailabilityOption = {
|
||||||
label: string;
|
label: string;
|
||||||
@@ -30,7 +30,7 @@ const AvailabilitySelect = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { data, isLoading } = trpc.useQuery(["viewer.availability.list"]);
|
const { data, isLoading } = trpc.useQuery(["viewer.availability.list"]);
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <AvailabilitySelectSkeletonLoader />;
|
return <SelectSkeletonLoader />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schedules = data?.schedules || [];
|
const schedules = data?.schedules || [];
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
DialogContent,
|
DialogContent,
|
||||||
Label,
|
Label,
|
||||||
showToast,
|
showToast,
|
||||||
|
Skeleton,
|
||||||
Switch,
|
Switch,
|
||||||
TextField,
|
TextField,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
@@ -37,12 +38,11 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
const connectedCalendarsQuery = trpc.useQuery(["viewer.connectedCalendars"]);
|
const connectedCalendarsQuery = trpc.useQuery(["viewer.connectedCalendars"]);
|
||||||
const formMethods = useFormContext<FormValues>();
|
const formMethods = useFormContext<FormValues>();
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const utils = trpc.useContext();
|
|
||||||
const [showEventNameTip, setShowEventNameTip] = useState(false);
|
const [showEventNameTip, setShowEventNameTip] = useState(false);
|
||||||
const [hashedLinkVisible, setHashedLinkVisible] = useState(!!eventType.hashedLink);
|
const [hashedLinkVisible, setHashedLinkVisible] = useState(!!eventType.hashedLink);
|
||||||
|
const [redirectUrlVisible, setRedirectUrlVisible] = useState(!!eventType.successRedirectUrl);
|
||||||
const [hashedUrl, setHashedUrl] = useState(eventType.hashedLink?.link);
|
const [hashedUrl, setHashedUrl] = useState(eventType.hashedLink?.link);
|
||||||
const [seatsInputVisible, setSeatsInputVisible] = useState(!!eventType.seatsPerTimeSlot);
|
const [seatsInputVisible, setSeatsInputVisible] = useState(!!eventType.seatsPerTimeSlot);
|
||||||
const [seatsPerTimeSlot, setSeatsPerTimeSlot] = useState(eventType.seatsPerTimeSlot);
|
|
||||||
const [customInputs, setCustomInputs] = useState<EventTypeCustomInput[]>(
|
const [customInputs, setCustomInputs] = useState<EventTypeCustomInput[]>(
|
||||||
eventType.customInputs.sort((a, b) => a.id - b.id) || []
|
eventType.customInputs.sort((a, b) => a.id - b.id) || []
|
||||||
);
|
);
|
||||||
@@ -51,7 +51,7 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
const placeholderHashedLink = `${CAL_URL}/d/${hashedUrl}/${eventType.slug}`;
|
const placeholderHashedLink = `${CAL_URL}/d/${hashedUrl}/${eventType.slug}`;
|
||||||
|
|
||||||
const animationRef = useRef(null);
|
const animationRef = useRef(null);
|
||||||
const seatsEnabled = !!eventType.seatsPerTimeSlot;
|
const seatsEnabled = formMethods.getValues("seatsPerTimeSlotEnabled");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
animationRef.current && autoAnimate(animationRef.current);
|
animationRef.current && autoAnimate(animationRef.current);
|
||||||
@@ -138,8 +138,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Label className="text-sm font-semibold leading-none text-black">{t("additional_inputs")}</Label>
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("additional_input_description")}</p>
|
{t("additional_inputs")}
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
|
{t("additional_input_description")}
|
||||||
|
</Skeleton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="my-4" ref={animationRef}>
|
<ul className="my-4" ref={animationRef}>
|
||||||
@@ -184,12 +188,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
fitToHeight={true}
|
fitToHeight={true}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Label className="text-sm font-semibold leading-none text-black">
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
{t("requires_confirmation")}
|
{t("requires_confirmation")}
|
||||||
</Label>
|
</Skeleton>
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
{t("requires_confirmation_description")}
|
{t("requires_confirmation_description")}
|
||||||
</p>
|
</Skeleton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -209,8 +213,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
disabled={seatsEnabled}
|
disabled={seatsEnabled}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Label className="text-sm font-semibold leading-none text-black">{t("disable_guests")}</Label>
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("disable_guests_description")}</p>
|
{t("disable_guests")}
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
|
{t("disable_guests_description")}
|
||||||
|
</Skeleton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -230,13 +238,59 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
onCheckedChange={(e) => onChange(e)}
|
onCheckedChange={(e) => onChange(e)}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Label className="text-sm font-semibold leading-none text-black">{t("disable_notes")}</Label>
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("disable_notes_description")}</p>
|
{t("disable_notes")}
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
|
{t("disable_notes_description")}
|
||||||
|
</Skeleton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<Controller
|
||||||
|
name="successRedirectUrl"
|
||||||
|
control={formMethods.control}
|
||||||
|
defaultValue={hashedUrl}
|
||||||
|
render={({ field: { value, onChange } }) => (
|
||||||
|
<>
|
||||||
|
<div className="flex space-x-3 ">
|
||||||
|
<Switch
|
||||||
|
name="successRedirectUrlCheck"
|
||||||
|
fitToHeight={true}
|
||||||
|
defaultChecked={redirectUrlVisible}
|
||||||
|
onCheckedChange={(e) => {
|
||||||
|
setRedirectUrlVisible(e);
|
||||||
|
onChange(e ? value : "");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
|
{t("redirect_success_booking")}
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
|
{t("redirect_url_description")}
|
||||||
|
</Skeleton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{redirectUrlVisible && (
|
||||||
|
<div className="">
|
||||||
|
<TextField
|
||||||
|
label={t("redirect_success_booking")}
|
||||||
|
placeholder={t("external_redirect_url")}
|
||||||
|
required={redirectUrlVisible}
|
||||||
|
type="text"
|
||||||
|
defaultValue={eventType.successRedirectUrl || ""}
|
||||||
|
{...formMethods.register("successRedirectUrl")}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<hr />
|
||||||
<Controller
|
<Controller
|
||||||
name="hashedLink"
|
name="hashedLink"
|
||||||
control={formMethods.control}
|
control={formMethods.control}
|
||||||
@@ -255,8 +309,12 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
<Label className="text-sm font-semibold leading-none text-black">{t("private_link")}</Label>
|
<Skeleton as={Label} className="text-sm font-semibold leading-none text-black">
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("private_link_description")}</p>
|
{t("private_link")}
|
||||||
|
</Skeleton>
|
||||||
|
<Skeleton as="p" className="-mt-2 text-sm leading-normal text-gray-600">
|
||||||
|
{t("private_link_description")}
|
||||||
|
</Skeleton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -297,44 +355,57 @@ export const EventAdvancedTab = ({ eventType, team }: Pick<EventTypeSetupInfered
|
|||||||
/>
|
/>
|
||||||
<hr />
|
<hr />
|
||||||
<Controller
|
<Controller
|
||||||
name="seatsPerTimeSlot"
|
name="seatsPerTimeSlotEnabled"
|
||||||
control={formMethods.control}
|
control={formMethods.control}
|
||||||
defaultValue={seatsPerTimeSlot}
|
defaultValue={!!eventType.seatsPerTimeSlot}
|
||||||
render={({ field: { value, onChange } }) => (
|
render={({ field: { value, onChange } }) => (
|
||||||
<>
|
<div className="flex space-x-3">
|
||||||
<div className="flex space-x-3">
|
<Switch
|
||||||
<Switch
|
name="seatsPerTimeSlotEnabled"
|
||||||
name="seatsPerTimeSlot"
|
checked={value}
|
||||||
checked={seatsInputVisible}
|
onCheckedChange={(e) => {
|
||||||
onCheckedChange={(e) => {
|
setSeatsInputVisible(e);
|
||||||
setSeatsInputVisible(e);
|
// Enabling seats will disable guests and requiring confimation until fully supported
|
||||||
onChange(e ? seatsPerTimeSlot : null);
|
if (e) {
|
||||||
}}
|
formMethods.setValue("disableGuests", true);
|
||||||
fitToHeight={true}
|
formMethods.setValue("requiresConfirmation", false);
|
||||||
/>
|
formMethods.setValue("seatsPerTimeSlot", 2);
|
||||||
<div className="flex flex-col">
|
} else {
|
||||||
<Label className="text-sm font-semibold leading-none text-black">{t("offer_seats")}</Label>
|
formMethods.setValue("seatsPerTimeSlot", null);
|
||||||
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("offer_seats_description")}</p>
|
}
|
||||||
</div>
|
onChange(e);
|
||||||
|
}}
|
||||||
|
fitToHeight={true}
|
||||||
|
/>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<Label className="text-sm font-semibold leading-none text-black">{t("offer_seats")}</Label>
|
||||||
|
<p className="-mt-2 text-sm leading-normal text-gray-600">{t("offer_seats_description")}</p>
|
||||||
</div>
|
</div>
|
||||||
{seatsInputVisible && (
|
</div>
|
||||||
<div className="">
|
|
||||||
<TextField
|
|
||||||
required
|
|
||||||
name="seatsPerTimeSlot"
|
|
||||||
label={t("number_of_seats")}
|
|
||||||
type="number"
|
|
||||||
defaultValue={seatsPerTimeSlot || 2}
|
|
||||||
addOnSuffix={<>{t("seats")}</>}
|
|
||||||
onChange={(e) => {
|
|
||||||
formMethods.setValue("seatsPerTimeSlot", Number(e.target.value));
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{seatsInputVisible && (
|
||||||
|
<Controller
|
||||||
|
name="seatsPerTimeSlot"
|
||||||
|
control={formMethods.control}
|
||||||
|
defaultValue={eventType.seatsPerTimeSlot}
|
||||||
|
render={({ field: { value, onChange } }) => (
|
||||||
|
<div className="">
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
name="seatsPerTimeSlot"
|
||||||
|
label={t("number_of_seats")}
|
||||||
|
type="number"
|
||||||
|
defaultValue={value || 2}
|
||||||
|
addOnSuffix={<>{t("seats")}</>}
|
||||||
|
onChange={(e) => {
|
||||||
|
onChange(Number(e.target.value));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
{showEventNameTip && (
|
{showEventNameTip && (
|
||||||
<Dialog open={showEventNameTip} onOpenChange={setShowEventNameTip}>
|
<Dialog open={showEventNameTip} onOpenChange={setShowEventNameTip}>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useFormContext, Controller, useWatch } from "react-hook-form";
|
|||||||
import { classNames } from "@calcom/lib";
|
import { classNames } from "@calcom/lib";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { PeriodType } from "@calcom/prisma/client";
|
import { PeriodType } from "@calcom/prisma/client";
|
||||||
import { Select, Switch, Label, Input } from "@calcom/ui/v2";
|
import { Select, Switch, Label, Input, MinutesField } from "@calcom/ui/v2";
|
||||||
import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker";
|
import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker";
|
||||||
|
|
||||||
export const EventLimitsTab = (props: Pick<EventTypeSetupInfered, "eventType">) => {
|
export const EventLimitsTab = (props: Pick<EventTypeSetupInfered, "eventType">) => {
|
||||||
@@ -113,35 +113,12 @@ export const EventLimitsTab = (props: Pick<EventTypeSetupInfered, "eventType">)
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col space-y-4 pt-4 lg:flex-row lg:space-y-0 lg:space-x-4">
|
<div className="flex flex-col space-y-4 pt-4 lg:flex-row lg:space-y-0 lg:space-x-4">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Label htmlFor="minimumBookingNotice">{t("minimum_booking_notice")} </Label>
|
<MinutesField
|
||||||
<Controller
|
required
|
||||||
name="minimumBookingNotice"
|
label={t("minimum_booking_notice")}
|
||||||
control={formMethods.control}
|
type="number"
|
||||||
defaultValue={eventType.minimumBookingNotice || 0}
|
placeholder="120"
|
||||||
render={({ field: { onChange, value } }) => {
|
{...formMethods.register("minimumBookingNotice", { valueAsNumber: true })}
|
||||||
const minimumBookingOptions = [
|
|
||||||
{
|
|
||||||
label: t("event_buffer_default"),
|
|
||||||
value: 0,
|
|
||||||
},
|
|
||||||
...[5, 10, 15, 20, 30, 45, 60, 90, 120].map((minutes) => ({
|
|
||||||
label: minutes + " " + t("minutes"),
|
|
||||||
value: minutes,
|
|
||||||
})),
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
isSearchable={false}
|
|
||||||
onChange={(val) => {
|
|
||||||
if (val) onChange(val.value);
|
|
||||||
}}
|
|
||||||
defaultValue={
|
|
||||||
minimumBookingOptions.find((option) => option.value === value) || minimumBookingOptions[0]
|
|
||||||
}
|
|
||||||
options={minimumBookingOptions}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { getEventLocationType, EventLocationType } from "@calcom/app-store/locat
|
|||||||
import { CAL_URL } from "@calcom/lib/constants";
|
import { CAL_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import { Select, Label, TextField, Button } from "@calcom/ui/v2";
|
import { Select, Label, TextField, Button, Skeleton } from "@calcom/ui/v2";
|
||||||
|
|
||||||
import { slugify } from "@lib/slugify";
|
import { slugify } from "@lib/slugify";
|
||||||
|
|
||||||
@@ -222,7 +222,9 @@ export const EventSetupTab = (
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("location")}</Label>
|
<Skeleton as={Label} loadingClassName="w-16">
|
||||||
|
{t("location")}
|
||||||
|
</Skeleton>
|
||||||
<Controller
|
<Controller
|
||||||
name="locations"
|
name="locations"
|
||||||
control={formMethods.control}
|
control={formMethods.control}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { TFunction } from "next-i18next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { EventTypeSetupInfered, FormValues } from "pages/v2/event-types/[type]";
|
import { EventTypeSetupInfered, FormValues } from "pages/v2/event-types/[type]";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { Loader } from "react-feather";
|
import { Loader } from "react-feather";
|
||||||
import { UseFormReturn } from "react-hook-form";
|
import { UseFormReturn } from "react-hook-form";
|
||||||
|
|
||||||
@@ -9,20 +10,18 @@ import { CAL_URL } from "@calcom/lib/constants";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { HttpError } from "@calcom/lib/http-error";
|
import { HttpError } from "@calcom/lib/http-error";
|
||||||
import { trpc, TRPCClientError } from "@calcom/trpc/react";
|
import { trpc, TRPCClientError } from "@calcom/trpc/react";
|
||||||
import ConfirmationDialogContent from "@calcom/ui/ConfirmationDialogContent";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Tooltip,
|
|
||||||
showToast,
|
|
||||||
VerticalTabItemProps,
|
|
||||||
VerticalTabs,
|
|
||||||
HorizontalTabs,
|
HorizontalTabs,
|
||||||
Switch,
|
|
||||||
Label,
|
Label,
|
||||||
HorizontalTabItemProps,
|
showToast,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
VerticalTabs,
|
||||||
} from "@calcom/ui/v2";
|
} from "@calcom/ui/v2";
|
||||||
|
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
||||||
import { Dialog } from "@calcom/ui/v2/core/Dialog";
|
import { Dialog } from "@calcom/ui/v2/core/Dialog";
|
||||||
import Dropdown, {
|
import Dropdown, {
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -31,6 +30,7 @@ import Dropdown, {
|
|||||||
} from "@calcom/ui/v2/core/Dropdown";
|
} from "@calcom/ui/v2/core/Dropdown";
|
||||||
import Shell from "@calcom/ui/v2/core/Shell";
|
import Shell from "@calcom/ui/v2/core/Shell";
|
||||||
import VerticalDivider from "@calcom/ui/v2/core/VerticalDivider";
|
import VerticalDivider from "@calcom/ui/v2/core/VerticalDivider";
|
||||||
|
import { Skeleton } from "@calcom/ui/v2/core/skeleton";
|
||||||
|
|
||||||
import { ClientSuspense } from "@components/ClientSuspense";
|
import { ClientSuspense } from "@components/ClientSuspense";
|
||||||
import { EmbedButton, EmbedDialog } from "@components/Embed";
|
import { EmbedButton, EmbedDialog } from "@components/Embed";
|
||||||
@@ -46,6 +46,59 @@ type Props = {
|
|||||||
formMethods: UseFormReturn<FormValues>;
|
formMethods: UseFormReturn<FormValues>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getNavigation(props: {
|
||||||
|
t: TFunction;
|
||||||
|
eventType: Props["eventType"];
|
||||||
|
enabledAppsNumber: number;
|
||||||
|
enabledWorkflowsNumber: number;
|
||||||
|
}) {
|
||||||
|
const { eventType, t, enabledAppsNumber, enabledWorkflowsNumber } = props;
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "event_setup_tab_title",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=setup`,
|
||||||
|
icon: Icon.FiLink,
|
||||||
|
info: `${eventType.length} Mins`, // TODO: Get this from props
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "availability",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=availability`,
|
||||||
|
icon: Icon.FiCalendar,
|
||||||
|
info: `Working Hours`, // TODO: Get this from props
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "event_limit_tab_title",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=limits`,
|
||||||
|
icon: Icon.FiClock,
|
||||||
|
info: `event_limit_tab_description`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "event_advanced_tab_title",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=advanced`,
|
||||||
|
icon: Icon.FiSliders,
|
||||||
|
info: `event_advanced_tab_description`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recurring",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=recurring`,
|
||||||
|
icon: Icon.FiRepeat,
|
||||||
|
info: `recurring_event_tab_description`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apps",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=apps`,
|
||||||
|
icon: Icon.FiGrid,
|
||||||
|
info: `${enabledAppsNumber} ${t("active")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "workflows",
|
||||||
|
href: `/event-types/${eventType.id}?tabName=workflows`,
|
||||||
|
icon: Icon.FiZap,
|
||||||
|
info: `${enabledWorkflowsNumber} ${t("active")}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
function EventTypeSingleLayout({
|
function EventTypeSingleLayout({
|
||||||
children,
|
children,
|
||||||
eventType,
|
eventType,
|
||||||
@@ -57,8 +110,8 @@ function EventTypeSingleLayout({
|
|||||||
formMethods,
|
formMethods,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
const router = useRouter();
|
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
const router = useRouter();
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
|
|
||||||
const hasPermsToDelete = currentUserMembership?.role !== "MEMBER" || !currentUserMembership;
|
const hasPermsToDelete = currentUserMembership?.role !== "MEMBER" || !currentUserMembership;
|
||||||
@@ -67,6 +120,7 @@ function EventTypeSingleLayout({
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await utils.invalidateQueries(["viewer.eventTypes"]);
|
await utils.invalidateQueries(["viewer.eventTypes"]);
|
||||||
showToast(t("event_type_deleted_successfully"), "success");
|
showToast(t("event_type_deleted_successfully"), "success");
|
||||||
|
await router.push("/event-types");
|
||||||
setDeleteDialogOpen(false);
|
setDeleteDialogOpen(false);
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
onError: (err) => {
|
||||||
@@ -82,73 +136,17 @@ function EventTypeSingleLayout({
|
|||||||
|
|
||||||
// Define tab navigation here
|
// Define tab navigation here
|
||||||
const EventTypeTabs = useMemo(() => {
|
const EventTypeTabs = useMemo(() => {
|
||||||
const navigation: (VerticalTabItemProps & HorizontalTabItemProps)[] = [
|
const navigation = getNavigation({ t, eventType, enabledAppsNumber, enabledWorkflowsNumber });
|
||||||
{
|
|
||||||
name: "event_setup_tab_title",
|
|
||||||
tabName: "setup",
|
|
||||||
icon: Icon.FiLink,
|
|
||||||
info: `${eventType.length} Mins`, // TODO: Get this from props
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "availability",
|
|
||||||
tabName: "availability",
|
|
||||||
icon: Icon.FiCalendar,
|
|
||||||
info: `Working Hours`, // TODO: Get this from props
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "event_limit_tab_title",
|
|
||||||
tabName: "limits",
|
|
||||||
icon: Icon.FiClock,
|
|
||||||
info: `event_limit_tab_description`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "event_advanced_tab_title",
|
|
||||||
tabName: "advanced",
|
|
||||||
icon: Icon.FiSliders,
|
|
||||||
info: `event_advanced_tab_description`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "recurring",
|
|
||||||
tabName: "recurring",
|
|
||||||
icon: Icon.FiRepeat,
|
|
||||||
info: `recurring_event_tab_description`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "apps",
|
|
||||||
tabName: "apps",
|
|
||||||
icon: Icon.FiGrid,
|
|
||||||
info: `${enabledAppsNumber} ${t("active")}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "workflows",
|
|
||||||
tabName: "workflows",
|
|
||||||
icon: Icon.FiZap,
|
|
||||||
info: `${enabledWorkflowsNumber} ${t("active")}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// If there is a team put this navigation item within the tabs
|
// If there is a team put this navigation item within the tabs
|
||||||
if (team)
|
if (team)
|
||||||
navigation.splice(2, 0, {
|
navigation.splice(2, 0, {
|
||||||
name: "scheduling_type",
|
name: "scheduling_type",
|
||||||
tabName: "team",
|
href: `/event-types/${eventType.id}?tabName=team`,
|
||||||
icon: Icon.FiUsers,
|
icon: Icon.FiUsers,
|
||||||
info: eventType.schedulingType === "COLLECTIVE" ? "collective" : "round_robin",
|
info: eventType.schedulingType === "COLLECTIVE" ? "collective" : "round_robin",
|
||||||
});
|
});
|
||||||
return navigation;
|
return navigation;
|
||||||
}, [eventType, enabledAppsNumber, team]);
|
}, [t, eventType, enabledAppsNumber, enabledWorkflowsNumber, team]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Default to the first in the list
|
|
||||||
if (!router.query.tabName) {
|
|
||||||
router.push({
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
tabName: EventTypeTabs[0].tabName,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [EventTypeTabs, router]);
|
|
||||||
|
|
||||||
const permalink = `${CAL_URL}/${team ? `team/${team.slug}` : eventType.users[0].username}/${
|
const permalink = `${CAL_URL}/${team ? `team/${team.slug}` : eventType.users[0].username}/${
|
||||||
eventType.slug
|
eventType.slug
|
||||||
@@ -159,15 +157,18 @@ function EventTypeSingleLayout({
|
|||||||
return (
|
return (
|
||||||
<Shell
|
<Shell
|
||||||
backPath="/event-types"
|
backPath="/event-types"
|
||||||
title={t("event_type_title", { eventTypeTitle: eventType.title })}
|
title={eventType.title + " | " + t("event_type")}
|
||||||
heading={eventType.title}
|
heading={eventType.title}
|
||||||
subtitle={eventType.description || ""}
|
subtitle={eventType.description || ""}
|
||||||
CTA={
|
CTA={
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
<div className="flex items-center rounded-md px-2 sm:hover:bg-gray-100">
|
<div className="flex items-center rounded-md px-2 sm:hover:bg-gray-100">
|
||||||
<Label htmlFor="hiddenSwitch" className="mt-2 hidden cursor-pointer self-center pr-2 sm:inline">
|
<Skeleton
|
||||||
|
as={Label}
|
||||||
|
htmlFor="hiddenSwitch"
|
||||||
|
className="mt-2 hidden cursor-pointer self-center pr-2 sm:inline">
|
||||||
{t("hide_from_profile")}
|
{t("hide_from_profile")}
|
||||||
</Label>
|
</Skeleton>
|
||||||
<Switch
|
<Switch
|
||||||
id="hiddenSwitch"
|
id="hiddenSwitch"
|
||||||
defaultChecked={formMethods.getValues("hidden")}
|
defaultChecked={formMethods.getValues("hidden")}
|
||||||
@@ -208,6 +209,7 @@ function EventTypeSingleLayout({
|
|||||||
StartIcon={Icon.FiCode}
|
StartIcon={Icon.FiCode}
|
||||||
color="secondary"
|
color="secondary"
|
||||||
size="icon"
|
size="icon"
|
||||||
|
tooltip={t("embed")}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
color="secondary"
|
color="secondary"
|
||||||
@@ -226,27 +228,29 @@ function EventTypeSingleLayout({
|
|||||||
<Icon.FiMoreHorizontal className="group-hover:text-gray-800" />
|
<Icon.FiMoreHorizontal className="group-hover:text-gray-800" />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent>
|
<DropdownMenuContent>
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem className="focus:ring-gray-100">
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
StartIcon={Icon.FiExternalLink}
|
StartIcon={Icon.FiExternalLink}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href={permalink}
|
href={permalink}
|
||||||
rel="noreferrer">
|
rel="noreferrer"
|
||||||
|
className="min-w-full">
|
||||||
{t("preview")}
|
{t("preview")}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem className="focus:ring-gray-100">
|
||||||
<Button color="minimal" StartIcon={Icon.FiLink}>
|
<Button color="minimal" StartIcon={Icon.FiLink}>
|
||||||
{t("copy_link")}
|
{t("copy_link")}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem>
|
<DropdownMenuItem className="focus:ring-gray-100">
|
||||||
<Button
|
<Button
|
||||||
color="minimal"
|
color="minimal"
|
||||||
StartIcon={Icon.FiTrash}
|
StartIcon={Icon.FiTrash}
|
||||||
disabled={!hasPermsToDelete}
|
disabled={!hasPermsToDelete}
|
||||||
onClick={() => setDeleteDialogOpen(true)}>
|
onClick={() => setDeleteDialogOpen(true)}
|
||||||
|
className="min-w-full">
|
||||||
{t("delete")}
|
{t("delete")}
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -265,10 +269,15 @@ function EventTypeSingleLayout({
|
|||||||
<ClientSuspense fallback={<Loader />}>
|
<ClientSuspense fallback={<Loader />}>
|
||||||
<div className="-mt-2 flex flex-col xl:flex-row xl:space-x-8">
|
<div className="-mt-2 flex flex-col xl:flex-row xl:space-x-8">
|
||||||
<div className="hidden xl:block">
|
<div className="hidden xl:block">
|
||||||
<VerticalTabs className="primary-navigation" tabs={EventTypeTabs} sticky />
|
<VerticalTabs
|
||||||
|
className="primary-navigation"
|
||||||
|
tabs={EventTypeTabs}
|
||||||
|
sticky
|
||||||
|
linkProps={{ shallow: true }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 md:mx-0 md:p-0 xl:hidden">
|
<div className="p-2 md:mx-0 md:p-0 xl:hidden">
|
||||||
<HorizontalTabs tabNameKey="tabName" tabs={EventTypeTabs} />
|
<HorizontalTabs tabs={EventTypeTabs} linkProps={{ shallow: true }} />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full ltr:mr-2 rtl:ml-2">
|
<div className="w-full ltr:mr-2 rtl:ml-2">
|
||||||
<div
|
<div
|
||||||
@@ -292,7 +301,7 @@ function EventTypeSingleLayout({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
deleteMutation.mutate({ id: eventType.id });
|
deleteMutation.mutate({ id: eventType.id });
|
||||||
}}>
|
}}>
|
||||||
{t("delete_event_type_description") as string}
|
{t("delete_event_type_description")}
|
||||||
</ConfirmationDialogContent>
|
</ConfirmationDialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<EmbedDialog />
|
<EmbedDialog />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useMutation } from "react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
@@ -12,6 +12,7 @@ export function CalendarSwitch(props: {
|
|||||||
externalId: string;
|
externalId: string;
|
||||||
title: string;
|
title: string;
|
||||||
defaultSelected: boolean;
|
defaultSelected: boolean;
|
||||||
|
isSelected: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ export function CalendarSwitch(props: {
|
|||||||
key={props.externalId}
|
key={props.externalId}
|
||||||
name="enabled"
|
name="enabled"
|
||||||
label={props.title}
|
label={props.title}
|
||||||
defaultChecked={props.defaultSelected}
|
defaultChecked={props.isSelected}
|
||||||
onCheckedChange={(isOn: boolean) => {
|
onCheckedChange={(isOn: boolean) => {
|
||||||
mutation.mutate({ isOn });
|
mutation.mutate({ isOn });
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
import { ReactNode } from "react";
|
|
||||||
import {
|
import {
|
||||||
QueryObserverIdleResult,
|
|
||||||
QueryObserverLoadingErrorResult,
|
QueryObserverLoadingErrorResult,
|
||||||
QueryObserverLoadingResult,
|
QueryObserverLoadingResult,
|
||||||
QueryObserverRefetchErrorResult,
|
QueryObserverRefetchErrorResult,
|
||||||
QueryObserverSuccessResult,
|
QueryObserverSuccessResult,
|
||||||
UseQueryResult,
|
UseQueryResult,
|
||||||
} from "react-query";
|
} from "@tanstack/react-query";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
|
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||||
import type { UseTRPCQueryOptions } from "@calcom/trpc/react";
|
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import type {
|
import type {
|
||||||
inferHandlerInput,
|
inferHandlerInput,
|
||||||
@@ -22,6 +20,8 @@ import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
|||||||
import { Alert } from "@calcom/ui/Alert";
|
import { Alert } from "@calcom/ui/Alert";
|
||||||
import Loader from "@calcom/ui/Loader";
|
import Loader from "@calcom/ui/Loader";
|
||||||
|
|
||||||
|
import type { UseTRPCQueryOptions } from "@trpc/react/shared";
|
||||||
|
|
||||||
type ErrorLike = {
|
type ErrorLike = {
|
||||||
message: string;
|
message: string;
|
||||||
};
|
};
|
||||||
@@ -34,7 +34,6 @@ interface QueryCellOptionsBase<TData, TError extends ErrorLike> {
|
|||||||
query: QueryObserverLoadingErrorResult<TData, TError> | QueryObserverRefetchErrorResult<TData, TError>
|
query: QueryObserverLoadingErrorResult<TData, TError> | QueryObserverRefetchErrorResult<TData, TError>
|
||||||
) => JSXElementOrNull;
|
) => JSXElementOrNull;
|
||||||
loading?: (query: QueryObserverLoadingResult<TData, TError> | null) => JSXElementOrNull;
|
loading?: (query: QueryObserverLoadingResult<TData, TError> | null) => JSXElementOrNull;
|
||||||
idle?: (query: QueryObserverIdleResult<TData, TError>) => JSXElementOrNull;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface QueryCellOptionsNoEmpty<TData, TError extends ErrorLike>
|
interface QueryCellOptionsNoEmpty<TData, TError extends ErrorLike>
|
||||||
@@ -84,14 +83,11 @@ export function QueryCell<TData, TError extends ErrorLike>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.status === "idle") {
|
|
||||||
return opts.idle?.(query) ?? StatusLoader;
|
|
||||||
}
|
|
||||||
// impossible state
|
// impossible state
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type inferProcedures<TObj extends ProcedureRecord<any, any, any, any, any, any>> = {
|
type inferProcedures<TObj extends ProcedureRecord> = {
|
||||||
[TPath in keyof TObj]: {
|
[TPath in keyof TObj]: {
|
||||||
input: inferProcedureInput<TObj[TPath]>;
|
input: inferProcedureInput<TObj[TPath]>;
|
||||||
output: inferProcedureOutput<TObj[TPath]>;
|
output: inferProcedureOutput<TObj[TPath]>;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ComponentProps, ReactNode } from "react";
|
|||||||
|
|
||||||
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic";
|
import DynamicHelpscoutProvider from "@calcom/features/ee/support/lib/helpscout/providerDynamic";
|
||||||
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic";
|
import DynamicIntercomProvider from "@calcom/features/ee/support/lib/intercom/providerDynamic";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc, proxy } from "@calcom/trpc/react";
|
||||||
import { MetaProvider } from "@calcom/ui/v2/core/Meta";
|
import { MetaProvider } from "@calcom/ui/v2/core/Meta";
|
||||||
|
|
||||||
import usePublicPage from "@lib/hooks/usePublicPage";
|
import usePublicPage from "@lib/hooks/usePublicPage";
|
||||||
@@ -38,7 +38,8 @@ const CustomI18nextProvider = (props: AppPropsWithChildren) => {
|
|||||||
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
||||||
* We intend to not cache i18n query
|
* We intend to not cache i18n query
|
||||||
**/
|
**/
|
||||||
const { i18n, locale } = trpc.useQuery(["viewer.public.i18n"], { context: { skipBatch: true } }).data ?? {
|
const { i18n, locale } = trpc.useQuery(["viewer.public.i18n"], { trpc: { context: { skipBatch: true } } })
|
||||||
|
.data ?? {
|
||||||
locale: "en",
|
locale: "en",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,7 +55,7 @@ const CustomI18nextProvider = (props: AppPropsWithChildren) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const AppProviders = (props: AppPropsWithChildren) => {
|
const AppProviders = (props: AppPropsWithChildren) => {
|
||||||
const session = trpc.useQuery(["viewer.public.session"]).data;
|
const session = proxy.public.session.useQuery().data;
|
||||||
// No need to have intercom on public pages - Good for Page Performance
|
// No need to have intercom on public pages - Good for Page Performance
|
||||||
const isPublicPage = usePublicPage();
|
const isPublicPage = usePublicPage();
|
||||||
const isThemeSupported =
|
const isThemeSupported =
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
// handles logic related to user clock display using 24h display / timeZone options.
|
// handles logic related to user clock display using 24h display / timeZone options.
|
||||||
import dayjs from "@calcom/dayjs";
|
import dayjs from "@calcom/dayjs";
|
||||||
import { isBrowserLocale24h } from "@calcom/lib/timeFormat";
|
import {
|
||||||
|
getIs24hClockFromLocalStorage,
|
||||||
|
isBrowserLocale24h,
|
||||||
|
setIs24hClockInLocalStorage,
|
||||||
|
} from "@calcom/lib/timeFormat";
|
||||||
import { localStorage } from "@calcom/lib/webstorage";
|
import { localStorage } from "@calcom/lib/webstorage";
|
||||||
|
|
||||||
interface TimeOptions {
|
interface TimeOptions {
|
||||||
@@ -20,8 +24,8 @@ const initClock = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// This only sets browser locale if there's no preference on localStorage.
|
// This only sets browser locale if there's no preference on localStorage.
|
||||||
if (!localStorage.getItem("timeOption.is24hClock")) set24hClock(isBrowserLocale24h());
|
if (getIs24hClockFromLocalStorage() === null) set24hClock(isBrowserLocale24h());
|
||||||
timeOptions.is24hClock = localStorage.getItem("timeOption.is24hClock") === "true";
|
timeOptions.is24hClock = !!getIs24hClockFromLocalStorage();
|
||||||
timeOptions.inviteeTimeZone = localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess();
|
timeOptions.inviteeTimeZone = localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32,7 +36,7 @@ const is24h = (is24hClock?: boolean) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const set24hClock = (is24hClock: boolean) => {
|
const set24hClock = (is24hClock: boolean) => {
|
||||||
localStorage.setItem("timeOption.is24hClock", is24hClock.toString());
|
setIs24hClockInLocalStorage(is24hClock);
|
||||||
timeOptions.is24hClock = is24hClock;
|
timeOptions.is24hClock = is24hClock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,14 +47,27 @@ export const parseRecurringDates = (
|
|||||||
return [dateStrings, rule.all()];
|
return [dateStrings, rule.all()];
|
||||||
};
|
};
|
||||||
|
|
||||||
type BookingItem = inferQueryOutput<"viewer.bookings">["bookings"][number];
|
|
||||||
|
|
||||||
export const extractRecurringDates = (
|
export const extractRecurringDates = (
|
||||||
bookings: BookingItem[],
|
booking: inferQueryOutput<"viewer.bookings">["bookings"][number] & {
|
||||||
|
eventType: { recurringEvent: RecurringEvent | null };
|
||||||
|
recurringEventId: string | null;
|
||||||
|
recurringBookings: inferQueryOutput<"viewer.bookings">["recurringInfo"];
|
||||||
|
},
|
||||||
timeZone: string | undefined,
|
timeZone: string | undefined,
|
||||||
i18n: I18n
|
i18n: I18n
|
||||||
): [string[], Date[]] => {
|
): [string[], Date[]] => {
|
||||||
const dateStrings = bookings.map((booking) => processDate(dayjs(booking.startTime).tz(timeZone), i18n));
|
const { count = 0, ...rest } =
|
||||||
const allDates = dateStrings.map((dateString) => dayjs(dateString).tz(timeZone).toDate());
|
booking.eventType.recurringEvent !== null ? booking.eventType.recurringEvent : {};
|
||||||
|
const recurringInfo = booking.recurringBookings.find(
|
||||||
|
(val) => val.recurringEventId === booking.recurringEventId
|
||||||
|
);
|
||||||
|
const allDates = new RRule({
|
||||||
|
...rest,
|
||||||
|
count: recurringInfo?._count.recurringEventId,
|
||||||
|
dtstart: recurringInfo?._min.startTime,
|
||||||
|
}).all();
|
||||||
|
const dateStrings = allDates.map((r) => {
|
||||||
|
return processDate(dayjs(r).tz(timeZone), i18n);
|
||||||
|
});
|
||||||
return [dateStrings, allDates];
|
return [dateStrings, allDates];
|
||||||
};
|
};
|
||||||
@@ -9,10 +9,10 @@ export const WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP = {
|
|||||||
WebhookTriggerEvents.BOOKING_RESCHEDULED,
|
WebhookTriggerEvents.BOOKING_RESCHEDULED,
|
||||||
WebhookTriggerEvents.MEETING_ENDED,
|
WebhookTriggerEvents.MEETING_ENDED,
|
||||||
] as const,
|
] as const,
|
||||||
routing_forms: [WebhookTriggerEvents.FORM_SUBMITTED] as ["FORM_SUBMITTED"],
|
"routing-forms": [WebhookTriggerEvents.FORM_SUBMITTED] as ["FORM_SUBMITTED"],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const WEBHOOK_TRIGGER_EVENTS = [
|
export const WEBHOOK_TRIGGER_EVENTS = [
|
||||||
...WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP.core,
|
...WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP.core,
|
||||||
...WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP.routing_forms,
|
...WEBHOOK_TRIGGER_EVENTS_GROUPED_BY_APP["routing-forms"],
|
||||||
] as const;
|
] as const;
|
||||||
+11
-1
@@ -7,6 +7,7 @@ import { extendEventData, nextCollectBasicSettings } from "@calcom/lib/telemetry
|
|||||||
|
|
||||||
const V2_WHITELIST = [
|
const V2_WHITELIST = [
|
||||||
"/settings/admin",
|
"/settings/admin",
|
||||||
|
"/settings/billing",
|
||||||
"/settings/developer/webhooks",
|
"/settings/developer/webhooks",
|
||||||
"/settings/developer/api-keys",
|
"/settings/developer/api-keys",
|
||||||
"/settings/my-account",
|
"/settings/my-account",
|
||||||
@@ -24,7 +25,8 @@ const V2_WHITELIST = [
|
|||||||
|
|
||||||
// For pages
|
// For pages
|
||||||
// - which has V1 versions being modified as V2
|
// - which has V1 versions being modified as V2
|
||||||
const V2_BLACKLIST = ["/apps/routing_forms/"];
|
// - Add routing_forms to keep old links working
|
||||||
|
const V2_BLACKLIST = ["/apps/routing_forms/", "/apps/routing-forms/", "/apps/typeform/"];
|
||||||
|
|
||||||
const middleware: NextMiddleware = async (req) => {
|
const middleware: NextMiddleware = async (req) => {
|
||||||
const url = req.nextUrl;
|
const url = req.nextUrl;
|
||||||
@@ -43,6 +45,13 @@ const middleware: NextMiddleware = async (req) => {
|
|||||||
return NextResponse.redirect(req.nextUrl);
|
return NextResponse.redirect(req.nextUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't 404 old routing_forms links
|
||||||
|
if (url.pathname.startsWith("/apps/routing_forms")) {
|
||||||
|
url.pathname = url.pathname.replace("/apps/routing_forms", "/apps/routing-forms");
|
||||||
|
return NextResponse.rewrite(url);
|
||||||
|
}
|
||||||
|
|
||||||
/** Display available V2 pages */
|
/** Display available V2 pages */
|
||||||
if (
|
if (
|
||||||
!V2_BLACKLIST.some((p) => url.pathname.startsWith(p)) &&
|
!V2_BLACKLIST.some((p) => url.pathname.startsWith(p)) &&
|
||||||
@@ -52,6 +61,7 @@ const middleware: NextMiddleware = async (req) => {
|
|||||||
url.pathname = `/v2${url.pathname}`;
|
url.pathname = `/v2${url.pathname}`;
|
||||||
return NextResponse.rewrite(url);
|
return NextResponse.rewrite(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.next();
|
return NextResponse.next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -135,11 +135,11 @@ const nextConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: "/forms/:formId",
|
source: "/forms/:formId",
|
||||||
destination: "/apps/routing_forms/routing-link/:formId",
|
destination: "/apps/routing-forms/routing-link/:formId",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: "/router",
|
source: "/router",
|
||||||
destination: "/apps/routing_forms/router",
|
destination: "/apps/routing-forms/router",
|
||||||
},
|
},
|
||||||
/* TODO: have these files being served from another deployment or CDN {
|
/* TODO: have these files being served from another deployment or CDN {
|
||||||
source: "/embed/embed.js",
|
source: "/embed/embed.js",
|
||||||
@@ -159,6 +159,11 @@ const nextConfig = {
|
|||||||
destination: "/settings/my-account/profile",
|
destination: "/settings/my-account/profile",
|
||||||
permanent: true,
|
permanent: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
source: "/settings/teams",
|
||||||
|
destination: "/teams",
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
/* V2 testers get redirected to the new settings */
|
/* V2 testers get redirected to the new settings */
|
||||||
{
|
{
|
||||||
source: "/settings/profile",
|
source: "/settings/profile",
|
||||||
|
|||||||
+12
-11
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@calcom/web",
|
"name": "@calcom/web",
|
||||||
"version": "2.0.1",
|
"version": "2.0.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"analyze": "ANALYZE=true next build",
|
"analyze": "ANALYZE=true next build",
|
||||||
@@ -45,18 +45,20 @@
|
|||||||
"@hookform/resolvers": "^2.9.7",
|
"@hookform/resolvers": "^2.9.7",
|
||||||
"@next-auth/prisma-adapter": "^1.0.4",
|
"@next-auth/prisma-adapter": "^1.0.4",
|
||||||
"@next/bundle-analyzer": "12.1.6",
|
"@next/bundle-analyzer": "12.1.6",
|
||||||
"@radix-ui/react-avatar": "^0.1.4",
|
"@radix-ui/react-avatar": "^1.0.0",
|
||||||
"@radix-ui/react-collapsible": "^0.1.0",
|
"@radix-ui/react-collapsible": "^1.0.0",
|
||||||
"@radix-ui/react-dialog": "^0.1.0",
|
"@radix-ui/react-dialog": "^1.0.0",
|
||||||
"@radix-ui/react-dropdown-menu": "^0.1.1",
|
"@radix-ui/react-dropdown-menu": "^1.0.0",
|
||||||
"@radix-ui/react-id": "^0.1.0",
|
"@radix-ui/react-id": "^1.0.0",
|
||||||
"@radix-ui/react-radio-group": "^0.1.1",
|
"@radix-ui/react-popover": "^1.0.0",
|
||||||
"@radix-ui/react-slider": "^0.1.1",
|
"@radix-ui/react-radio-group": "^1.0.0",
|
||||||
"@radix-ui/react-switch": "^0.1.1",
|
"@radix-ui/react-slider": "^1.0.0",
|
||||||
"@radix-ui/react-toggle-group": "^0.1.5",
|
"@radix-ui/react-switch": "^1.0.0",
|
||||||
|
"@radix-ui/react-toggle-group": "^1.0.0",
|
||||||
"@radix-ui/react-tooltip": "^1.0.0",
|
"@radix-ui/react-tooltip": "^1.0.0",
|
||||||
"@stripe/react-stripe-js": "^1.10.0",
|
"@stripe/react-stripe-js": "^1.10.0",
|
||||||
"@stripe/stripe-js": "^1.35.0",
|
"@stripe/stripe-js": "^1.35.0",
|
||||||
|
"@tanstack/react-query": "^4.3.9",
|
||||||
"@vercel/edge-functions-ui": "^0.2.1",
|
"@vercel/edge-functions-ui": "^0.2.1",
|
||||||
"@wojtekmaj/react-daterange-picker": "^3.3.1",
|
"@wojtekmaj/react-daterange-picker": "^3.3.1",
|
||||||
"accept-language-parser": "^1.5.0",
|
"accept-language-parser": "^1.5.0",
|
||||||
@@ -105,7 +107,6 @@
|
|||||||
"react-live-chat-loader": "^2.7.3",
|
"react-live-chat-loader": "^2.7.3",
|
||||||
"react-multi-email": "^0.5.3",
|
"react-multi-email": "^0.5.3",
|
||||||
"react-phone-number-input": "^3.2.7",
|
"react-phone-number-input": "^3.2.7",
|
||||||
"react-query": "^3.39.2",
|
|
||||||
"react-select": "^5.4.0",
|
"react-select": "^5.4.0",
|
||||||
"react-timezone-select": "^1.3.2",
|
"react-timezone-select": "^1.3.2",
|
||||||
"react-use-intercom": "1.5.1",
|
"react-use-intercom": "1.5.1",
|
||||||
|
|||||||
+29
-31
@@ -73,7 +73,7 @@ export default function Custom404() {
|
|||||||
<ul role="list" className="mt-4">
|
<ul role="list" className="mt-4">
|
||||||
<li className="border-2 border-green-500 px-4 py-2">
|
<li className="border-2 border-green-500 px-4 py-2">
|
||||||
<a
|
<a
|
||||||
href={`${WEBSITE_URL}/pricing?infra`}
|
href="https://console.cal.com"
|
||||||
className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
|
className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
|
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
|
||||||
@@ -190,12 +190,10 @@ export default function Custom404() {
|
|||||||
{t("check_spelling_mistakes_or_go_back")}
|
{t("check_spelling_mistakes_or_go_back")}
|
||||||
</span>
|
</span>
|
||||||
) : isCalcom ? (
|
) : isCalcom ? (
|
||||||
<Link href={url}>
|
<a target="_blank" href={url} className="mt-2 inline-block text-lg" rel="noreferrer">
|
||||||
<a className="mt-2 inline-block text-lg">
|
{t("the_username")} <strong className="text-blue-500">cal.com{username}</strong>{" "}
|
||||||
{t("the_username")} <strong className="text-blue-500">cal.com{username}</strong>{" "}
|
{t("is_still_available")} <span className="text-blue-500">{t("register_now")}</span>.
|
||||||
{t("is_still_available")} <span className="text-blue-500">{t("register_now")}</span>.
|
</a>
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
) : (
|
) : (
|
||||||
<span className="mt-2 inline-block text-lg">
|
<span className="mt-2 inline-block text-lg">
|
||||||
{t("the_username")}{" "}
|
{t("the_username")}{" "}
|
||||||
@@ -211,31 +209,31 @@ export default function Custom404() {
|
|||||||
{!isSubpage && isCalcom && (
|
{!isSubpage && isCalcom && (
|
||||||
<ul role="list" className="mt-4">
|
<ul role="list" className="mt-4">
|
||||||
<li className="border-2 border-green-500 px-4 py-2">
|
<li className="border-2 border-green-500 px-4 py-2">
|
||||||
<Link href={url}>
|
<a
|
||||||
<a className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse">
|
href={url}
|
||||||
<div className="flex-shrink-0">
|
target="_blank"
|
||||||
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
|
className="relative flex items-start space-x-4 py-6 rtl:space-x-reverse"
|
||||||
<Icon.FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" />
|
rel="noreferrer">
|
||||||
</span>
|
<div className="flex-shrink-0">
|
||||||
</div>
|
<span className="flex h-12 w-12 items-center justify-center rounded-lg bg-green-50">
|
||||||
<div className="min-w-0 flex-1">
|
<Icon.FiCheck className="h-6 w-6 text-green-500" aria-hidden="true" />
|
||||||
<h3 className="text-base font-medium text-gray-900">
|
</span>
|
||||||
<span className="rounded-sm focus-within:ring-2 focus-within:ring-gray-500 focus-within:ring-offset-2">
|
</div>
|
||||||
<span className="focus:outline-none">
|
<div className="min-w-0 flex-1">
|
||||||
<span className="absolute inset-0" aria-hidden="true" />
|
<h3 className="text-base font-medium text-gray-900">
|
||||||
{t("register")} <strong className="text-green-500">{username}</strong>
|
<span className="rounded-sm focus-within:ring-2 focus-within:ring-gray-500 focus-within:ring-offset-2">
|
||||||
</span>
|
<span className="focus:outline-none">
|
||||||
|
<span className="absolute inset-0" aria-hidden="true" />
|
||||||
|
{t("register")} <strong className="text-green-500">{username}</strong>
|
||||||
</span>
|
</span>
|
||||||
</h3>
|
</span>
|
||||||
<p className="text-base text-gray-500">
|
</h3>
|
||||||
{t("claim_username_and_schedule_events")}
|
<p className="text-base text-gray-500">{t("claim_username_and_schedule_events")}</p>
|
||||||
</p>
|
</div>
|
||||||
</div>
|
<div className="flex-shrink-0 self-center">
|
||||||
<div className="flex-shrink-0 self-center">
|
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
||||||
<Icon.FiChevronRight className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
</div>
|
||||||
</div>
|
</a>
|
||||||
</a>
|
|
||||||
</Link>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -182,7 +182,6 @@ export default function User(props: inferSSRProps<typeof getServerSideProps>) {
|
|||||||
<h2 className="dark:text-darkgray-700 pr-2 text-sm font-semibold text-gray-700">
|
<h2 className="dark:text-darkgray-700 pr-2 text-sm font-semibold text-gray-700">
|
||||||
{type.title}
|
{type.title}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="dark:text-darkgray-600 hidden text-sm font-normal leading-none text-gray-600 md:block">{`/${user.username}/${type.slug}`}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<EventTypeDescription eventType={type} />
|
<EventTypeDescription eventType={type} />
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
});
|
});
|
||||||
|
|
||||||
// get user's credentials + their connected integrations
|
// get user's credentials + their connected integrations
|
||||||
const calendarCredentials = getCalendarCredentials(user.credentials, user.id);
|
const calendarCredentials = getCalendarCredentials(user.credentials);
|
||||||
// get all the connected integrations' calendars (from third party)
|
// get all the connected integrations' calendars (from third party)
|
||||||
const connectedCalendars = await getConnectedCalendars(calendarCredentials, user.selectedCalendars);
|
const connectedCalendars = await getConnectedCalendars(calendarCredentials, user.selectedCalendars);
|
||||||
const calendars = connectedCalendars.flatMap((c) => c.calendars).filter(notEmpty);
|
const calendars = connectedCalendars.flatMap((c) => c.calendars).filter(notEmpty);
|
||||||
|
|||||||
@@ -327,20 +327,20 @@ async function handler(req: NextApiRequest) {
|
|||||||
|
|
||||||
if (!users) throw new HttpError({ statusCode: 404, message: "eventTypeUser.notFound" });
|
if (!users) throw new HttpError({ statusCode: 404, message: "eventTypeUser.notFound" });
|
||||||
|
|
||||||
const availableUsers = await ensureAvailableUsers(
|
|
||||||
{
|
|
||||||
...eventType,
|
|
||||||
users,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
dateFrom: reqBody.start,
|
|
||||||
dateTo: reqBody.end,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add an if conditional if there are no seats on the event type
|
|
||||||
// Assign to only one user when ROUND_ROBIN
|
|
||||||
if (!eventType.seatsPerTimeSlot) {
|
if (!eventType.seatsPerTimeSlot) {
|
||||||
|
const availableUsers = await ensureAvailableUsers(
|
||||||
|
{
|
||||||
|
...eventType,
|
||||||
|
users,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dateFrom: reqBody.start,
|
||||||
|
dateTo: reqBody.end,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add an if conditional if there are no seats on the event type
|
||||||
|
// Assign to only one user when ROUND_ROBIN
|
||||||
if (eventType.schedulingType === SchedulingType.ROUND_ROBIN) {
|
if (eventType.schedulingType === SchedulingType.ROUND_ROBIN) {
|
||||||
users = [await getLuckyUser("MAXIMIZE_AVAILABILITY", { availableUsers, eventTypeId: eventType.id })];
|
users = [await getLuckyUser("MAXIMIZE_AVAILABILITY", { availableUsers, eventTypeId: eventType.id })];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { GetServerSidePropsContext } from "next";
|
import { GetServerSidePropsContext } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import RoutingFormsRoutingConfig from "@calcom/app-store/ee/routing_forms/pages/app-routing.config";
|
import RoutingFormsRoutingConfig from "@calcom/app-store/ee/routing-forms/pages/app-routing.config";
|
||||||
import TypeformRoutingConfig from "@calcom/app-store/typeform/pages/app-routing.config";
|
import TypeformRoutingConfig from "@calcom/app-store/typeform/pages/app-routing.config";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { AppGetServerSideProps } from "@calcom/types/AppGetServerSideProps";
|
import { AppGetServerSideProps } from "@calcom/types/AppGetServerSideProps";
|
||||||
@@ -28,7 +28,7 @@ type NotFound = {
|
|||||||
|
|
||||||
// TODO: It is a candidate for apps.*.generated.*
|
// TODO: It is a candidate for apps.*.generated.*
|
||||||
const AppsRouting = {
|
const AppsRouting = {
|
||||||
routing_forms: RoutingFormsRoutingConfig,
|
"routing-forms": RoutingFormsRoutingConfig,
|
||||||
typeform: TypeformRoutingConfig,
|
typeform: TypeformRoutingConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import { GetServerSidePropsContext } from "next";
|
import { GetServerSidePropsContext } from "next";
|
||||||
import { signOut, useSession } from "next-auth/react";
|
import { signOut, useSession } from "next-auth/react";
|
||||||
import Link from "next/link";
|
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { WEBSITE_URL } from "@calcom/lib/constants";
|
import { WEBSITE_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import Button from "@calcom/ui/Button";
|
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
|
|
||||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
|
|
||||||
import AuthContainer from "@components/ui/AuthContainer";
|
import AuthContainer from "@components/v2/ui/AuthContainer";
|
||||||
|
|
||||||
import { ssrInit } from "@server/lib/ssr";
|
import { ssrInit } from "@server/lib/ssr";
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ export default function Logout(props: Props) {
|
|||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthContainer title={t("logged_out")} description={t("youve_been_logged_out")}>
|
<AuthContainer title={t("logged_out")} description={t("youve_been_logged_out")} showLogo>
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
|
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100">
|
||||||
<Icon.FiCheck className="h-6 w-6 text-green-600" />
|
<Icon.FiCheck className="h-6 w-6 text-green-600" />
|
||||||
@@ -44,9 +43,9 @@ export default function Logout(props: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Link href="/auth/login" passHref>
|
<Button href="/auth/login" passHref className="flex w-full justify-center">
|
||||||
<Button className="flex w-full justify-center"> {t("go_back_login")}</Button>
|
{t("go_back_login")}
|
||||||
</Link>
|
</Button>
|
||||||
</AuthContainer>
|
</AuthContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { CheckIcon } from "@heroicons/react/solid";
|
import { CheckIcon } from "@heroicons/react/solid";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import classNames from "classnames";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||||
@@ -9,7 +10,7 @@ import { isPasswordValid } from "@calcom/lib/auth";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { inferSSRProps } from "@calcom/types/inferSSRProps";
|
import { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||||
import { TextField, EmailField, PasswordField } from "@calcom/ui/v2";
|
import { TextField, EmailField, PasswordField, Label } from "@calcom/ui/v2";
|
||||||
import WizardForm from "@calcom/ui/v2/core/WizardForm";
|
import WizardForm from "@calcom/ui/v2/core/WizardForm";
|
||||||
|
|
||||||
const StepDone = () => {
|
const StepDone = () => {
|
||||||
@@ -85,6 +86,8 @@ const SetupFormStep1 = (props: { setIsLoading: (val: boolean) => void }) => {
|
|||||||
}
|
}
|
||||||
}, onError);
|
}, onError);
|
||||||
|
|
||||||
|
const longWebsiteUrl = process.env.NEXT_PUBLIC_WEBSITE_URL.length > 30;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormProvider {...formMethods}>
|
<FormProvider {...formMethods}>
|
||||||
<form id="setup-step-1" name="setup-step-1" className="space-y-4" onSubmit={onSubmit}>
|
<form id="setup-step-1" name="setup-step-1" className="space-y-4" onSubmit={onSubmit}>
|
||||||
@@ -93,22 +96,36 @@ const SetupFormStep1 = (props: { setIsLoading: (val: boolean) => void }) => {
|
|||||||
name="username"
|
name="username"
|
||||||
control={formMethods.control}
|
control={formMethods.control}
|
||||||
render={({ field: { onBlur, onChange, value } }) => (
|
render={({ field: { onBlur, onChange, value } }) => (
|
||||||
<TextField
|
<>
|
||||||
addOnLeading={
|
<Label htmlFor="username" className={classNames(longWebsiteUrl && "mb-0")}>
|
||||||
<span className="items-centerpx-3 inline-flex rounded-none text-sm text-gray-500">
|
<span className="block">{t("username")}</span>
|
||||||
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
|
{longWebsiteUrl && (
|
||||||
</span>
|
<small className="items-centerpx-3 mt-2 inline-flex rounded-t-md border border-b-0 border-gray-300 bg-gray-100 py-1 px-3 text-gray-500">
|
||||||
}
|
{process.env.NEXT_PUBLIC_WEBSITE_URL}
|
||||||
value={value || ""}
|
</small>
|
||||||
className="my-0"
|
)}
|
||||||
onBlur={onBlur}
|
</Label>
|
||||||
name="username"
|
<TextField
|
||||||
onChange={async (e) => {
|
addOnLeading={
|
||||||
onChange(e.target.value);
|
!longWebsiteUrl && (
|
||||||
formMethods.setValue("username", e.target.value);
|
<span className="items-centerpx-3 inline-flex rounded-none text-sm text-gray-500">
|
||||||
await formMethods.trigger("username");
|
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
|
||||||
}}
|
</span>
|
||||||
/>
|
)
|
||||||
|
}
|
||||||
|
id="username"
|
||||||
|
labelSrOnly={true}
|
||||||
|
value={value || ""}
|
||||||
|
className={classNames("my-0", longWebsiteUrl && "rounded-t-none")}
|
||||||
|
onBlur={onBlur}
|
||||||
|
name="username"
|
||||||
|
onChange={async (e) => {
|
||||||
|
onChange(e.target.value);
|
||||||
|
formMethods.setValue("username", e.target.value);
|
||||||
|
await formMethods.trigger("username");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* @deprecated modifications to this file should be v2 only
|
* @deprecated modifications to this file should be v2 only
|
||||||
* Use `/apps/web/pages/v2/availability/[schedule].tsx` instead
|
* Use `/apps/web/pages/v2/availability/[schedule].tsx` instead
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-nocheck
|
||||||
import { GetStaticPaths, GetStaticProps } from "next";
|
import { GetStaticPaths, GetStaticProps } from "next";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availab
|
|||||||
key={schedule.id}
|
key={schedule.id}
|
||||||
schedule={schedule}
|
schedule={schedule}
|
||||||
deleteFunction={deleteMutation.mutate}
|
deleteFunction={deleteMutation.mutate}
|
||||||
isDeleting={deleteMutation.isLoading}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const descriptionByStatus: Record<BookingListingStatus, string> = {
|
|||||||
recurring: "recurring_bookings",
|
recurring: "recurring_bookings",
|
||||||
past: "past_bookings",
|
past: "past_bookings",
|
||||||
cancelled: "cancelled_bookings",
|
cancelled: "cancelled_bookings",
|
||||||
|
unconfirmed: "unconfirmed_bookings",
|
||||||
};
|
};
|
||||||
|
|
||||||
const querySchema = z.object({
|
const querySchema = z.object({
|
||||||
@@ -53,17 +54,6 @@ export default function Bookings() {
|
|||||||
|
|
||||||
const isEmpty = !query.data?.pages[0]?.bookings.length;
|
const isEmpty = !query.data?.pages[0]?.bookings.length;
|
||||||
|
|
||||||
// Get all recurring events of the series with the same recurringEventId
|
|
||||||
const defineRecurrentBookings = (
|
|
||||||
booking: BookingOutput,
|
|
||||||
groupedBookings: Record<string, BookingOutput[]>
|
|
||||||
) => {
|
|
||||||
let recurringBookings = undefined;
|
|
||||||
if (booking.recurringEventId !== null) {
|
|
||||||
recurringBookings = groupedBookings[booking.recurringEventId];
|
|
||||||
}
|
|
||||||
return { recurringBookings };
|
|
||||||
};
|
|
||||||
const shownBookings: Record<string, BookingOutput[]> = {};
|
const shownBookings: Record<string, BookingOutput[]> = {};
|
||||||
const filterBookings = (booking: BookingOutput) => {
|
const filterBookings = (booking: BookingOutput) => {
|
||||||
if (status === "recurring" || status === "cancelled") {
|
if (status === "recurring" || status === "cancelled") {
|
||||||
@@ -91,7 +81,7 @@ export default function Bookings() {
|
|||||||
{query.status === "error" && (
|
{query.status === "error" && (
|
||||||
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
||||||
)}
|
)}
|
||||||
{(query.status === "loading" || query.status === "idle") && <SkeletonLoader />}
|
{(query.status === "loading" || query.isPaused) && <SkeletonLoader />}
|
||||||
{query.status === "success" && !isEmpty && (
|
{query.status === "success" && !isEmpty && (
|
||||||
<>
|
<>
|
||||||
<div className="mt-6 overflow-hidden rounded-sm border border-b border-gray-200">
|
<div className="mt-6 overflow-hidden rounded-sm border border-b border-gray-200">
|
||||||
@@ -103,7 +93,7 @@ export default function Bookings() {
|
|||||||
<BookingListItem
|
<BookingListItem
|
||||||
key={booking.id}
|
key={booking.id}
|
||||||
listingStatus={status}
|
listingStatus={status}
|
||||||
{...defineRecurrentBookings(booking, shownBookings)}
|
recurringBookings={page.recurringInfo}
|
||||||
{...booking}
|
{...booking}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* @deprecated modifications to this file should be v2 only
|
||||||
|
* Use `apps/web/pages/v2/event-types/[type].tsx` instead
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-nocheck
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { EventTypeCustomInput, MembershipRole, PeriodType, Prisma, SchedulingType } from "@prisma/client";
|
import { EventTypeCustomInput, MembershipRole, PeriodType, Prisma, SchedulingType } from "@prisma/client";
|
||||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@radix-ui/react-collapsible";
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@radix-ui/react-collapsible";
|
||||||
@@ -16,15 +22,16 @@ import { v5 as uuidv5 } from "uuid";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SelectGifInput } from "@calcom/app-store/giphy/components";
|
import { SelectGifInput } from "@calcom/app-store/giphy/components";
|
||||||
import { getEventLocationType, EventLocationType } from "@calcom/app-store/locations";
|
import { EventLocationType, getEventLocationType } from "@calcom/app-store/locations";
|
||||||
import { StripeData } from "@calcom/app-store/stripepayment/lib/server";
|
import { StripeData } from "@calcom/app-store/stripepayment/lib/server";
|
||||||
import getApps, { getLocationOptions } from "@calcom/app-store/utils";
|
import getApps, { getLocationOptions } from "@calcom/app-store/utils";
|
||||||
import { LocationObject, LocationType } from "@calcom/core/location";
|
import { LocationObject } from "@calcom/core/location";
|
||||||
import { parseRecurringEvent } from "@calcom/lib";
|
import { parseRecurringEvent } from "@calcom/lib";
|
||||||
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
|
import { TRPCClientError } from "@calcom/trpc/client";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import type { RecurringEvent } from "@calcom/types/Calendar";
|
import type { RecurringEvent } from "@calcom/types/Calendar";
|
||||||
import { Alert } from "@calcom/ui/Alert";
|
import { Alert } from "@calcom/ui/Alert";
|
||||||
@@ -64,7 +71,6 @@ import * as RadioArea from "@components/ui/form/radio-area";
|
|||||||
import WebhookListContainer from "@components/webhook/WebhookListContainer";
|
import WebhookListContainer from "@components/webhook/WebhookListContainer";
|
||||||
|
|
||||||
import { getTranslation } from "@server/lib/i18n";
|
import { getTranslation } from "@server/lib/i18n";
|
||||||
import { TRPCClientError } from "@trpc/client";
|
|
||||||
|
|
||||||
const RainbowInstallForm = dynamic(() => import("@calcom/rainbow/components/RainbowInstallForm"), {
|
const RainbowInstallForm = dynamic(() => import("@calcom/rainbow/components/RainbowInstallForm"), {
|
||||||
suspense: true,
|
suspense: true,
|
||||||
@@ -108,6 +114,7 @@ export type FormValues = {
|
|||||||
periodCountCalendarDays: "1" | "0";
|
periodCountCalendarDays: "1" | "0";
|
||||||
periodDates: { startDate: Date; endDate: Date };
|
periodDates: { startDate: Date; endDate: Date };
|
||||||
seatsPerTimeSlot: number | null;
|
seatsPerTimeSlot: number | null;
|
||||||
|
seatsPerTimeSlotEnabled: boolean;
|
||||||
minimumBookingNotice: number;
|
minimumBookingNotice: number;
|
||||||
beforeBufferTime: number;
|
beforeBufferTime: number;
|
||||||
afterBufferTime: number;
|
afterBufferTime: number;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
|
import { TRPCClientError } from "@calcom/trpc/react";
|
||||||
import { Button } from "@calcom/ui";
|
import { Button } from "@calcom/ui";
|
||||||
import { Alert } from "@calcom/ui/Alert";
|
import { Alert } from "@calcom/ui/Alert";
|
||||||
import Badge from "@calcom/ui/Badge";
|
import Badge from "@calcom/ui/Badge";
|
||||||
@@ -23,6 +24,7 @@ import Dropdown, {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
|
DropdownMenuPortal,
|
||||||
} from "@calcom/ui/Dropdown";
|
} from "@calcom/ui/Dropdown";
|
||||||
import EmptyScreen from "@calcom/ui/EmptyScreen";
|
import EmptyScreen from "@calcom/ui/EmptyScreen";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
@@ -42,8 +44,6 @@ import { LinkText } from "@components/ui/LinkText";
|
|||||||
import NoCalendarConnectedAlert from "@components/ui/NoCalendarConnectedAlert";
|
import NoCalendarConnectedAlert from "@components/ui/NoCalendarConnectedAlert";
|
||||||
import SkeletonLoader from "@components/v2/eventtype/SkeletonLoader";
|
import SkeletonLoader from "@components/v2/eventtype/SkeletonLoader";
|
||||||
|
|
||||||
import { TRPCClientError } from "@trpc/react";
|
|
||||||
|
|
||||||
type EventTypeGroups = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"];
|
type EventTypeGroups = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"];
|
||||||
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
|
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
|
||||||
interface EventTypeListHeadingProps {
|
interface EventTypeListHeadingProps {
|
||||||
@@ -346,36 +346,70 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
|
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
|
||||||
<Button type="button" size="icon" color="minimal" StartIcon={Icon.FiMoreHorizontal} />
|
<Button type="button" size="icon" color="minimal" StartIcon={Icon.FiMoreHorizontal} />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent portalled>
|
<DropdownMenuPortal>
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuContent>
|
||||||
<Link href={calLink}>
|
<DropdownMenuItem className="outline-none">
|
||||||
|
<Link href={calLink}>
|
||||||
|
<Button
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
color="minimal"
|
||||||
|
size="sm"
|
||||||
|
StartIcon={Icon.FiExternalLink}
|
||||||
|
className="w-full rounded-none">
|
||||||
|
{t("preview") as string}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
rel="noreferrer"
|
type="button"
|
||||||
target="_blank"
|
|
||||||
color="minimal"
|
color="minimal"
|
||||||
size="sm"
|
size="sm"
|
||||||
StartIcon={Icon.FiExternalLink}
|
className="w-full rounded-none text-left"
|
||||||
className="w-full rounded-none">
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
{t("preview") as string}
|
StartIcon={Icon.FiClipboard}
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(calLink);
|
||||||
|
showToast(t("link_copied"), "success");
|
||||||
|
}}>
|
||||||
|
{t("copy_link") as string}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</DropdownMenuItem>
|
||||||
</DropdownMenuItem>
|
{isNativeShare ? (
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="minimal"
|
color="minimal"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="w-full rounded-none text-left"
|
className="w-full rounded-none"
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
StartIcon={Icon.FiClipboard}
|
StartIcon={Icon.FiUpload}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigator.clipboard.writeText(calLink);
|
navigator
|
||||||
showToast(t("link_copied"), "success");
|
.share({
|
||||||
}}>
|
title: t("share"),
|
||||||
{t("copy_link") as string}
|
text: t("share_event"),
|
||||||
</Button>
|
url: calLink,
|
||||||
</DropdownMenuItem>
|
})
|
||||||
{isNativeShare ? (
|
.then(() => showToast(t("link_shared"), "success"))
|
||||||
|
.catch(() => showToast(t("failed"), "error"));
|
||||||
|
}}>
|
||||||
|
{t("share") as string}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
) : null}
|
||||||
|
<DropdownMenuItem className="outline-none">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
size="sm"
|
||||||
|
href={"/event-types/" + type.id}
|
||||||
|
color="minimal"
|
||||||
|
className="w-full rounded-none"
|
||||||
|
StartIcon={Icon.FiEdit2}>
|
||||||
|
{t("edit") as string}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -383,59 +417,27 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
size="sm"
|
size="sm"
|
||||||
className="w-full rounded-none"
|
className="w-full rounded-none"
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
StartIcon={Icon.FiUpload}
|
StartIcon={Icon.FiCopy}
|
||||||
onClick={() => {
|
onClick={() => openModal(group, type)}>
|
||||||
navigator
|
{t("duplicate") as string}
|
||||||
.share({
|
|
||||||
title: t("share"),
|
|
||||||
text: t("share_event"),
|
|
||||||
url: calLink,
|
|
||||||
})
|
|
||||||
.then(() => showToast(t("link_shared"), "success"))
|
|
||||||
.catch(() => showToast(t("failed"), "error"));
|
|
||||||
}}>
|
|
||||||
{t("share") as string}
|
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
) : null}
|
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
onClick={() => {
|
||||||
size="sm"
|
setDeleteDialogOpen(true);
|
||||||
href={"/event-types/" + type.id}
|
setDeleteDialogTypeId(type.id);
|
||||||
color="minimal"
|
}}
|
||||||
className="w-full rounded-none"
|
color="warn"
|
||||||
StartIcon={Icon.FiEdit2}>
|
size="sm"
|
||||||
{t("edit") as string}
|
StartIcon={Icon.FiTrash}
|
||||||
</Button>
|
className="w-full rounded-none">
|
||||||
</DropdownMenuItem>
|
{t("delete") as string}
|
||||||
<DropdownMenuItem className="outline-none">
|
</Button>
|
||||||
<Button
|
</DropdownMenuItem>
|
||||||
type="button"
|
</DropdownMenuContent>
|
||||||
color="minimal"
|
</DropdownMenuPortal>
|
||||||
size="sm"
|
|
||||||
className="w-full rounded-none"
|
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
|
||||||
StartIcon={Icon.FiCopy}
|
|
||||||
onClick={() => openModal(group, type)}>
|
|
||||||
{t("duplicate") as string}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
|
||||||
<DropdownMenuItem className="outline-none">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setDeleteDialogOpen(true);
|
|
||||||
setDeleteDialogTypeId(type.id);
|
|
||||||
}}
|
|
||||||
color="warn"
|
|
||||||
size="sm"
|
|
||||||
StartIcon={Icon.FiTrash}
|
|
||||||
className="w-full rounded-none">
|
|
||||||
{t("delete") as string}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -540,6 +542,7 @@ const EventTypesPage = () => {
|
|||||||
<title>Home | Cal.com</title>
|
<title>Home | Cal.com</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<Shell
|
<Shell
|
||||||
heading={t("event_types_page_title") as string}
|
heading={t("event_types_page_title") as string}
|
||||||
subtitle={t("event_types_page_subtitle") as string}
|
subtitle={t("event_types_page_subtitle") as string}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ const OnboardingPage = (props: IOnboardingPageProps) => {
|
|||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<div className="mx-auto px-4 py-24">
|
<div className="mx-auto px-4 py-6 md:py-24">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
||||||
<div className="mx-auto sm:max-w-[520px]">
|
<div className="mx-auto sm:max-w-[520px]">
|
||||||
@@ -129,7 +129,7 @@ const OnboardingPage = (props: IOnboardingPageProps) => {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
goToIndex(currentStepIndex + 1);
|
goToIndex(currentStepIndex + 1);
|
||||||
}}
|
}}
|
||||||
className="mt-24 cursor-pointer px-4 py-2 font-sans text-sm font-medium">
|
className="mt-8 cursor-pointer px-4 py-2 font-sans text-sm font-medium">
|
||||||
{headers[currentStepIndex]?.skipText}
|
{headers[currentStepIndex]?.skipText}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
|
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
import type { AppRouter } from "@calcom/trpc/server/routers/_app";
|
||||||
import { Alert } from "@calcom/ui/Alert";
|
import { Alert } from "@calcom/ui/Alert";
|
||||||
@@ -39,8 +40,6 @@ import Schedule from "@components/availability/Schedule";
|
|||||||
import { CalendarListContainer } from "@components/integrations/CalendarListContainer";
|
import { CalendarListContainer } from "@components/integrations/CalendarListContainer";
|
||||||
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
|
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
|
||||||
|
|
||||||
import { TRPCClientErrorLike } from "@trpc/client";
|
|
||||||
|
|
||||||
// Embed isn't applicable to onboarding, so ignore the rule
|
// Embed isn't applicable to onboarding, so ignore the rule
|
||||||
/* eslint-disable @calcom/eslint/avoid-web-storage */
|
/* eslint-disable @calcom/eslint/avoid-web-storage */
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useQuery } from "react-query";
|
|
||||||
|
|
||||||
import { HttpError } from "@lib/core/http/error";
|
import { HttpError } from "@lib/core/http/error";
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default function Settings() {
|
|||||||
const { data: routingForms } = trpc.useQuery([
|
const { data: routingForms } = trpc.useQuery([
|
||||||
"viewer.appById",
|
"viewer.appById",
|
||||||
{
|
{
|
||||||
appId: "routing_forms",
|
appId: "routing-forms",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ export default function Settings() {
|
|||||||
<WebhookListContainer title="Event Webhooks" subtitle={t("receive_cal_meeting_data")} />
|
<WebhookListContainer title="Event Webhooks" subtitle={t("receive_cal_meeting_data")} />
|
||||||
{routingForms && (
|
{routingForms && (
|
||||||
<WebhookListContainer
|
<WebhookListContainer
|
||||||
appId="routing_forms"
|
appId="routing-forms"
|
||||||
title="Routing Webhooks"
|
title="Routing Webhooks"
|
||||||
subtitle="Receive Routing Form responses at a specified URL, in real-time, when a Routing Form is submitted"
|
subtitle="Receive Routing Form responses at a specified URL, in real-time, when a Routing Form is submitted"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import TimezoneSelect, { ITimezone } from "react-timezone-select";
|
|||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import showToast from "@calcom/lib/notification";
|
import showToast from "@calcom/lib/notification";
|
||||||
|
import { setIs24hClockInLocalStorage } from "@calcom/lib/timeFormat";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
import { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
@@ -229,7 +230,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
|
|||||||
// Write time format to localStorage if available
|
// Write time format to localStorage if available
|
||||||
// Embed isn't applicable to profile pages. So ignore the rule
|
// Embed isn't applicable to profile pages. So ignore the rule
|
||||||
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
||||||
window.localStorage.setItem("timeOption.is24hClock", selectedTimeFormat.value === 12 ? "false" : "true");
|
setIs24hClockInLocalStorage(selectedTimeFormat.value === 24);
|
||||||
|
|
||||||
// TODO: Add validation
|
// TODO: Add validation
|
||||||
|
|
||||||
@@ -575,7 +576,7 @@ function SettingsView(props: ComponentProps<typeof Settings> & { localeProp: str
|
|||||||
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
* i18n should never be clubbed with other queries, so that it's caching can be managed independently.
|
||||||
* We intend to not cache i18n query
|
* We intend to not cache i18n query
|
||||||
**/
|
**/
|
||||||
const WithQuery = withQuery(["viewer.public.i18n"], { context: { skipBatch: true } });
|
const WithQuery = withQuery(["viewer.public.i18n"], { trpc: { context: { skipBatch: true } } });
|
||||||
|
|
||||||
export default function Settings(props: Props) {
|
export default function Settings(props: Props) {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||||
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
|
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||||
import { isBrowserLocale24h } from "@calcom/lib/timeFormat";
|
import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat";
|
||||||
import { localStorage } from "@calcom/lib/webstorage";
|
import { localStorage } from "@calcom/lib/webstorage";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import Button from "@calcom/ui/Button";
|
import Button from "@calcom/ui/Button";
|
||||||
@@ -203,7 +203,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
// TODO: Add payment details
|
// TODO: Add payment details
|
||||||
});
|
});
|
||||||
setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()));
|
setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()));
|
||||||
setIs24h(!!localStorage.getItem("timeOption.is24hClock"));
|
setIs24h(!!getIs24hClockFromLocalStorage());
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [eventType, needsConfirmation]);
|
}, [eventType, needsConfirmation]);
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import React, { useEffect } from "react";
|
|||||||
import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
|
import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
|
||||||
import { CAL_URL } from "@calcom/lib/constants";
|
import { CAL_URL } from "@calcom/lib/constants";
|
||||||
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
||||||
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||||
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
|
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||||
@@ -17,7 +18,6 @@ import { Button } from "@calcom/ui/v2/core";
|
|||||||
import EventTypeDescription from "@calcom/ui/v2/modules/event-types/EventTypeDescription";
|
import EventTypeDescription from "@calcom/ui/v2/modules/event-types/EventTypeDescription";
|
||||||
|
|
||||||
import { useExposePlanGlobally } from "@lib/hooks/useExposePlanGlobally";
|
import { useExposePlanGlobally } from "@lib/hooks/useExposePlanGlobally";
|
||||||
import { useLocale } from "@lib/hooks/useLocale";
|
|
||||||
import { useToggleQuery } from "@lib/hooks/useToggleQuery";
|
import { useToggleQuery } from "@lib/hooks/useToggleQuery";
|
||||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
|
|
||||||
@@ -56,7 +56,6 @@ function TeamPage({ team }: TeamPageProps) {
|
|||||||
<div className="flex-shrink">
|
<div className="flex-shrink">
|
||||||
<div className="flex flex-wrap items-center space-x-2">
|
<div className="flex flex-wrap items-center space-x-2">
|
||||||
<h2 className="dark:text-darkgray-700 text-sm font-semibold text-gray-700">{type.title}</h2>
|
<h2 className="dark:text-darkgray-700 text-sm font-semibold text-gray-700">{type.title}</h2>
|
||||||
<p className="dark:text-darkgray-600 hidden text-sm font-normal leading-none text-gray-600 md:block">{`/${team.slug}/${type.slug}`}</p>
|
|
||||||
</div>
|
</div>
|
||||||
<EventTypeDescription className="text-sm" eventType={type} />
|
<EventTypeDescription className="text-sm" eventType={type} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,21 +18,25 @@ export default function Apps({ apps }: InferGetStaticPropsType<typeof getStaticP
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Shell isPublic large>
|
<Shell
|
||||||
<div className="text-md flex items-center gap-1 px-4 pb-3 pt-3 font-semibold md:px-8 lg:px-0 lg:pt-0">
|
isPublic
|
||||||
<Link href="/apps">
|
backPath="/apps"
|
||||||
<a className="inline-flex items-center justify-start gap-1 rounded-sm py-2 text-gray-900">
|
heading={
|
||||||
<Icon.FiArrowLeft className="h-4 w-4" />
|
<>
|
||||||
{isLocaleReady ? t("app_store") : <SkeletonText className="h-4 w-24" />}{" "}
|
<Link href="/apps">
|
||||||
</a>
|
<a className="inline-flex items-center justify-start gap-1 rounded-sm py-2 text-gray-900">
|
||||||
</Link>
|
{isLocaleReady ? t("app_store") : <SkeletonText className="h-4 w-24" />}{" "}
|
||||||
{category && (
|
</a>
|
||||||
<span className="flex gap-1 text-gray-600">
|
</Link>
|
||||||
<span> / </span>
|
{category && (
|
||||||
{t("category_apps", { category: category[0].toUpperCase() + category?.slice(1) })}
|
<span className="gap-1 text-gray-600">
|
||||||
</span>
|
<span> / </span>
|
||||||
)}
|
{t("category_apps", { category: category[0].toUpperCase() + category?.slice(1) })}
|
||||||
</div>
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
large>
|
||||||
<div className="mb-16">
|
<div className="mb-16">
|
||||||
<div className="grid-col-1 grid grid-cols-1 gap-3 md:grid-cols-3">
|
<div className="grid-col-1 grid grid-cols-1 gap-3 md:grid-cols-3">
|
||||||
{apps.map((app) => {
|
{apps.map((app) => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useRouter } from "next/router";
|
import { InferGetServerSidePropsType } from "next";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
|
|
||||||
import { InstallAppButton } from "@calcom/app-store/components";
|
import { InstallAppButton } from "@calcom/app-store/components";
|
||||||
@@ -6,6 +6,7 @@ import { InstalledAppVariants } from "@calcom/app-store/utils";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
import { App } from "@calcom/types/App";
|
import { App } from "@calcom/types/App";
|
||||||
|
import { AppGetServerSidePropsContext } from "@calcom/types/AppGetServerSideProps";
|
||||||
import { Icon } from "@calcom/ui/Icon";
|
import { Icon } from "@calcom/ui/Icon";
|
||||||
import SkeletonLoader from "@calcom/ui/apps/SkeletonLoader";
|
import SkeletonLoader from "@calcom/ui/apps/SkeletonLoader";
|
||||||
import { Alert } from "@calcom/ui/v2/core/Alert";
|
import { Alert } from "@calcom/ui/v2/core/Alert";
|
||||||
@@ -90,7 +91,7 @@ interface IntegrationsContainerProps {
|
|||||||
|
|
||||||
const IntegrationsList = ({ data }: { data: inferQueryOutput<"viewer.integrations"> }) => {
|
const IntegrationsList = ({ data }: { data: inferQueryOutput<"viewer.integrations"> }) => {
|
||||||
return (
|
return (
|
||||||
<List>
|
<List noBorderTreatment>
|
||||||
{data.items.map((item) => (
|
{data.items.map((item) => (
|
||||||
<IntegrationListItem
|
<IntegrationListItem
|
||||||
name={item.name}
|
name={item.name}
|
||||||
@@ -177,12 +178,8 @@ const querySchema = z.object({
|
|||||||
category: z.nativeEnum(InstalledAppVariants),
|
category: z.nativeEnum(InstalledAppVariants),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default function InstalledApps() {
|
export default function InstalledApps({ category }: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const router = useRouter();
|
|
||||||
const { category } = router.isReady
|
|
||||||
? querySchema.parse(router.query)
|
|
||||||
: { category: InstalledAppVariants.calendar as const };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InstalledAppsLayout heading={t("installed_apps")} subtitle={t("manage_your_connected_apps")}>
|
<InstalledAppsLayout heading={t("installed_apps")} subtitle={t("manage_your_connected_apps")}>
|
||||||
@@ -202,3 +199,30 @@ export default function InstalledApps() {
|
|||||||
</InstalledAppsLayout>
|
</InstalledAppsLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Server side rendering
|
||||||
|
export async function getServerSideProps(ctx: AppGetServerSidePropsContext) {
|
||||||
|
// get return-to cookie and redirect if needed
|
||||||
|
const { cookies } = ctx.req;
|
||||||
|
if (cookies && cookies["return-to"]) {
|
||||||
|
const returnTo = cookies["return-to"];
|
||||||
|
if (returnTo) {
|
||||||
|
ctx.res.setHeader("Set-Cookie", "return-to=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT");
|
||||||
|
return {
|
||||||
|
redirect: {
|
||||||
|
destination: `${returnTo}`,
|
||||||
|
permanent: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const params = querySchema.safeParse(ctx.params);
|
||||||
|
|
||||||
|
if (!params.success) return { notFound: true };
|
||||||
|
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
category: params.data.category,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -78,7 +78,7 @@ export default function Login({
|
|||||||
|
|
||||||
const LoginFooter = (
|
const LoginFooter = (
|
||||||
<a href={`${WEBSITE_URL}/signup`} className="text-brand-500 font-medium">
|
<a href={`${WEBSITE_URL}/signup`} className="text-brand-500 font-medium">
|
||||||
{t("i_dont_have_an_account")}
|
{t("dont_have_an_account")}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -9,20 +9,22 @@ import { availabilityAsString } from "@calcom/lib/availability";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { stringOrNumber } from "@calcom/prisma/zod-utils";
|
import { stringOrNumber } from "@calcom/prisma/zod-utils";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
|
||||||
import type { Schedule as ScheduleType } from "@calcom/types/schedule";
|
import type { Schedule as ScheduleType } from "@calcom/types/schedule";
|
||||||
import { Icon } from "@calcom/ui";
|
import { Icon } from "@calcom/ui";
|
||||||
import TimezoneSelect from "@calcom/ui/form/TimezoneSelect";
|
|
||||||
import Button from "@calcom/ui/v2/core/Button";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
import Shell from "@calcom/ui/v2/core/Shell";
|
import Shell from "@calcom/ui/v2/core/Shell";
|
||||||
import Switch from "@calcom/ui/v2/core/Switch";
|
import Switch from "@calcom/ui/v2/core/Switch";
|
||||||
|
import TimezoneSelect from "@calcom/ui/v2/core/TimezoneSelect";
|
||||||
import VerticalDivider from "@calcom/ui/v2/core/VerticalDivider";
|
import VerticalDivider from "@calcom/ui/v2/core/VerticalDivider";
|
||||||
import { Form, Label } from "@calcom/ui/v2/core/form/fields";
|
import { Form, Label } from "@calcom/ui/v2/core/form/fields";
|
||||||
import showToast from "@calcom/ui/v2/core/notifications";
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
import { SkeletonText } from "@calcom/ui/v2/core/skeleton";
|
import { Skeleton, SkeletonText } from "@calcom/ui/v2/core/skeleton";
|
||||||
|
|
||||||
import { HttpError } from "@lib/core/http/error";
|
import { HttpError } from "@lib/core/http/error";
|
||||||
|
|
||||||
import EditableHeading from "@components/ui/EditableHeading";
|
import EditableHeading from "@components/ui/EditableHeading";
|
||||||
|
import { SelectSkeletonLoader } from "@components/v2/availability/SkeletonLoader";
|
||||||
|
|
||||||
const querySchema = z.object({
|
const querySchema = z.object({
|
||||||
schedule: stringOrNumber,
|
schedule: stringOrNumber,
|
||||||
@@ -39,11 +41,12 @@ export default function Availability({ schedule }: { schedule: number }) {
|
|||||||
const { t, i18n } = useLocale();
|
const { t, i18n } = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
|
const me = useMeQuery();
|
||||||
|
|
||||||
const { data, isLoading } = trpc.useQuery(["viewer.availability.schedule", { scheduleId: schedule }]);
|
const { data, isLoading } = trpc.useQuery(["viewer.availability.schedule", { scheduleId: schedule }]);
|
||||||
|
|
||||||
const form = useForm<AvailabilityFormValues>();
|
const form = useForm<AvailabilityFormValues>();
|
||||||
const { control, reset, setValue } = form;
|
const { control, reset } = form;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoading && data) {
|
if (!isLoading && data) {
|
||||||
@@ -79,22 +82,35 @@ export default function Availability({ schedule }: { schedule: number }) {
|
|||||||
return (
|
return (
|
||||||
<Shell
|
<Shell
|
||||||
backPath="/availability"
|
backPath="/availability"
|
||||||
title={t("availability_title", { availabilityTitle: data?.schedule.name })}
|
title={data?.schedule.name && data.schedule.name + " | " + t("availability")}
|
||||||
heading={
|
heading={
|
||||||
<EditableHeading title={data?.schedule.name || ""} onChange={(name) => setValue("name", name)} />
|
<Controller
|
||||||
|
control={form.control}
|
||||||
|
name="name"
|
||||||
|
render={({ field }) => <EditableHeading isReady={!isLoading} {...field} />}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
subtitle={
|
||||||
|
data ? (
|
||||||
|
data.schedule.availability.map((availability) => (
|
||||||
|
<span key={availability.id}>
|
||||||
|
{availabilityAsString(availability, { locale: i18n.language })}
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<SkeletonText className="h-4 w-48" />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
subtitle={data?.schedule.availability.map((availability) => (
|
|
||||||
<span key={availability.id}>
|
|
||||||
{availabilityAsString(availability, { locale: i18n.language })}
|
|
||||||
<br />
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
CTA={
|
CTA={
|
||||||
<div className="flex items-center justify-end">
|
<div className="flex items-center justify-end">
|
||||||
<div className="flex items-center rounded-md px-2 sm:hover:bg-gray-100">
|
<div className="flex items-center rounded-md px-2 sm:hover:bg-gray-100">
|
||||||
<Label htmlFor="hiddenSwitch" className="mt-2 hidden cursor-pointer self-center pr-2 sm:inline">
|
<Skeleton
|
||||||
|
as={Label}
|
||||||
|
htmlFor="hiddenSwitch"
|
||||||
|
className="mt-2 hidden cursor-pointer self-center pr-2 sm:inline">
|
||||||
{t("set_to_default")}
|
{t("set_to_default")}
|
||||||
</Label>
|
</Skeleton>
|
||||||
<Switch
|
<Switch
|
||||||
id="hiddenSwitch"
|
id="hiddenSwitch"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
@@ -132,7 +148,17 @@ export default function Availability({ schedule }: { schedule: number }) {
|
|||||||
<h3 className="mb-5 text-base font-medium leading-6 text-gray-900">
|
<h3 className="mb-5 text-base font-medium leading-6 text-gray-900">
|
||||||
{t("change_start_end")}
|
{t("change_start_end")}
|
||||||
</h3>
|
</h3>
|
||||||
<Schedule control={control} name="schedule" />
|
{typeof me.data?.weekStart === "string" && (
|
||||||
|
<Schedule
|
||||||
|
control={control}
|
||||||
|
name="schedule"
|
||||||
|
weekStart={
|
||||||
|
["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"].indexOf(
|
||||||
|
me.data?.weekStart
|
||||||
|
) as 0 | 1 | 2 | 3 | 4 | 5 | 6
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="min-w-40 col-span-3 space-y-2 lg:col-span-1">
|
<div className="min-w-40 col-span-3 space-y-2 lg:col-span-1">
|
||||||
@@ -147,11 +173,11 @@ export default function Availability({ schedule }: { schedule: number }) {
|
|||||||
value ? (
|
value ? (
|
||||||
<TimezoneSelect
|
<TimezoneSelect
|
||||||
value={value}
|
value={value}
|
||||||
className="focus:border-brand mt-1 block rounded-md border-gray-300 text-sm"
|
className="focus:border-brand mt-1 block w-72 rounded-md border-gray-300 text-sm"
|
||||||
onChange={(timezone) => onChange(timezone.value)}
|
onChange={(timezone) => onChange(timezone.value)}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SkeletonText className="h-6 w-full" />
|
<SelectSkeletonLoader className="w-72" />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -21,16 +21,32 @@ export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availab
|
|||||||
const meQuery = trpc.useQuery(["viewer.me"]);
|
const meQuery = trpc.useQuery(["viewer.me"]);
|
||||||
|
|
||||||
const deleteMutation = trpc.useMutation("viewer.availability.schedule.delete", {
|
const deleteMutation = trpc.useMutation("viewer.availability.schedule.delete", {
|
||||||
onSuccess: async () => {
|
onMutate: async ({ scheduleId }) => {
|
||||||
await utils.invalidateQueries(["viewer.availability.list"]);
|
await utils.cancelQuery(["viewer.availability.list"]);
|
||||||
showToast(t("schedule_deleted_successfully"), "success");
|
const previousValue = utils.getQueryData(["viewer.availability.list"]);
|
||||||
|
if (previousValue) {
|
||||||
|
const filteredValue = previousValue.schedules.filter(({ id }) => id !== scheduleId);
|
||||||
|
utils.setQueryData(["viewer.availability.list"], { ...previousValue, schedules: filteredValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { previousValue };
|
||||||
},
|
},
|
||||||
onError: (err) => {
|
|
||||||
|
onError: (err, variables, context) => {
|
||||||
|
if (context?.previousValue) {
|
||||||
|
utils.setQueryData(["viewer.availability.list"], context.previousValue);
|
||||||
|
}
|
||||||
if (err instanceof HttpError) {
|
if (err instanceof HttpError) {
|
||||||
const message = `${err.statusCode}: ${err.message}`;
|
const message = `${err.statusCode}: ${err.message}`;
|
||||||
showToast(message, "error");
|
showToast(message, "error");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onSettled: () => {
|
||||||
|
utils.invalidateQueries(["viewer.availability.list"]);
|
||||||
|
},
|
||||||
|
onSuccess: () => {
|
||||||
|
showToast(t("schedule_deleted_successfully"), "success");
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Adds smooth delete button - item fades and old item slides into place
|
// Adds smooth delete button - item fades and old item slides into place
|
||||||
@@ -61,7 +77,6 @@ export function AvailabilityList({ schedules }: inferQueryOutput<"viewer.availab
|
|||||||
key={schedule.id}
|
key={schedule.id}
|
||||||
schedule={schedule}
|
schedule={schedule}
|
||||||
deleteFunction={deleteMutation.mutate}
|
deleteFunction={deleteMutation.mutate}
|
||||||
isDeleting={deleteMutation.isLoading}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -20,13 +20,14 @@ import SkeletonLoader from "@components/v2/bookings/SkeletonLoader";
|
|||||||
type BookingListingStatus = inferQueryInput<"viewer.bookings">["status"];
|
type BookingListingStatus = inferQueryInput<"viewer.bookings">["status"];
|
||||||
type BookingOutput = inferQueryOutput<"viewer.bookings">["bookings"][0];
|
type BookingOutput = inferQueryOutput<"viewer.bookings">["bookings"][0];
|
||||||
|
|
||||||
const validStatuses = ["upcoming", "recurring", "past", "cancelled"] as const;
|
const validStatuses = ["upcoming", "recurring", "past", "cancelled", "unconfirmed"] as const;
|
||||||
|
|
||||||
const descriptionByStatus: Record<BookingListingStatus, string> = {
|
const descriptionByStatus: Record<BookingListingStatus, string> = {
|
||||||
upcoming: "upcoming_bookings",
|
upcoming: "upcoming_bookings",
|
||||||
recurring: "recurring_bookings",
|
recurring: "recurring_bookings",
|
||||||
past: "past_bookings",
|
past: "past_bookings",
|
||||||
cancelled: "cancelled_bookings",
|
cancelled: "cancelled_bookings",
|
||||||
|
unconfirmed: "unconfirmed_bookings",
|
||||||
};
|
};
|
||||||
|
|
||||||
const querySchema = z.object({
|
const querySchema = z.object({
|
||||||
@@ -54,20 +55,9 @@ export default function Bookings() {
|
|||||||
|
|
||||||
const isEmpty = !query.data?.pages[0]?.bookings.length;
|
const isEmpty = !query.data?.pages[0]?.bookings.length;
|
||||||
|
|
||||||
// Get all recurring events of the series with the same recurringEventId
|
|
||||||
const defineRecurrentBookings = (
|
|
||||||
booking: BookingOutput,
|
|
||||||
groupedBookings: Record<string, BookingOutput[]>
|
|
||||||
) => {
|
|
||||||
let recurringBookings = undefined;
|
|
||||||
if (booking.recurringEventId !== null) {
|
|
||||||
recurringBookings = groupedBookings[booking.recurringEventId];
|
|
||||||
}
|
|
||||||
return { recurringBookings };
|
|
||||||
};
|
|
||||||
const shownBookings: Record<string, BookingOutput[]> = {};
|
const shownBookings: Record<string, BookingOutput[]> = {};
|
||||||
const filterBookings = (booking: BookingOutput) => {
|
const filterBookings = (booking: BookingOutput) => {
|
||||||
if (status === "recurring" || status === "cancelled") {
|
if (status === "recurring" || status == "unconfirmed" || status === "cancelled") {
|
||||||
if (!booking.recurringEventId) {
|
if (!booking.recurringEventId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -89,11 +79,11 @@ export default function Bookings() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<BookingLayout heading={t("bookings")} subtitle={t("bookings_description")}>
|
<BookingLayout heading={t("bookings")} subtitle={t("bookings_description")}>
|
||||||
<div className="flex w-full flex-1 flex-col" ref={animationParentRef}>
|
<div className="flex w-full flex-col" ref={animationParentRef}>
|
||||||
{query.status === "error" && (
|
{query.status === "error" && (
|
||||||
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
<Alert severity="error" title={t("something_went_wrong")} message={query.error.message} />
|
||||||
)}
|
)}
|
||||||
{(query.status === "loading" || query.status === "idle") && <SkeletonLoader />}
|
{(query.status === "loading" || query.isPaused) && <SkeletonLoader />}
|
||||||
{query.status === "success" && !isEmpty && (
|
{query.status === "success" && !isEmpty && (
|
||||||
<div className="pt-2 xl:pt-0">
|
<div className="pt-2 xl:pt-0">
|
||||||
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
<WipeMyCalActionButton bookingStatus={status} bookingsEmpty={isEmpty} />
|
||||||
@@ -102,7 +92,7 @@ export default function Bookings() {
|
|||||||
*/}
|
*/}
|
||||||
|
|
||||||
<div className="overflow-hidden rounded-md border border-gray-200">
|
<div className="overflow-hidden rounded-md border border-gray-200">
|
||||||
<table className="w-full">
|
<table className="w-full max-w-full table-fixed">
|
||||||
<tbody className="divide-y divide-gray-200 bg-white" data-testid="bookings">
|
<tbody className="divide-y divide-gray-200 bg-white" data-testid="bookings">
|
||||||
{query.data.pages.map((page, index) => (
|
{query.data.pages.map((page, index) => (
|
||||||
<Fragment key={index}>
|
<Fragment key={index}>
|
||||||
@@ -110,7 +100,7 @@ export default function Bookings() {
|
|||||||
<BookingListItem
|
<BookingListItem
|
||||||
key={booking.id}
|
key={booking.id}
|
||||||
listingStatus={status}
|
listingStatus={status}
|
||||||
{...defineRecurrentBookings(booking, shownBookings)}
|
recurringBookings={page.recurringInfo}
|
||||||
{...booking}
|
{...booking}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export type FormValues = {
|
|||||||
periodCountCalendarDays: "1" | "0";
|
periodCountCalendarDays: "1" | "0";
|
||||||
periodDates: { startDate: Date; endDate: Date };
|
periodDates: { startDate: Date; endDate: Date };
|
||||||
seatsPerTimeSlot: number | null;
|
seatsPerTimeSlot: number | null;
|
||||||
|
seatsPerTimeSlotEnabled: boolean;
|
||||||
minimumBookingNotice: number;
|
minimumBookingNotice: number;
|
||||||
beforeBufferTime: number;
|
beforeBufferTime: number;
|
||||||
afterBufferTime: number;
|
afterBufferTime: number;
|
||||||
@@ -96,7 +97,8 @@ export type EventTypeSetupInfered = inferSSRProps<typeof getServerSideProps>;
|
|||||||
const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
const { eventType, locationOptions, team, teamMembers } = props;
|
const { eventType: dbEventType, locationOptions, team, teamMembers } = props;
|
||||||
|
const [eventType, setEventType] = useState(dbEventType);
|
||||||
const animationParentRef = useRef(null);
|
const animationParentRef = useRef(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { tabName } = querySchema.parse(router.query);
|
const { tabName } = querySchema.parse(router.query);
|
||||||
@@ -106,7 +108,8 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
|||||||
}, [animationParentRef]);
|
}, [animationParentRef]);
|
||||||
|
|
||||||
const updateMutation = trpc.useMutation("viewer.eventTypes.update", {
|
const updateMutation = trpc.useMutation("viewer.eventTypes.update", {
|
||||||
onSuccess: async ({ eventType }) => {
|
onSuccess: async ({ eventType: newEventType }) => {
|
||||||
|
setEventType({ ...eventType, slug: newEventType.slug });
|
||||||
showToast(
|
showToast(
|
||||||
t("event_type_updated_successfully", {
|
t("event_type_updated_successfully", {
|
||||||
eventTypeTitle: eventType.title,
|
eventTypeTitle: eventType.title,
|
||||||
@@ -153,6 +156,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
|||||||
endDate: periodDates.endDate,
|
endDate: periodDates.endDate,
|
||||||
},
|
},
|
||||||
schedulingType: eventType.schedulingType,
|
schedulingType: eventType.schedulingType,
|
||||||
|
minimumBookingNotice: eventType.minimumBookingNotice,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -220,6 +224,9 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
|||||||
locations,
|
locations,
|
||||||
blockchainId,
|
blockchainId,
|
||||||
smartContractAddress,
|
smartContractAddress,
|
||||||
|
// We don't need to send it to the backend
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
seatsPerTimeSlotEnabled,
|
||||||
...input
|
...input
|
||||||
} = values;
|
} = values;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { UserPlan } from "@prisma/client";
|
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
@@ -7,6 +7,7 @@ import React, { Fragment, useEffect, useState } from "react";
|
|||||||
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
|
import { TRPCClientError } from "@calcom/trpc/react";
|
||||||
import { Icon } from "@calcom/ui";
|
import { Icon } from "@calcom/ui";
|
||||||
import { Badge, Button, ButtonGroup, Dialog, EmptyScreen, showToast, Switch, Tooltip } from "@calcom/ui/v2";
|
import { Badge, Button, ButtonGroup, Dialog, EmptyScreen, showToast, Switch, Tooltip } from "@calcom/ui/v2";
|
||||||
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
||||||
@@ -16,6 +17,7 @@ import Dropdown, {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
|
DropdownMenuPortal,
|
||||||
} from "@calcom/ui/v2/core/Dropdown";
|
} from "@calcom/ui/v2/core/Dropdown";
|
||||||
import Shell from "@calcom/ui/v2/core/Shell";
|
import Shell from "@calcom/ui/v2/core/Shell";
|
||||||
import CreateEventTypeButton from "@calcom/ui/v2/modules/event-types/CreateEventType";
|
import CreateEventTypeButton from "@calcom/ui/v2/modules/event-types/CreateEventType";
|
||||||
@@ -29,8 +31,6 @@ import Avatar from "@components/ui/Avatar";
|
|||||||
import AvatarGroup from "@components/ui/AvatarGroup";
|
import AvatarGroup from "@components/ui/AvatarGroup";
|
||||||
import SkeletonLoader from "@components/v2/eventtype/SkeletonLoader";
|
import SkeletonLoader from "@components/v2/eventtype/SkeletonLoader";
|
||||||
|
|
||||||
import { TRPCClientError } from "@trpc/react";
|
|
||||||
|
|
||||||
type EventTypeGroups = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"];
|
type EventTypeGroups = inferQueryOutput<"viewer.eventTypes">["eventTypeGroups"];
|
||||||
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
|
type EventTypeGroupProfile = EventTypeGroups[number]["profile"];
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ const Item = ({ type, group, readOnly }: { type: EventType; group: EventTypeGrou
|
|||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href={`/event-types/${type.id}`}>
|
<Link href={`/event-types/${type.id}?tabName=setup`}>
|
||||||
<a
|
<a
|
||||||
className="flex-grow truncate text-sm"
|
className="flex-grow truncate text-sm"
|
||||||
title={`${type.title} ${type.description ? `– ${type.description}` : ""}`}>
|
title={`${type.title} ${type.description ? `– ${type.description}` : ""}`}>
|
||||||
@@ -82,6 +82,7 @@ const MemoizedItem = React.memo(Item);
|
|||||||
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
|
export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeListProps): JSX.Element => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const [parent] = useAutoAnimate<HTMLUListElement>();
|
||||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||||
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
|
const [deleteDialogTypeId, setDeleteDialogTypeId] = useState(0);
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
@@ -91,8 +92,8 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
await utils.cancelQuery(["viewer.eventTypes"]);
|
await utils.cancelQuery(["viewer.eventTypes"]);
|
||||||
await utils.invalidateQueries(["viewer.eventTypes"]);
|
await utils.invalidateQueries(["viewer.eventTypes"]);
|
||||||
},
|
},
|
||||||
onSettled: async () => {
|
onSettled: () => {
|
||||||
await utils.invalidateQueries(["viewer.eventTypes"]);
|
utils.invalidateQueries(["viewer.eventTypes"]);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function moveEventType(index: number, increment: 1 | -1) {
|
async function moveEventType(index: number, increment: 1 | -1) {
|
||||||
const newList = [...types];
|
const newList = [...types];
|
||||||
|
|
||||||
const type = types[index];
|
const type = types[index];
|
||||||
@@ -117,24 +118,19 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
newList[index + increment] = type;
|
newList[index + increment] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.cancelQuery(["viewer.eventTypes"]);
|
await utils.cancelQuery(["viewer.eventTypes"]);
|
||||||
utils.setQueryData(["viewer.eventTypes"], (data) => {
|
|
||||||
// tRPC is very strict with the return signature...
|
const previousValue = utils.getQueryData(["viewer.eventTypes"]);
|
||||||
if (!data)
|
if (previousValue) {
|
||||||
return {
|
utils.setQueryData(["viewer.eventTypes"], {
|
||||||
eventTypeGroups: [],
|
...previousValue,
|
||||||
profiles: [],
|
eventTypeGroups: [
|
||||||
viewer: { canAddEvents: true, plan: UserPlan.PRO },
|
...previousValue.eventTypeGroups.slice(0, groupIndex),
|
||||||
};
|
|
||||||
return {
|
|
||||||
...data,
|
|
||||||
eventTypesGroups: [
|
|
||||||
...data.eventTypeGroups.slice(0, groupIndex),
|
|
||||||
{ ...group, eventTypes: newList },
|
{ ...group, eventTypes: newList },
|
||||||
...data.eventTypeGroups.slice(groupIndex + 1),
|
...previousValue.eventTypeGroups.slice(groupIndex + 1),
|
||||||
],
|
],
|
||||||
};
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
ids: newList.map((type) => type.id),
|
ids: newList.map((type) => type.id),
|
||||||
@@ -201,7 +197,7 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
const lastItem = types[types.length - 1];
|
const lastItem = types[types.length - 1];
|
||||||
return (
|
return (
|
||||||
<div className="mb-16 flex overflow-hidden rounded-md border border-gray-200 bg-white">
|
<div className="mb-16 flex overflow-hidden rounded-md border border-gray-200 bg-white">
|
||||||
<ul className="w-full divide-y divide-neutral-200" data-testid="event-types">
|
<ul ref={parent} className="!static w-full divide-y divide-neutral-200" data-testid="event-types">
|
||||||
{types.map((type, index) => {
|
{types.map((type, index) => {
|
||||||
const embedLink = `${group.profile.slug}/${type.slug}`;
|
const embedLink = `${group.profile.slug}/${type.slug}`;
|
||||||
const calLink = `${CAL_URL}/${embedLink}`;
|
const calLink = `${CAL_URL}/${embedLink}`;
|
||||||
@@ -296,8 +292,9 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
<DropdownMenuItem>
|
<DropdownMenuItem>
|
||||||
<DropdownItem
|
<DropdownItem
|
||||||
type="button"
|
type="button"
|
||||||
href={"/event-types/" + type.id}
|
data-testid={"event-type-edit-" + type.id}
|
||||||
StartIcon={Icon.FiEdit2}>
|
StartIcon={Icon.FiEdit2}
|
||||||
|
onClick={() => router.push("/event-types/" + type.id)}>
|
||||||
{t("edit") as string}
|
{t("edit") as string}
|
||||||
</DropdownItem>
|
</DropdownItem>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -347,90 +344,92 @@ export const EventTypeList = ({ group, groupIndex, readOnly, types }: EventTypeL
|
|||||||
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
|
<DropdownMenuTrigger asChild data-testid={"event-type-options-" + type.id}>
|
||||||
<Button type="button" size="icon" color="secondary" StartIcon={Icon.FiMoreHorizontal} />
|
<Button type="button" size="icon" color="secondary" StartIcon={Icon.FiMoreHorizontal} />
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent portalled>
|
<DropdownMenuPortal>
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuContent>
|
||||||
<Link href={calLink}>
|
<DropdownMenuItem className="outline-none">
|
||||||
<a target="_blank">
|
<Link href={calLink}>
|
||||||
|
<a target="_blank">
|
||||||
|
<Button
|
||||||
|
color="minimal"
|
||||||
|
StartIcon={Icon.FiExternalLink}
|
||||||
|
className="w-full rounded-none">
|
||||||
|
{t("preview") as string}
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</Link>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem className="outline-none">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
color="minimal"
|
||||||
|
className="w-full rounded-none text-left"
|
||||||
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
|
StartIcon={Icon.FiClipboard}
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(calLink);
|
||||||
|
showToast(t("link_copied"), "success");
|
||||||
|
}}>
|
||||||
|
{t("copy_link") as string}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuItem>
|
||||||
|
{isNativeShare ? (
|
||||||
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
|
type="button"
|
||||||
color="minimal"
|
color="minimal"
|
||||||
StartIcon={Icon.FiExternalLink}
|
className="w-full rounded-none"
|
||||||
className="w-full rounded-none">
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
{t("preview") as string}
|
StartIcon={Icon.FiUpload}
|
||||||
|
onClick={() => {
|
||||||
|
navigator
|
||||||
|
.share({
|
||||||
|
title: t("share"),
|
||||||
|
text: t("share_event"),
|
||||||
|
url: calLink,
|
||||||
|
})
|
||||||
|
.then(() => showToast(t("link_shared"), "success"))
|
||||||
|
.catch(() => showToast(t("failed"), "error"));
|
||||||
|
}}>
|
||||||
|
{t("share") as string}
|
||||||
</Button>
|
</Button>
|
||||||
</a>
|
</DropdownMenuItem>
|
||||||
</Link>
|
) : null}
|
||||||
</DropdownMenuItem>
|
<DropdownMenuItem className="outline-none">
|
||||||
<DropdownMenuItem className="outline-none">
|
<Button
|
||||||
<Button
|
type="button"
|
||||||
type="button"
|
onClick={() => router.push("/event-types/" + type.id)}
|
||||||
color="minimal"
|
color="minimal"
|
||||||
className="w-full rounded-none text-left"
|
className="w-full rounded-none"
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
StartIcon={Icon.FiEdit}>
|
||||||
StartIcon={Icon.FiClipboard}
|
{t("edit") as string}
|
||||||
onClick={() => {
|
</Button>
|
||||||
navigator.clipboard.writeText(calLink);
|
</DropdownMenuItem>
|
||||||
showToast(t("link_copied"), "success");
|
|
||||||
}}>
|
|
||||||
{t("copy_link") as string}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
{isNativeShare ? (
|
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="minimal"
|
color="minimal"
|
||||||
className="w-full rounded-none"
|
className="w-full rounded-none"
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
data-testid={"event-type-duplicate-" + type.id}
|
||||||
StartIcon={Icon.FiUpload}
|
StartIcon={Icon.FiCopy}
|
||||||
onClick={() => {
|
onClick={() => openModal(group, type)}>
|
||||||
navigator
|
{t("duplicate") as string}
|
||||||
.share({
|
|
||||||
title: t("share"),
|
|
||||||
text: t("share_event"),
|
|
||||||
url: calLink,
|
|
||||||
})
|
|
||||||
.then(() => showToast(t("link_shared"), "success"))
|
|
||||||
.catch(() => showToast(t("failed"), "error"));
|
|
||||||
}}>
|
|
||||||
{t("share") as string}
|
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
) : null}
|
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
||||||
<DropdownMenuItem className="outline-none">
|
<DropdownMenuItem className="outline-none">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
onClick={() => {
|
||||||
href={"/event-types/" + type.id}
|
setDeleteDialogOpen(true);
|
||||||
color="minimal"
|
setDeleteDialogTypeId(type.id);
|
||||||
className="w-full"
|
}}
|
||||||
StartIcon={Icon.FiEdit}>
|
color="destructive"
|
||||||
{t("edit") as string}
|
StartIcon={Icon.FiTrash}
|
||||||
</Button>
|
className="w-full rounded-none">
|
||||||
</DropdownMenuItem>
|
{t("delete") as string}
|
||||||
<DropdownMenuItem className="outline-none">
|
</Button>
|
||||||
<Button
|
</DropdownMenuItem>
|
||||||
type="button"
|
</DropdownMenuContent>
|
||||||
color="minimal"
|
</DropdownMenuPortal>
|
||||||
className="w-full rounded-none"
|
|
||||||
data-testid={"event-type-duplicate-" + type.id}
|
|
||||||
StartIcon={Icon.FiCopy}
|
|
||||||
onClick={() => openModal(group, type)}>
|
|
||||||
{t("duplicate") as string}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
<DropdownMenuSeparator className="h-px bg-gray-200" />
|
|
||||||
<DropdownMenuItem className="outline-none">
|
|
||||||
<Button
|
|
||||||
onClick={() => {
|
|
||||||
setDeleteDialogOpen(true);
|
|
||||||
setDeleteDialogTypeId(type.id);
|
|
||||||
}}
|
|
||||||
color="destructive"
|
|
||||||
StartIcon={Icon.FiTrash}
|
|
||||||
className="w-full rounded-none">
|
|
||||||
{t("delete") as string}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { HelpScout, useChat } from "react-live-chat-loader";
|
||||||
|
|
||||||
|
import { classNames } from "@calcom/lib";
|
||||||
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
|
import { trpc } from "@calcom/trpc/react";
|
||||||
|
import { Icon } from "@calcom/ui";
|
||||||
|
import { Button } from "@calcom/ui/v2";
|
||||||
|
import Meta from "@calcom/ui/v2/core/Meta";
|
||||||
|
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
|
||||||
|
|
||||||
|
interface CtaRowProps {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CtaRow = ({ title, description, className, children }: CtaRowProps) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<section className={classNames("flex flex-col sm:flex-row", className)}>
|
||||||
|
<div>
|
||||||
|
<h2 className="font-medium">{title}</h2>
|
||||||
|
<p>{description}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 pt-3 sm:ml-auto sm:pt-0 sm:pl-3">{children}</div>
|
||||||
|
</section>
|
||||||
|
<hr className="border-neutral-200" />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BillingView = () => {
|
||||||
|
const { t } = useLocale();
|
||||||
|
const { data: user } = trpc.useQuery(["viewer.me"]);
|
||||||
|
const isPro = user?.plan === "PRO";
|
||||||
|
const [, loadChat] = useChat();
|
||||||
|
const [showChat, setShowChat] = useState(false);
|
||||||
|
|
||||||
|
const onContactSupportClick = () => {
|
||||||
|
setShowChat(true);
|
||||||
|
loadChat({ open: true });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Meta title={t("billing")} description={t("manage_billing_description")} />
|
||||||
|
<div className="space-y-6 text-sm sm:space-y-8">
|
||||||
|
{!isPro && (
|
||||||
|
<CtaRow title={t("billing_freeplan_title")} description={t("billing_freeplan_description")}>
|
||||||
|
<form target="_blank" method="POST" action="/api/upgrade">
|
||||||
|
<Button type="submit" EndIcon={Icon.FiExternalLink}>
|
||||||
|
{t("billing_freeplan_cta")}
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</CtaRow>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<CtaRow
|
||||||
|
className={classNames(!isPro && "pointer-events-none opacity-30")}
|
||||||
|
title={t("billing_manage_details_title")}
|
||||||
|
description={t("billing_manage_details_description")}>
|
||||||
|
<Button
|
||||||
|
color={isPro ? "primary" : "secondary"}
|
||||||
|
href="/api/integrations/stripepayment/portal"
|
||||||
|
target="_blank"
|
||||||
|
EndIcon={Icon.FiExternalLink}>
|
||||||
|
{t("billing_portal")}
|
||||||
|
</Button>
|
||||||
|
</CtaRow>
|
||||||
|
|
||||||
|
<CtaRow title={t("billing_help_title")} description={t("billing_help_description")}>
|
||||||
|
<Button color="secondary" onClick={onContactSupportClick}>
|
||||||
|
{t("billing_help_cta")}
|
||||||
|
</Button>
|
||||||
|
</CtaRow>
|
||||||
|
{showChat && <HelpScout color="#292929" icon="message" horizontalPosition="right" zIndex="1" />}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
BillingView.getLayout = getLayout;
|
||||||
|
|
||||||
|
export default BillingView;
|
||||||
@@ -39,16 +39,16 @@ const ApiKeysView = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Meta title="api_keys" description="webhooks_description" />
|
<Meta title="API Keys" description="API keys allow other apps to communicate with Cal.com" />
|
||||||
|
|
||||||
<LicenseRequired>
|
<LicenseRequired>
|
||||||
<>
|
<>
|
||||||
{isLoading && <SkeletonLoader />}
|
{isLoading && <SkeletonLoader />}
|
||||||
<div>
|
<div>
|
||||||
{data?.length ? (
|
{isLoading ? null : data?.length ? (
|
||||||
<>
|
<>
|
||||||
<div className="mt-6 mb-8 rounded-md border">
|
<div className="mt-6 mb-8 rounded-md border">
|
||||||
{data?.map((apiKey, index) => (
|
{data.map((apiKey, index) => (
|
||||||
<ApiKeyListItem
|
<ApiKeyListItem
|
||||||
key={apiKey.id}
|
key={apiKey.id}
|
||||||
apiKey={apiKey}
|
apiKey={apiKey}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { WEBAPP_URL } from "@calcom/lib/constants";
|
|||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import { Icon } from "@calcom/ui";
|
import { Icon } from "@calcom/ui";
|
||||||
|
import { Alert } from "@calcom/ui/v2";
|
||||||
import Badge from "@calcom/ui/v2/core/Badge";
|
import Badge from "@calcom/ui/v2/core/Badge";
|
||||||
import EmptyScreen from "@calcom/ui/v2/core/EmptyScreen";
|
import EmptyScreen from "@calcom/ui/v2/core/EmptyScreen";
|
||||||
import Meta from "@calcom/ui/v2/core/Meta";
|
import Meta from "@calcom/ui/v2/core/Meta";
|
||||||
@@ -23,7 +24,7 @@ import { CalendarSwitch } from "@components/v2/settings/CalendarSwitch";
|
|||||||
const SkeletonLoader = () => {
|
const SkeletonLoader = () => {
|
||||||
return (
|
return (
|
||||||
<SkeletonContainer>
|
<SkeletonContainer>
|
||||||
<div className="mt-6 mb-8 space-y-6 divide-y">
|
<div className="mt-6 mb-8 space-y-6">
|
||||||
<SkeletonText className="h-8 w-full" />
|
<SkeletonText className="h-8 w-full" />
|
||||||
<SkeletonText className="h-8 w-full" />
|
<SkeletonText className="h-8 w-full" />
|
||||||
<SkeletonText className="h-8 w-full" />
|
<SkeletonText className="h-8 w-full" />
|
||||||
@@ -89,7 +90,30 @@ const CalendarsView = () => {
|
|||||||
<List>
|
<List>
|
||||||
{data.connectedCalendars.map((item) => (
|
{data.connectedCalendars.map((item) => (
|
||||||
<Fragment key={item.credentialId}>
|
<Fragment key={item.credentialId}>
|
||||||
{item.calendars && (
|
{item.error && item.error.message && (
|
||||||
|
<Alert
|
||||||
|
severity="warning"
|
||||||
|
key={item.credentialId}
|
||||||
|
title={t("calendar_connection_fail")}
|
||||||
|
message={item.error.message}
|
||||||
|
className="mb-4 mt-4"
|
||||||
|
actions={
|
||||||
|
<>
|
||||||
|
{/* @TODO: add a reconnect button, that calls add api and delete old credential */}
|
||||||
|
<DisconnectIntegration
|
||||||
|
credentialId={item.credentialId}
|
||||||
|
trashIcon
|
||||||
|
onSuccess={() => query.refetch()}
|
||||||
|
buttonProps={{
|
||||||
|
className: "border border-gray-300 py-[2px]",
|
||||||
|
color: "secondary",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{item?.error === undefined && item.calendars && (
|
||||||
<ListItem expanded className="flex-col">
|
<ListItem expanded className="flex-col">
|
||||||
<div className="flex w-full flex-1 items-center space-x-3 pb-5 pl-1 pt-1 rtl:space-x-reverse">
|
<div className="flex w-full flex-1 items-center space-x-3 pb-5 pl-1 pt-1 rtl:space-x-reverse">
|
||||||
{
|
{
|
||||||
@@ -132,6 +156,7 @@ const CalendarsView = () => {
|
|||||||
externalId={cal.externalId}
|
externalId={cal.externalId}
|
||||||
title={cal.name || "Nameless calendar"}
|
title={cal.name || "Nameless calendar"}
|
||||||
type={item.integration.type}
|
type={item.integration.type}
|
||||||
|
isSelected={cal.isSelected}
|
||||||
defaultSelected={cal.externalId === data?.destinationCalendar?.externalId}
|
defaultSelected={cal.externalId === data?.destinationCalendar?.externalId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
@@ -153,6 +178,22 @@ const CalendarsView = () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
error={() => {
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
message={
|
||||||
|
<Trans i18nKey="fetching_calendars_error">
|
||||||
|
An error ocurred while fetching your Calendars.
|
||||||
|
<a className="cursor-pointer underline" onClick={() => query.refetch()}>
|
||||||
|
try again
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</Trans>
|
||||||
|
}
|
||||||
|
severity="error"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const ConferencingLayout = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full bg-white sm:mx-0 xl:mt-0">
|
<div className="w-full bg-white sm:mx-0 xl:mt-0">
|
||||||
<Meta title="conferencing" description="conferencing_description" />
|
<Meta title="Conferencing" description="Add your favourite video conferencing apps for your meetings" />
|
||||||
<List roundContainer={true}>
|
<List roundContainer={true}>
|
||||||
{apps?.items &&
|
{apps?.items &&
|
||||||
apps.items
|
apps.items
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { useMemo } from "react";
|
|||||||
import { useForm, Controller } from "react-hook-form";
|
import { useForm, Controller } from "react-hook-form";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { trpc } from "@calcom/trpc/react";
|
import { setIs24hClockInLocalStorage } from "@calcom/lib/timeFormat";
|
||||||
|
import { inferQueryOutput, trpc } from "@calcom/trpc/react";
|
||||||
import { Button } from "@calcom/ui/v2/core/Button";
|
import { Button } from "@calcom/ui/v2/core/Button";
|
||||||
import Meta from "@calcom/ui/v2/core/Meta";
|
import Meta from "@calcom/ui/v2/core/Meta";
|
||||||
import TimezoneSelect from "@calcom/ui/v2/core/TimezoneSelect";
|
import TimezoneSelect from "@calcom/ui/v2/core/TimezoneSelect";
|
||||||
import Select from "@calcom/ui/v2/core/form/Select";
|
|
||||||
import { Form, Label } from "@calcom/ui/v2/core/form/fields";
|
import { Form, Label } from "@calcom/ui/v2/core/form/fields";
|
||||||
|
import Select from "@calcom/ui/v2/core/form/select";
|
||||||
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
|
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
|
||||||
import showToast from "@calcom/ui/v2/core/notifications";
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
import { SkeletonContainer, SkeletonText, SkeletonButton } from "@calcom/ui/v2/core/skeleton";
|
import { SkeletonContainer, SkeletonText, SkeletonButton } from "@calcom/ui/v2/core/skeleton";
|
||||||
@@ -33,25 +34,32 @@ const SkeletonLoader = () => {
|
|||||||
|
|
||||||
interface GeneralViewProps {
|
interface GeneralViewProps {
|
||||||
localeProp: string;
|
localeProp: string;
|
||||||
|
user: inferQueryOutput<"viewer.me">;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WithQuery = withQuery(["viewer.public.i18n"], { context: { skipBatch: true } });
|
const WithQuery = withQuery(["viewer.public.i18n"], { trpc: { context: { skipBatch: true } } });
|
||||||
|
|
||||||
const GeneralQueryView = () => {
|
const GeneralQueryView = () => {
|
||||||
|
const { t } = useLocale();
|
||||||
|
|
||||||
|
const { data: user, isLoading } = trpc.useQuery(["viewer.me"]);
|
||||||
|
if (isLoading) return <SkeletonLoader />;
|
||||||
|
if (!user) {
|
||||||
|
throw new Error(t("something_went_wrong"));
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<WithQuery
|
<WithQuery
|
||||||
success={({ data }) => <GeneralView localeProp={data.locale} />}
|
success={({ data }) => <GeneralView user={user} localeProp={data.locale} />}
|
||||||
customLoader={<SkeletonLoader />}
|
customLoader={<SkeletonLoader />}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const GeneralView = ({ localeProp }: GeneralViewProps) => {
|
const GeneralView = ({ localeProp, user }: GeneralViewProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
|
|
||||||
const { data: user, isLoading } = trpc.useQuery(["viewer.me"]);
|
|
||||||
const mutation = trpc.useMutation("viewer.updateProfile", {
|
const mutation = trpc.useMutation("viewer.updateProfile", {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
showToast(t("settings_updated_successfully"), "success");
|
showToast(t("settings_updated_successfully"), "success");
|
||||||
@@ -92,24 +100,24 @@ const GeneralView = ({ localeProp }: GeneralViewProps) => {
|
|||||||
value: localeProp || "",
|
value: localeProp || "",
|
||||||
label: localeOptions.find((option) => option.value === localeProp)?.label || "",
|
label: localeOptions.find((option) => option.value === localeProp)?.label || "",
|
||||||
},
|
},
|
||||||
timeZone: user?.timeZone || "",
|
timeZone: user.timeZone || "",
|
||||||
timeFormat: {
|
timeFormat: {
|
||||||
value: user?.timeFormat || 12,
|
value: user.timeFormat || 12,
|
||||||
label: timeFormatOptions.find((option) => option.value === user?.timeFormat)?.label || 12,
|
label: timeFormatOptions.find((option) => option.value === user.timeFormat)?.label || 12,
|
||||||
},
|
},
|
||||||
weekStart: {
|
weekStart: {
|
||||||
value: user?.weekStart,
|
value: user.weekStart,
|
||||||
label: nameOfDay(localeProp, user?.weekStart === "Sunday" ? 0 : 1),
|
label: nameOfDay(localeProp, user.weekStart === "Sunday" ? 0 : 1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (isLoading) return <SkeletonLoader />;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
form={formMethods}
|
form={formMethods}
|
||||||
handleSubmit={(values) => {
|
handleSubmit={(values) => {
|
||||||
|
setIs24hClockInLocalStorage(values.timeFormat.value === 24);
|
||||||
|
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
...values,
|
...values,
|
||||||
locale: values.locale.value,
|
locale: values.locale.value,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
import { signOut } from "next-auth/react";
|
import { signOut } from "next-auth/react";
|
||||||
import { useRef, useState, BaseSyntheticEvent } from "react";
|
import { useRef, useState, BaseSyntheticEvent, useEffect } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
|
||||||
import { ErrorCode } from "@calcom/lib/auth";
|
import { ErrorCode } from "@calcom/lib/auth";
|
||||||
@@ -22,6 +22,7 @@ import showToast from "@calcom/ui/v2/core/notifications";
|
|||||||
import { SkeletonContainer, SkeletonText, SkeletonButton, SkeletonAvatar } from "@calcom/ui/v2/core/skeleton";
|
import { SkeletonContainer, SkeletonText, SkeletonButton, SkeletonAvatar } from "@calcom/ui/v2/core/skeleton";
|
||||||
|
|
||||||
import TwoFactor from "@components/auth/TwoFactor";
|
import TwoFactor from "@components/auth/TwoFactor";
|
||||||
|
import { UsernameAvailability } from "@components/ui/UsernameAvailability";
|
||||||
|
|
||||||
const SkeletonLoader = () => {
|
const SkeletonLoader = () => {
|
||||||
return (
|
return (
|
||||||
@@ -48,6 +49,7 @@ interface DeleteAccountValues {
|
|||||||
const ProfileView = () => {
|
const ProfileView = () => {
|
||||||
const { t } = useLocale();
|
const { t } = useLocale();
|
||||||
const utils = trpc.useContext();
|
const utils = trpc.useContext();
|
||||||
|
const usernameRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
const { data: user, isLoading } = trpc.useQuery(["viewer.me"]);
|
const { data: user, isLoading } = trpc.useQuery(["viewer.me"]);
|
||||||
const mutation = trpc.useMutation("viewer.updateProfile", {
|
const mutation = trpc.useMutation("viewer.updateProfile", {
|
||||||
@@ -64,7 +66,11 @@ const ProfileView = () => {
|
|||||||
const [deleteAccountOpen, setDeleteAccountOpen] = useState(false);
|
const [deleteAccountOpen, setDeleteAccountOpen] = useState(false);
|
||||||
const [hasDeleteErrors, setHasDeleteErrors] = useState(false);
|
const [hasDeleteErrors, setHasDeleteErrors] = useState(false);
|
||||||
const [deleteErrorMessage, setDeleteErrorMessage] = useState("");
|
const [deleteErrorMessage, setDeleteErrorMessage] = useState("");
|
||||||
|
const [currentUsername, setCurrentUsername] = useState<string | undefined>(user?.username || undefined);
|
||||||
|
const [inputUsernameValue, setInputUsernameValue] = useState(currentUsername);
|
||||||
|
useEffect(() => {
|
||||||
|
if (user?.username) setCurrentUsername(user?.username);
|
||||||
|
}, [user?.username]);
|
||||||
const form = useForm<DeleteAccountValues>();
|
const form = useForm<DeleteAccountValues>();
|
||||||
|
|
||||||
const emailMd5 = crypto
|
const emailMd5 = crypto
|
||||||
@@ -124,15 +130,26 @@ const ProfileView = () => {
|
|||||||
deleteMeMutation.mutate({ password, totpCode });
|
deleteMeMutation.mutate({ password, totpCode });
|
||||||
};
|
};
|
||||||
|
|
||||||
const formMethods = useForm({
|
const formMethods = useForm<{
|
||||||
defaultValues: {
|
avatar?: string;
|
||||||
avatar: user?.avatar || "",
|
username?: string;
|
||||||
username: user?.username || "",
|
name?: string;
|
||||||
name: user?.name || "",
|
email?: string;
|
||||||
email: user?.email || "",
|
bio?: string;
|
||||||
bio: user?.bio || "",
|
}>();
|
||||||
},
|
|
||||||
});
|
const { reset } = formMethods;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (user)
|
||||||
|
reset({
|
||||||
|
avatar: user?.avatar || "",
|
||||||
|
username: user?.username || "",
|
||||||
|
name: user?.name || "",
|
||||||
|
email: user?.email || "",
|
||||||
|
bio: user?.bio || "",
|
||||||
|
});
|
||||||
|
}, [reset, user]);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const passwordRef = useRef<HTMLInputElement>(null!);
|
const passwordRef = useRef<HTMLInputElement>(null!);
|
||||||
@@ -145,8 +162,16 @@ const ProfileView = () => {
|
|||||||
[ErrorCode.InternalServerError]: `${t("something_went_wrong")} ${t("please_try_again_and_contact_us")}`,
|
[ErrorCode.InternalServerError]: `${t("something_went_wrong")} ${t("please_try_again_and_contact_us")}`,
|
||||||
[ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"),
|
[ErrorCode.ThirdPartyIdentityProviderEnabled]: t("account_created_with_identity_provider"),
|
||||||
};
|
};
|
||||||
|
const onSuccessfulUsernameUpdate = async () => {
|
||||||
|
showToast(t("settings_updated_successfully"), "success");
|
||||||
|
await utils.invalidateQueries(["viewer.me"]);
|
||||||
|
};
|
||||||
|
|
||||||
if (isLoading) return <SkeletonLoader />;
|
const onErrorInUsernameUpdate = () => {
|
||||||
|
showToast(t("error_updating_settings"), "error");
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoading || !user) return <SkeletonLoader />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -183,11 +208,15 @@ const ProfileView = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<TextField
|
<UsernameAvailability
|
||||||
data-testid="username-input"
|
currentUsername={currentUsername}
|
||||||
label={t("personal_cal_url")}
|
setCurrentUsername={setCurrentUsername}
|
||||||
addOnLeading={WEBSITE_URL + "/"}
|
inputUsernameValue={inputUsernameValue}
|
||||||
{...formMethods.register("username")}
|
usernameRef={usernameRef}
|
||||||
|
setInputUsernameValue={setInputUsernameValue}
|
||||||
|
onSuccessMutation={onSuccessfulUsernameUpdate}
|
||||||
|
onErrorMutation={onErrorInUsernameUpdate}
|
||||||
|
user={user}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import { trpc } from "@calcom/trpc/react";
|
import { trpc } from "@calcom/trpc/react";
|
||||||
import Button from "@calcom/ui/v2/core/Button";
|
import Button from "@calcom/ui/v2/core/Button";
|
||||||
import Meta from "@calcom/ui/v2/core/Meta";
|
import Meta from "@calcom/ui/v2/core/Meta";
|
||||||
import { Form, TextField } from "@calcom/ui/v2/core/form/fields";
|
import { Form, PasswordField } from "@calcom/ui/v2/core/form/fields";
|
||||||
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
|
import { getLayout } from "@calcom/ui/v2/core/layouts/SettingsLayout";
|
||||||
import showToast from "@calcom/ui/v2/core/notifications";
|
import showToast from "@calcom/ui/v2/core/notifications";
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ const PasswordView = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Meta title="Password" description="Manage settings for your account passwords" />
|
<Meta title={t("password")} description={t("password_description")} />
|
||||||
{user && user.identityProvider !== IdentityProvider.CAL ? (
|
{user && user.identityProvider !== IdentityProvider.CAL ? (
|
||||||
<div>
|
<div>
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
@@ -65,22 +65,17 @@ const PasswordView = () => {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Form<ChangePasswordFormValues> form={formMethods} handleSubmit={handleSubmit}>
|
<Form form={formMethods} handleSubmit={handleSubmit}>
|
||||||
<div className="max-w-[38rem] sm:flex sm:space-x-4">
|
<div className="max-w-[38rem] sm:flex sm:space-x-4">
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
<TextField {...register("oldPassword")} label={t("old_password")} type="password" />
|
<PasswordField {...register("oldPassword")} label={t("old_password")} />
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-grow">
|
<div className="flex-grow">
|
||||||
<TextField
|
<PasswordField {...register("newPassword")} label={t("new_password")} />
|
||||||
{...register("newPassword")}
|
|
||||||
label={t("new_password")}
|
|
||||||
type="password"
|
|
||||||
placeholder={t("secure_password")}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-gray-600">
|
<p className="text-sm text-gray-600">
|
||||||
<Trans i18nKey="valid_password">
|
<Trans i18nKey="invalid_password_hint">
|
||||||
Password must be at least at least 7 characters, mix of uppercase & lowercase letters, and
|
Password must be at least at least 7 characters, mix of uppercase & lowercase letters, and
|
||||||
contain at least 1 number
|
contain at least 1 number
|
||||||
</Trans>
|
</Trans>
|
||||||
@@ -89,8 +84,8 @@ const PasswordView = () => {
|
|||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
className="mt-8"
|
className="mt-8"
|
||||||
disabled={isSubmitting || mutation.isLoading}
|
type="submit"
|
||||||
onClick={() => handleSubmit(formMethods.getValues())}>
|
disabled={isSubmitting || mutation.isLoading}>
|
||||||
{t("update")}
|
{t("update")}
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -69,10 +69,9 @@ const CreateNewTeamPage = () => {
|
|||||||
data-testid="onboarding"
|
data-testid="onboarding"
|
||||||
key={router.asPath}>
|
key={router.asPath}>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{t("create_new_team")}</title>
|
<title>Create a new Team</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<div className="mx-auto px-4 py-24">
|
<div className="mx-auto px-4 py-24">
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
<div className="sm:mx-auto sm:w-full sm:max-w-[600px]">
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|||||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||||
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
|
import { getEveryFreqFor } from "@calcom/lib/recurringStrings";
|
||||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||||
import { isBrowserLocale24h } from "@calcom/lib/timeFormat";
|
import { getIs24hClockFromLocalStorage, isBrowserLocale24h } from "@calcom/lib/timeFormat";
|
||||||
import { localStorage } from "@calcom/lib/webstorage";
|
import { localStorage } from "@calcom/lib/webstorage";
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import Button from "@calcom/ui/Button";
|
import Button from "@calcom/ui/Button";
|
||||||
@@ -201,7 +201,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
// TODO: Add payment details
|
// TODO: Add payment details
|
||||||
});
|
});
|
||||||
setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()));
|
setDate(date.tz(localStorage.getItem("timeOption.preferredTimeZone") || dayjs.tz.guess()));
|
||||||
setIs24h(!!localStorage.getItem("timeOption.is24hClock"));
|
setIs24h(!!getIs24hClockFromLocalStorage());
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [eventType, needsConfirmation]);
|
}, [eventType, needsConfirmation]);
|
||||||
|
|
||||||
@@ -263,7 +263,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
{userIsOwner && !isEmbed && (
|
{userIsOwner && !isEmbed && (
|
||||||
<div className="mt-2 ml-4 -mb-4">
|
<div className="mt-2 ml-4 -mb-4">
|
||||||
<Link href={eventType.recurringEvent?.count ? "/bookings/recurring" : "/bookings/upcoming"}>
|
<Link href={eventType.recurringEvent?.count ? "/bookings/recurring" : "/bookings/upcoming"}>
|
||||||
<a className="mt-2 inline-flex px-1 py-2 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-800">
|
<a className="mt-2 inline-flex px-1 py-2 text-sm text-gray-500 hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-transparent dark:hover:text-white">
|
||||||
<Icon.FiChevronLeft className="h-5 w-5" /> {t("back_to_bookings")}
|
<Icon.FiChevronLeft className="h-5 w-5" /> {t("back_to_bookings")}
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
@@ -411,7 +411,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
!isCancelled &&
|
!isCancelled &&
|
||||||
(!isCancellationMode ? (
|
(!isCancellationMode ? (
|
||||||
<>
|
<>
|
||||||
<hr className="border-bookinglightest" />
|
<hr className="border-bookinglightest dark:border-darkgray-300" />
|
||||||
<div className="py-8 text-center last:pb-0">
|
<div className="py-8 text-center last:pb-0">
|
||||||
<span className="text-gray-900 ltr:mr-2 rtl:ml-2 dark:text-gray-50">
|
<span className="text-gray-900 ltr:mr-2 rtl:ml-2 dark:text-gray-50">
|
||||||
{t("need_to_make_a_change")}
|
{t("need_to_make_a_change")}
|
||||||
@@ -448,7 +448,7 @@ export default function Success(props: SuccessProps) {
|
|||||||
))}
|
))}
|
||||||
{userIsOwner && !needsConfirmation && !isCancellationMode && !isCancelled && (
|
{userIsOwner && !needsConfirmation && !isCancellationMode && !isCancelled && (
|
||||||
<>
|
<>
|
||||||
<hr className="border-bookinglightest" />
|
<hr className="border-bookinglightest dark:border-darkgray-300" />
|
||||||
<div className="text-bookingdark align-center flex flex-row justify-center pt-8">
|
<div className="text-bookingdark align-center flex flex-row justify-center pt-8">
|
||||||
<span className="flex self-center font-medium text-gray-700 ltr:mr-2 rtl:ml-2 dark:text-gray-50">
|
<span className="flex self-center font-medium text-gray-700 ltr:mr-2 rtl:ml-2 dark:text-gray-50">
|
||||||
{t("add_to_calendar")}
|
{t("add_to_calendar")}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ test.describe("Change username on settings", () => {
|
|||||||
await users.deleteAll();
|
await users.deleteAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("User can change username", async ({ page, users, prisma }) => {
|
/** TODO: Find out why it's timing out */
|
||||||
|
test.fixme("User can change username", async ({ page, users, prisma }) => {
|
||||||
const user = await users.create({ plan: UserPlan.TRIAL });
|
const user = await users.create({ plan: UserPlan.TRIAL });
|
||||||
|
|
||||||
await user.login();
|
await user.login();
|
||||||
@@ -35,10 +36,10 @@ test.describe("Change username on settings", () => {
|
|||||||
const usernameInput = page.locator("[data-testid=username-input]");
|
const usernameInput = page.locator("[data-testid=username-input]");
|
||||||
|
|
||||||
await usernameInput.fill("demousernamex");
|
await usernameInput.fill("demousernamex");
|
||||||
|
await page.click("[data-testid=update-username-btn]");
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
page.click("[data-testid=save-username]"),
|
||||||
page.waitForResponse("**/viewer.updateProfile*"),
|
page.waitForResponse("**/viewer.updateProfile*"),
|
||||||
page.click('button[type="submit"]'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const newUpdatedUser = await prisma.user.findUniqueOrThrow({
|
const newUpdatedUser = await prisma.user.findUniqueOrThrow({
|
||||||
|
|||||||
@@ -2,13 +2,8 @@ import { expect, Page } from "@playwright/test";
|
|||||||
|
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
|
|
||||||
// these tests need rewrite
|
function chooseEmbedType(page: Page, embedType: string) {
|
||||||
// eslint-disable-next-line playwright/no-skipped-test
|
page.locator(`[data-testid=${embedType}]`).click();
|
||||||
test.skip();
|
|
||||||
|
|
||||||
async function chooseEmbedType(page: Page, embedType: string) {
|
|
||||||
const $embedTypeSelector = await page.locator(`[data-testid=${embedType}]`);
|
|
||||||
$embedTypeSelector.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function gotToPreviewTab(page: Page) {
|
async function gotToPreviewTab(page: Page) {
|
||||||
@@ -111,7 +106,7 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
|
|
||||||
await chooseEmbedType(page, "inline");
|
chooseEmbedType(page, "inline");
|
||||||
|
|
||||||
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
||||||
embedUrl,
|
embedUrl,
|
||||||
@@ -119,19 +114,18 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
|
|
||||||
/*await expectToContainValidCode(page, { embedType: "inline" });
|
await expectToContainValidCode(page, { embedType: "inline" });
|
||||||
|
|
||||||
await gotToPreviewTab(page);
|
await gotToPreviewTab(page);
|
||||||
|
|
||||||
await expectToContainValidPreviewIframe(page, {
|
await expectToContainValidPreviewIframe(page, {
|
||||||
embedType: "inline",
|
embedType: "inline",
|
||||||
calLink: `${pro.username}/30-min`,
|
calLink: `${pro.username}/30-min`,
|
||||||
});*/
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("open Embed Dialog and choose floating-popup for First Event Type", async ({ page, users }) => {
|
test("open Embed Dialog and choose floating-popup for First Event Type", async ({ page, users }) => {
|
||||||
const [pro] = users.get();
|
const [pro] = users.get();
|
||||||
|
|
||||||
const embedUrl = await clickFirstEventTypeEmbedButton(page);
|
const embedUrl = await clickFirstEventTypeEmbedButton(page);
|
||||||
|
|
||||||
await expectToBeNavigatingToEmbedTypesDialog(page, {
|
await expectToBeNavigatingToEmbedTypesDialog(page, {
|
||||||
@@ -139,20 +133,20 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
|
|
||||||
await chooseEmbedType(page, "floating-popup");
|
chooseEmbedType(page, "floating-popup");
|
||||||
|
|
||||||
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
||||||
embedUrl,
|
embedUrl,
|
||||||
embedType: "floating-popup",
|
embedType: "floating-popup",
|
||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
/*await expectToContainValidCode(page, { embedType: "floating-popup" });
|
await expectToContainValidCode(page, { embedType: "floating-popup" });
|
||||||
|
|
||||||
await gotToPreviewTab(page);
|
await gotToPreviewTab(page);
|
||||||
await expectToContainValidPreviewIframe(page, {
|
await expectToContainValidPreviewIframe(page, {
|
||||||
embedType: "floating-popup",
|
embedType: "floating-popup",
|
||||||
calLink: `${pro.username}/30-min`,
|
calLink: `${pro.username}/30-min`,
|
||||||
});*/
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("open Embed Dialog and choose element-click for First Event Type", async ({ page, users }) => {
|
test("open Embed Dialog and choose element-click for First Event Type", async ({ page, users }) => {
|
||||||
@@ -164,20 +158,20 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
|
|
||||||
await chooseEmbedType(page, "element-click");
|
chooseEmbedType(page, "element-click");
|
||||||
|
|
||||||
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
||||||
embedUrl,
|
embedUrl,
|
||||||
embedType: "element-click",
|
embedType: "element-click",
|
||||||
basePage: "/event-types",
|
basePage: "/event-types",
|
||||||
});
|
});
|
||||||
/*await expectToContainValidCode(page, { embedType: "element-click" });
|
await expectToContainValidCode(page, { embedType: "element-click" });
|
||||||
|
|
||||||
await gotToPreviewTab(page);
|
await gotToPreviewTab(page);
|
||||||
await expectToContainValidPreviewIframe(page, {
|
await expectToContainValidPreviewIframe(page, {
|
||||||
embedType: "element-click",
|
embedType: "element-click",
|
||||||
calLink: `${pro.username}/30-min`,
|
calLink: `${pro.username}/30-min`,
|
||||||
});*/
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -200,7 +194,7 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
basePage,
|
basePage,
|
||||||
});
|
});
|
||||||
|
|
||||||
await chooseEmbedType(page, "inline");
|
chooseEmbedType(page, "inline");
|
||||||
|
|
||||||
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
await expectToBeNavigatingToEmbedCodeAndPreviewDialog(page, {
|
||||||
embedUrl,
|
embedUrl,
|
||||||
@@ -208,7 +202,7 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
embedType: "inline",
|
embedType: "inline",
|
||||||
});
|
});
|
||||||
|
|
||||||
/*await expectToContainValidCode(page, {
|
await expectToContainValidCode(page, {
|
||||||
embedType: "inline",
|
embedType: "inline",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -217,7 +211,7 @@ test.describe("Embed Code Generator Tests", () => {
|
|||||||
await expectToContainValidPreviewIframe(page, {
|
await expectToContainValidPreviewIframe(page, {
|
||||||
embedType: "inline",
|
embedType: "inline",
|
||||||
calLink: decodeURIComponent(embedUrl),
|
calLink: decodeURIComponent(embedUrl),
|
||||||
});*/
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { expect } from "@playwright/test";
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
|
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||||
|
|
||||||
import { randomString } from "../lib/random";
|
import { randomString } from "../lib/random";
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
|
|
||||||
@@ -87,7 +89,7 @@ test.describe("Event Types tests", () => {
|
|||||||
);
|
);
|
||||||
const href = await firstElement.getAttribute("href");
|
const href = await firstElement.getAttribute("href");
|
||||||
if (!href) throw new Error("No href found for event type");
|
if (!href) throw new Error("No href found for event type");
|
||||||
const [eventTypeId] = href.split("/").reverse();
|
const [eventTypeId] = new URL(WEBAPP_URL + href).pathname.split("/").reverse();
|
||||||
const firstTitle = await page.locator(`[data-testid=event-type-title-${eventTypeId}]`).innerText();
|
const firstTitle = await page.locator(`[data-testid=event-type-title-${eventTypeId}]`).innerText();
|
||||||
const firstFullSlug = await page.locator(`[data-testid=event-type-slug-${eventTypeId}]`).innerText();
|
const firstFullSlug = await page.locator(`[data-testid=event-type-slug-${eventTypeId}]`).innerText();
|
||||||
const firstSlug = firstFullSlug.split("/")[2];
|
const firstSlug = firstFullSlug.split("/")[2];
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type Prisma from "@prisma/client";
|
|||||||
import { Prisma as PrismaType, UserPlan } from "@prisma/client";
|
import { Prisma as PrismaType, UserPlan } from "@prisma/client";
|
||||||
import { hash } from "bcryptjs";
|
import { hash } from "bcryptjs";
|
||||||
|
|
||||||
|
import dayjs from "@calcom/dayjs";
|
||||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||||
import { prisma } from "@calcom/prisma";
|
import { prisma } from "@calcom/prisma";
|
||||||
|
|
||||||
@@ -257,7 +258,7 @@ const createUser = async (
|
|||||||
password: await hashPassword(uname),
|
password: await hashPassword(uname),
|
||||||
emailVerified: new Date(),
|
emailVerified: new Date(),
|
||||||
completedOnboarding: opts?.completedOnboarding ?? true,
|
completedOnboarding: opts?.completedOnboarding ?? true,
|
||||||
timeZone: opts?.timeZone ?? TimeZoneEnum.UK,
|
timeZone: opts?.timeZone ?? dayjs.tz.guess(),
|
||||||
locale: opts?.locale ?? "en",
|
locale: opts?.locale ?? "en",
|
||||||
schedules:
|
schedules:
|
||||||
opts?.completedOnboarding ?? true
|
opts?.completedOnboarding ?? true
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { v4 as uuidv4 } from "uuid";
|
|||||||
import { prisma } from "@calcom/prisma";
|
import { prisma } from "@calcom/prisma";
|
||||||
|
|
||||||
import { test } from "./lib/fixtures";
|
import { test } from "./lib/fixtures";
|
||||||
import { createHttpServer, selectFirstAvailableTimeSlotNextMonth, todo, waitFor } from "./lib/testUtils";
|
import { todo } from "./lib/testUtils";
|
||||||
|
|
||||||
declare let global: {
|
declare let global: {
|
||||||
E2E_EMAILS?: ({ text: string } | Record<string, unknown>)[];
|
E2E_EMAILS?: ({ text: string } | Record<string, unknown>)[];
|
||||||
@@ -182,7 +182,7 @@ test.fixme("Integrations", () => {
|
|||||||
},
|
},
|
||||||
token: {
|
token: {
|
||||||
url: "https://zoom.us/oauth/token",
|
url: "https://zoom.us/oauth/token",
|
||||||
verify({ requestHeaders, code }) {
|
verify({ requestHeaders }) {
|
||||||
const authorization = requestHeaders.get("authorization").replace("Basic ", "");
|
const authorization = requestHeaders.get("authorization").replace("Basic ", "");
|
||||||
const clientPair = Buffer.from(authorization, "base64").toString();
|
const clientPair = Buffer.from(authorization, "base64").toString();
|
||||||
const [clientId, clientSecret] = clientPair.split(":");
|
const [clientId, clientSecret] = clientPair.split(":");
|
||||||
@@ -361,75 +361,4 @@ test.fixme("Integrations", () => {
|
|||||||
todo("Can add CalDav Calendar");
|
todo("Can add CalDav Calendar");
|
||||||
|
|
||||||
todo("Can add Apple Calendar");
|
todo("Can add Apple Calendar");
|
||||||
|
|
||||||
test("add webhook & test that creating an event triggers a webhook call", async ({
|
|
||||||
page,
|
|
||||||
users,
|
|
||||||
}, testInfo) => {
|
|
||||||
const webhookReceiver = createHttpServer();
|
|
||||||
const user = await users.create();
|
|
||||||
const [eventType] = user.eventTypes;
|
|
||||||
await user.login();
|
|
||||||
await page.goto(`/settings/developer`);
|
|
||||||
|
|
||||||
// --- add webhook
|
|
||||||
await page.click('[data-testid="new_webhook"]');
|
|
||||||
|
|
||||||
await expect(page.locator(`[data-testid='WebhookDialogForm']`)).toBeVisible();
|
|
||||||
|
|
||||||
await page.fill('[name="subscriberUrl"]', webhookReceiver.url);
|
|
||||||
|
|
||||||
await page.fill('[name="secret"]', "secret");
|
|
||||||
|
|
||||||
await page.click("[type=submit]");
|
|
||||||
|
|
||||||
// dialog is closed
|
|
||||||
await expect(page.locator(`[data-testid='WebhookDialogForm']`)).not.toBeVisible();
|
|
||||||
// page contains the url
|
|
||||||
expect(page.locator(`text='${webhookReceiver.url}'`)).toBeDefined();
|
|
||||||
|
|
||||||
// --- Book the first available day next month in the pro user's "30min"-event
|
|
||||||
await page.goto(`/${user.username}/${eventType.slug}`);
|
|
||||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
|
||||||
|
|
||||||
// --- fill form
|
|
||||||
await page.fill('[name="name"]', "Test Testson");
|
|
||||||
await page.fill('[name="email"]', "test@example.com");
|
|
||||||
await page.press('[name="email"]', "Enter");
|
|
||||||
|
|
||||||
// --- check that webhook was called
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(webhookReceiver.requestList.length).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
const [request] = webhookReceiver.requestList;
|
|
||||||
const body = request.body as any;
|
|
||||||
|
|
||||||
// remove dynamic properties that differs depending on where you run the tests
|
|
||||||
const dynamic = "[redacted/dynamic]";
|
|
||||||
body.createdAt = dynamic;
|
|
||||||
body.payload.startTime = dynamic;
|
|
||||||
body.payload.endTime = dynamic;
|
|
||||||
body.payload.location = dynamic;
|
|
||||||
for (const attendee of body.payload.attendees) {
|
|
||||||
attendee.timeZone = dynamic;
|
|
||||||
attendee.language = dynamic;
|
|
||||||
}
|
|
||||||
body.payload.organizer.email = dynamic;
|
|
||||||
body.payload.organizer.timeZone = dynamic;
|
|
||||||
body.payload.organizer.language = dynamic;
|
|
||||||
body.payload.uid = dynamic;
|
|
||||||
body.payload.bookingId = dynamic;
|
|
||||||
body.payload.additionalInformation = dynamic;
|
|
||||||
body.payload.requiresConfirmation = dynamic;
|
|
||||||
body.payload.eventTypeId = dynamic;
|
|
||||||
|
|
||||||
// if we change the shape of our webhooks, we can simply update this by clicking `u`
|
|
||||||
// console.log("BODY", body);
|
|
||||||
// Text files shouldn't have platform specific suffixes
|
|
||||||
testInfo.snapshotSuffix = "";
|
|
||||||
expect(JSON.stringify(body)).toMatchSnapshot(`webhookResponse.txt`);
|
|
||||||
|
|
||||||
webhookReceiver.close();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { expect } from "@playwright/test";
|
||||||
|
|
||||||
|
import { test } from "./lib/fixtures";
|
||||||
|
import { createHttpServer, selectFirstAvailableTimeSlotNextMonth, waitFor } from "./lib/testUtils";
|
||||||
|
|
||||||
|
test("add webhook & test that creating an event triggers a webhook call", async ({
|
||||||
|
page,
|
||||||
|
users,
|
||||||
|
}, testInfo) => {
|
||||||
|
const webhookReceiver = createHttpServer();
|
||||||
|
const user = await users.create();
|
||||||
|
const [eventType] = user.eventTypes;
|
||||||
|
await user.login();
|
||||||
|
await page.goto(`/settings/developer/webhooks`);
|
||||||
|
|
||||||
|
// --- add webhook
|
||||||
|
await page.click('[data-testid="new_webhook"]');
|
||||||
|
|
||||||
|
await page.fill('[name="subscriberUrl"]', webhookReceiver.url);
|
||||||
|
|
||||||
|
await page.fill('[name="secret"]', "secret");
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
page.click("[type=submit]"),
|
||||||
|
page.waitForNavigation({
|
||||||
|
url: (url) => url.pathname.endsWith("/settings/developer/webhooks"),
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// page contains the url
|
||||||
|
expect(page.locator(`text='${webhookReceiver.url}'`)).toBeDefined();
|
||||||
|
|
||||||
|
// --- Book the first available day next month in the pro user's "30min"-event
|
||||||
|
await page.goto(`/${user.username}/${eventType.slug}`);
|
||||||
|
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||||
|
|
||||||
|
// --- fill form
|
||||||
|
await page.fill('[name="name"]', "Test Testson");
|
||||||
|
await page.fill('[name="email"]', "test@example.com");
|
||||||
|
await page.press('[name="email"]', "Enter");
|
||||||
|
|
||||||
|
// --- check that webhook was called
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(webhookReceiver.requestList.length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
const [request] = webhookReceiver.requestList;
|
||||||
|
const body = request.body as any;
|
||||||
|
|
||||||
|
// remove dynamic properties that differs depending on where you run the tests
|
||||||
|
const dynamic = "[redacted/dynamic]";
|
||||||
|
body.createdAt = dynamic;
|
||||||
|
body.payload.startTime = dynamic;
|
||||||
|
body.payload.endTime = dynamic;
|
||||||
|
body.payload.location = dynamic;
|
||||||
|
for (const attendee of body.payload.attendees) {
|
||||||
|
attendee.timeZone = dynamic;
|
||||||
|
attendee.language = dynamic;
|
||||||
|
}
|
||||||
|
body.payload.organizer.email = dynamic;
|
||||||
|
body.payload.organizer.timeZone = dynamic;
|
||||||
|
body.payload.organizer.language = dynamic;
|
||||||
|
body.payload.uid = dynamic;
|
||||||
|
body.payload.bookingId = dynamic;
|
||||||
|
body.payload.additionalInformation = dynamic;
|
||||||
|
body.payload.requiresConfirmation = dynamic;
|
||||||
|
body.payload.eventTypeId = dynamic;
|
||||||
|
|
||||||
|
// if we change the shape of our webhooks, we can simply update this by clicking `u`
|
||||||
|
// console.log("BODY", body);
|
||||||
|
// Text files shouldn't have platform specific suffixes
|
||||||
|
testInfo.snapshotSuffix = "";
|
||||||
|
expect(JSON.stringify(body)).toMatchSnapshot(`webhookResponse.txt`);
|
||||||
|
|
||||||
|
webhookReceiver.close();
|
||||||
|
});
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"triggerEvent":"BOOKING_CREATED","createdAt":"[redacted/dynamic]","payload":{"type":"30 min","title":"30 min between PRO and Test Testson","description":"","additionalNotes":"","customInputs":{},"startTime":"[redacted/dynamic]","endTime":"[redacted/dynamic]","organizer":{"name":"PRO","email":"[redacted/dynamic]","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"},"attendees":[{"email":"test@example.com","name":"Test Testson","timeZone":"[redacted/dynamic]","language":"[redacted/dynamic]"}],"location":"[redacted/dynamic]","destinationCalendar":null,"hideCalendarNotes":false,"requiresConfirmation":"[redacted/dynamic]","eventTypeId":"[redacted/dynamic]","uid":"[redacted/dynamic]","eventTitle":"30 min","eventDescription":null,"price":0,"currency":"usd","length":30,"bookingId":"[redacted/dynamic]","metadata":{},"status":"ACCEPTED","additionalInformation":"[redacted/dynamic]"}}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "استخدم الرابط أدناه لإعادة تعيين كلمة المرور",
|
"use_link_to_reset_password": "استخدم الرابط أدناه لإعادة تعيين كلمة المرور",
|
||||||
"hey_there": "مرحبًا،",
|
"hey_there": "مرحبًا،",
|
||||||
"forgot_your_password_calcom": "نسيت كلمة المرور الخاصة بك؟ - Cal.com",
|
"forgot_your_password_calcom": "نسيت كلمة المرور الخاصة بك؟ - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | نوع الحدث",
|
|
||||||
"delete_webhook_confirmation_message": "هل أنت متأكد أنك تريد حذف الويب هوك هذا؟ لن تتلقى بعد الآن بيانات اجتماعات Cal.com على عنوان URL محدد، وفي الوقت الفعلي، عندما تتم جدولة حدث أو يتم إلغاؤه.",
|
"delete_webhook_confirmation_message": "هل أنت متأكد أنك تريد حذف الويب هوك هذا؟ لن تتلقى بعد الآن بيانات اجتماعات Cal.com على عنوان URL محدد، وفي الوقت الفعلي، عندما تتم جدولة حدث أو يتم إلغاؤه.",
|
||||||
"confirm_delete_webhook": "نعم، قم بحذف الويبهوك",
|
"confirm_delete_webhook": "نعم، قم بحذف الويبهوك",
|
||||||
"edit_webhook": "تعديل الويبهوك",
|
"edit_webhook": "تعديل الويبهوك",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "عرض الصفحة العامة",
|
"view_public_page": "عرض الصفحة العامة",
|
||||||
"sign_out": "تسجيل الخروج",
|
"sign_out": "تسجيل الخروج",
|
||||||
"add_another": "أضف واحدًا آخر",
|
"add_another": "أضف واحدًا آخر",
|
||||||
|
"install_another": "تثبيت آخر",
|
||||||
"until": "حتى",
|
"until": "حتى",
|
||||||
"powered_by": "مدعوم بواسطة",
|
"powered_by": "مدعوم بواسطة",
|
||||||
"unavailable": "غير متاح",
|
"unavailable": "غير متاح",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "مربع الاختيار",
|
"checkbox": "مربع الاختيار",
|
||||||
"is_required": "مطلوب",
|
"is_required": "مطلوب",
|
||||||
"required": "مطلوب",
|
"required": "مطلوب",
|
||||||
|
"optional": "اختياري",
|
||||||
"input_type": "نوع الإدخال",
|
"input_type": "نوع الإدخال",
|
||||||
"rejected": "مرفوض",
|
"rejected": "مرفوض",
|
||||||
"unconfirmed": "غير مؤكد",
|
"unconfirmed": "غير مؤكد",
|
||||||
@@ -227,7 +228,9 @@
|
|||||||
"connect_your_calendar_instructions": "اربط التقويم لديك للتحقق تلقائيًا من الأوقات المشغولة والأحداث الجديدة أثناء جدولتها.",
|
"connect_your_calendar_instructions": "اربط التقويم لديك للتحقق تلقائيًا من الأوقات المشغولة والأحداث الجديدة أثناء جدولتها.",
|
||||||
"set_up_later": "الإعداد لاحقًا",
|
"set_up_later": "الإعداد لاحقًا",
|
||||||
"current_time": "الوقت الحالي",
|
"current_time": "الوقت الحالي",
|
||||||
|
"details": "التفاصيل",
|
||||||
"welcome": "مرحبًا",
|
"welcome": "مرحبًا",
|
||||||
|
"welcome_back": "أهلاً بك من جديد",
|
||||||
"welcome_to_calcom": "مرحبًا بك في Cal.com",
|
"welcome_to_calcom": "مرحبًا بك في Cal.com",
|
||||||
"welcome_instructions": "أخبرنا باسمك وبالمنطقة الزمنية التي توجد فيها. ستتمكن لاحقًا من تعديل هذا.",
|
"welcome_instructions": "أخبرنا باسمك وبالمنطقة الزمنية التي توجد فيها. ستتمكن لاحقًا من تعديل هذا.",
|
||||||
"connect_caldav": "الاتصال بخادم CalDav",
|
"connect_caldav": "الاتصال بخادم CalDav",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "متى",
|
"when": "متى",
|
||||||
"where": "أين",
|
"where": "أين",
|
||||||
"add_to_calendar": "إضافة إلى التقويم",
|
"add_to_calendar": "إضافة إلى التقويم",
|
||||||
|
"add_another_calendar": "إضافة رزنامة أخرى",
|
||||||
"other": "آخر",
|
"other": "آخر",
|
||||||
"emailed_you_and_attendees": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة للتقويم عبر البريد الإلكتروني تتضمن كل التفاصيل.",
|
"emailed_you_and_attendees": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة للتقويم عبر البريد الإلكتروني تتضمن كل التفاصيل.",
|
||||||
"emailed_you_and_attendees_recurring": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة تقويم عبر البريد الإلكتروني لأول هذه الأحداث المتكررة.",
|
"emailed_you_and_attendees_recurring": "لقد أرسلنا إليك وإلى الحضور الآخرين دعوة تقويم عبر البريد الإلكتروني لأول هذه الأحداث المتكررة.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "أدخل كلمة المرور الجديدة التي ترغب في تعيينها لحسابك.",
|
"enter_new_password": "أدخل كلمة المرور الجديدة التي ترغب في تعيينها لحسابك.",
|
||||||
"reset_password": "إعادة تعيين كلمة المرور",
|
"reset_password": "إعادة تعيين كلمة المرور",
|
||||||
"change_your_password": "تغيير كلمة المرور",
|
"change_your_password": "تغيير كلمة المرور",
|
||||||
|
"show_password": "عرض كلمة المرور",
|
||||||
|
"hide_password": "إخفاء كلمة المرور",
|
||||||
"try_again": "حاول مجددًا",
|
"try_again": "حاول مجددًا",
|
||||||
"request_is_expired": "انتهت صلاحية ذلك الطلب.",
|
"request_is_expired": "انتهت صلاحية ذلك الطلب.",
|
||||||
"reset_instructions": "أدخل عنوان البريد الإلكتروني المرتبط بحسابك وسنرسل إليك رابطًا لإعادة تعيين كلمة المرور.",
|
"reset_instructions": "أدخل عنوان البريد الإلكتروني المرتبط بحسابك وسنرسل إليك رابطًا لإعادة تعيين كلمة المرور.",
|
||||||
@@ -289,7 +295,7 @@
|
|||||||
"reschedule_instead": "بدلًا من ذلك، يمكنك إعادة جدولته.",
|
"reschedule_instead": "بدلًا من ذلك، يمكنك إعادة جدولته.",
|
||||||
"event_is_in_the_past": "الحدث في الماضي",
|
"event_is_in_the_past": "الحدث في الماضي",
|
||||||
"cancelling_event_recurring": "إن هذا الحدث أحد الأمثلة على حدث متكرر.",
|
"cancelling_event_recurring": "إن هذا الحدث أحد الأمثلة على حدث متكرر.",
|
||||||
"cancelling_all_recurring": "هذه هي الحالات المتبقية في الحدث المتكرر.",
|
"cancelling_all_recurring": "هذه هي كل الأمثلة المتبقية في الحدث المتكرر.",
|
||||||
"error_with_status_code_occured": "حدث خطأ برمز الحالة {{status}}.",
|
"error_with_status_code_occured": "حدث خطأ برمز الحالة {{status}}.",
|
||||||
"booking_already_cancelled": "تم إلغاء هذا الحجز بالفعل",
|
"booking_already_cancelled": "تم إلغاء هذا الحجز بالفعل",
|
||||||
"go_back_home": "العودة إلى الشاشة الرئيسية",
|
"go_back_home": "العودة إلى الشاشة الرئيسية",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "بمجرد أن يحجز شخص ما اجتماعًا متكررًا معك، سيظهر هنا.",
|
"recurring_bookings": "بمجرد أن يحجز شخص ما اجتماعًا متكررًا معك، سيظهر هنا.",
|
||||||
"past_bookings": "ستظهر هنا عمليات حجزك السابقة.",
|
"past_bookings": "ستظهر هنا عمليات حجزك السابقة.",
|
||||||
"cancelled_bookings": "ستظهر هنا عمليات حجزك التي تم إلغاؤها.",
|
"cancelled_bookings": "ستظهر هنا عمليات حجزك التي تم إلغاؤها.",
|
||||||
|
"unconfirmed_bookings": "ستظهر هنا كل حجوزات غير المؤكدة بعد.",
|
||||||
"on": "في",
|
"on": "في",
|
||||||
"and": "و",
|
"and": "و",
|
||||||
"calendar_shows_busy_between": "يظهر التقويم أنك مشغول بين",
|
"calendar_shows_busy_between": "يظهر التقويم أنك مشغول بين",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "تم إلغاء الحجز",
|
"booking_cancelled": "تم إلغاء الحجز",
|
||||||
"booking_rescheduled": "تمت إعادة جدولة الحجز",
|
"booking_rescheduled": "تمت إعادة جدولة الحجز",
|
||||||
"booking_created": "تم إنشاء الحجز",
|
"booking_created": "تم إنشاء الحجز",
|
||||||
|
"meeting_ended": "انتهى الاجتماع",
|
||||||
"form_submitted": "تم إرسال النموذج",
|
"form_submitted": "تم إرسال النموذج",
|
||||||
"event_triggers": "مشغلات الحدث",
|
"event_triggers": "مشغلات الحدث",
|
||||||
"subscriber_url": "عنوان URL للمشترك",
|
"subscriber_url": "عنوان URL للمشترك",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "لنقم بإنشاء المستخدم المسؤول الأول.",
|
"lets_create_first_administrator_user": "لنقم بإنشاء المستخدم المسؤول الأول.",
|
||||||
"new_member": "العضو الجديد",
|
"new_member": "العضو الجديد",
|
||||||
"invite": "دعوة",
|
"invite": "دعوة",
|
||||||
|
"add_team_members": "إضافة أعضاء الفريق",
|
||||||
|
"add_team_members_description": "قم بدعوة الآخرين للانضمام إلى فريقك",
|
||||||
|
"add_team_member": "إضافة عضو فريق",
|
||||||
"invite_new_member": "دعوة عضو جديد",
|
"invite_new_member": "دعوة عضو جديد",
|
||||||
"invite_new_team_member": "دعوة شخص ما إلى فريقك.",
|
"invite_new_team_member": "دعوة شخص ما إلى فريقك.",
|
||||||
"change_member_role": "تغيير دور العضو في الفريق",
|
"change_member_role": "تغيير دور العضو في الفريق",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "قم بإنشاء فريقك الأول ودعوة المستخدمين الآخرين للعمل معك.",
|
"create_first_team_and_invite_others": "قم بإنشاء فريقك الأول ودعوة المستخدمين الآخرين للعمل معك.",
|
||||||
"create_team_to_get_started": "قم بإنشاء فريق للبدء",
|
"create_team_to_get_started": "قم بإنشاء فريق للبدء",
|
||||||
"teams": "الفرق",
|
"teams": "الفرق",
|
||||||
|
"team": "فريق",
|
||||||
"team_billing": "الفوترة الخاصة بالفريق",
|
"team_billing": "الفوترة الخاصة بالفريق",
|
||||||
"upgrade_to_flexible_pro_title": "لقد قمنا بتغيير الفوترة الخاصة بالفرق",
|
"upgrade_to_flexible_pro_title": "لقد قمنا بتغيير الفوترة الخاصة بالفرق",
|
||||||
"upgrade_to_flexible_pro_message": "يوجد أعضاء في فريقك من دون مقاعد. قم بترقية خطة Pro خاصتك لتوفير المقاعد الناقصة.",
|
"upgrade_to_flexible_pro_message": "يوجد أعضاء في فريقك من دون مقاعد. قم بترقية خطة Pro خاصتك لتوفير المقاعد الناقصة.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "الفوترة",
|
"billing": "الفوترة",
|
||||||
"manage_your_billing_info": "قم بإدارة معلومات الفوترة لديك وإلغاء اشتراكك.",
|
"manage_your_billing_info": "قم بإدارة معلومات الفوترة لديك وإلغاء اشتراكك.",
|
||||||
"availability": "الأوقات المتاحة",
|
"availability": "الأوقات المتاحة",
|
||||||
|
"edit_availability": "تعديل التوفر",
|
||||||
"configure_availability": "اضبط الأوقات التي تكون متاحًا فيها للحجز.",
|
"configure_availability": "اضبط الأوقات التي تكون متاحًا فيها للحجز.",
|
||||||
|
"copy_times_to": "نسخ الأوقات إلى",
|
||||||
"change_weekly_schedule": "تغيير جدولك الأسبوعي",
|
"change_weekly_schedule": "تغيير جدولك الأسبوعي",
|
||||||
"logo": "الشعار",
|
"logo": "الشعار",
|
||||||
"error": "خطأ",
|
"error": "خطأ",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "الاسم الذي سيظهر في التقاويم",
|
"event_name_tooltip": "الاسم الذي سيظهر في التقاويم",
|
||||||
"meeting_with_user": "الاجتماع مع {ATTENDEE}",
|
"meeting_with_user": "الاجتماع مع {ATTENDEE}",
|
||||||
"additional_inputs": "مدخلات إضافية",
|
"additional_inputs": "مدخلات إضافية",
|
||||||
|
"additional_input_description": "يتطلب من المجدول إدخال مدخلات إضافية قبل تأكيد الحجز",
|
||||||
"label": "العلامة",
|
"label": "العلامة",
|
||||||
"placeholder": "العنصر النائب",
|
"placeholder": "العنصر النائب",
|
||||||
"type": "النوع",
|
"type": "النوع",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "تعطيل خاصية الضيوف",
|
"disable_guests": "تعطيل خاصية الضيوف",
|
||||||
"disable_guests_description": "قم بتعطيل إضافة مزيد من الضيوف أثناء الحجز.",
|
"disable_guests_description": "قم بتعطيل إضافة مزيد من الضيوف أثناء الحجز.",
|
||||||
"private_link": "إنشاء رابط خاص",
|
"private_link": "إنشاء رابط خاص",
|
||||||
|
"private_link_label": "رابط خاص",
|
||||||
|
"private_link_hint": "سيتم إعادة توليد الرابط الخاص بك بعد كل استخدام",
|
||||||
"copy_private_link": "نسخ الرابط الخاص",
|
"copy_private_link": "نسخ الرابط الخاص",
|
||||||
"private_link_description": "إنشاء عنوان URL خاص لمشاركته دون الكشف عن اسم المستخدم الخاص بك في Cal",
|
"private_link_description": "إنشاء عنوان URL خاص لمشاركته دون الكشف عن اسم المستخدم الخاص بك في Cal",
|
||||||
"invitees_can_schedule": "يمكن للمدعوين الجدولة",
|
"invitees_can_schedule": "يمكن للمدعوين الجدولة",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "هل تريد بالتأكيد حذف حسابك على Cal.com؟ أي شخص شاركت رابط حسابك معه لن يستطيع بعد الآن الحجز باستخدامه، وستفقد أي تفضيلات حفظتها.",
|
"delete_account_confirmation_message": "هل تريد بالتأكيد حذف حسابك على Cal.com؟ أي شخص شاركت رابط حسابك معه لن يستطيع بعد الآن الحجز باستخدامه، وستفقد أي تفضيلات حفظتها.",
|
||||||
"integrations": "التكاملات",
|
"integrations": "التكاملات",
|
||||||
"apps": "التطبيقات",
|
"apps": "التطبيقات",
|
||||||
|
"category_apps": "تطبيقات {{category}}",
|
||||||
"app_store": "متجر التطبيقات",
|
"app_store": "متجر التطبيقات",
|
||||||
"app_store_description": "الربط بين الناس، والتكنولوجيا، ومكان العمل.",
|
"app_store_description": "الربط بين الناس، والتكنولوجيا، ومكان العمل.",
|
||||||
"settings": "الإعدادات",
|
"settings": "الإعدادات",
|
||||||
"event_type_moved_successfully": "تم نقل نوع الحدث بنجاح",
|
"event_type_moved_successfully": "تم نقل نوع الحدث بنجاح",
|
||||||
|
"next_step_text": "الخطوة التالية",
|
||||||
"next_step": "تخطي الخطوة",
|
"next_step": "تخطي الخطوة",
|
||||||
"prev_step": "الخطوة السابقة",
|
"prev_step": "الخطوة السابقة",
|
||||||
|
"install": "تثبيت",
|
||||||
"installed": "تم التثبيت",
|
"installed": "تم التثبيت",
|
||||||
"active_install_one": "{{count}} تثبيت نشط",
|
"active_install_one": "{{count}} تثبيت نشط",
|
||||||
"active_install_other": "{{count}} تثبيت نشط",
|
"active_install_other": "{{count}} تثبيت نشط",
|
||||||
"globally_install": "تم تثبيته حول العالم",
|
"globally_install": "تم تثبيته حول العالم",
|
||||||
|
"app_successfully_installed": "تم تثبيت التطبيق بنجاح",
|
||||||
|
"app_could_not_be_installed": "تعذر تثبيت التطبيق",
|
||||||
"disconnect": "فصل",
|
"disconnect": "فصل",
|
||||||
"embed_your_calendar": "تضمين تقويمك في صفحة الويب لديك",
|
"embed_your_calendar": "تضمين تقويمك في صفحة الويب لديك",
|
||||||
"connect_your_favourite_apps": "الربط مع تطبيقاتك المفضلة.",
|
"connect_your_favourite_apps": "الربط مع تطبيقاتك المفضلة.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "ربط رزنامة إضافية",
|
"connect_additional_calendar": "ربط رزنامة إضافية",
|
||||||
"conferencing": "المؤتمرات عبر الفيديو",
|
"conferencing": "المؤتمرات عبر الفيديو",
|
||||||
"calendar": "التقويم",
|
"calendar": "التقويم",
|
||||||
|
"payments": "الدفعات",
|
||||||
"not_installed": "لم يتم التثبيت",
|
"not_installed": "لم يتم التثبيت",
|
||||||
"error_password_mismatch": "كلمات المرور غير متطابقة.",
|
"error_password_mismatch": "كلمات المرور غير متطابقة.",
|
||||||
"error_required_field": "هذا الحقل مطلوب.",
|
"error_required_field": "هذا الحقل مطلوب.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "الاستيراد من",
|
"import_from": "الاستيراد من",
|
||||||
"access_token": "Access token",
|
"access_token": "Access token",
|
||||||
"visit_roadmap": "المخطط",
|
"visit_roadmap": "المخطط",
|
||||||
|
"featured_categories": "الفئات البارزة",
|
||||||
"popular_categories": "الفئات الشائعة",
|
"popular_categories": "الفئات الشائعة",
|
||||||
|
"number_apps_one": "تطبيق {{count}}",
|
||||||
|
"number_apps_other": "تطبيقات {{count}}",
|
||||||
"trending_apps": "التطبيقات الرائجة",
|
"trending_apps": "التطبيقات الرائجة",
|
||||||
|
"explore_apps": "تطبيقات {{category}}",
|
||||||
"installed_apps": "التطبيقات المثبتة",
|
"installed_apps": "التطبيقات المثبتة",
|
||||||
|
"no_category_apps": "لا تطبيقات {{category}}",
|
||||||
|
"no_category_apps_description_calendar": "أضف تطبيق رزنامة للتحقق من أي تضارب لمنع أي حجوزات مزدوجة",
|
||||||
|
"no_category_apps_description_conferencing": "حاول إضافة تطبيق مؤتمرات لدمج مكالمة الفيديو مع عملائك",
|
||||||
|
"no_category_apps_description_payment": "أضف تطبيق دفع لتسهيل التعاملات المالية بينك وبين عملائك",
|
||||||
|
"no_category_apps_description_other": "أضف أي نوع آخر من التطبيقات للقيام بأي شيء",
|
||||||
|
"installed_app_calendar_description": "اضبط الرزنامة (الرزنامات) للتحقق من أي تضارب لمنع الحجوزات المزدوجة.",
|
||||||
|
"installed_app_conferencing_description": "أضف تطبيقات مؤتمرات الفيديو المفضلة لديك لاجتماعاتك",
|
||||||
|
"installed_app_payment_description": "قم بإعداد أي خدمات معالجة دفع تود استخدامها عند طلب النقود من العملاء.",
|
||||||
|
"installed_app_other_description": "جميع تطبيقاتك المثبتة من الفئات الأخرى.",
|
||||||
"empty_installed_apps_headline": "لم يتم تثبيت أي تطبيق",
|
"empty_installed_apps_headline": "لم يتم تثبيت أي تطبيق",
|
||||||
"empty_installed_apps_description": "تعطيك التطبيقات القدرة على تعزيز سير عملك وتحسين الجدولة في حياتك بشدة.",
|
"empty_installed_apps_description": "تعطيك التطبيقات القدرة على تعزيز سير عملك وتحسين الجدولة في حياتك بشدة.",
|
||||||
"empty_installed_apps_button": "استكشف متجر التطبيقات (App Store)",
|
"empty_installed_apps_button": "استكشف متجر التطبيقات (App Store)",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "إزالة",
|
"remove": "إزالة",
|
||||||
"add": "إضافة",
|
"add": "إضافة",
|
||||||
"installed_one": "تم التثبيت",
|
"installed_one": "تم التثبيت",
|
||||||
|
"installed_other": "{{count}} مثبت",
|
||||||
"verify_wallet": "تأكيد المحفظة",
|
"verify_wallet": "تأكيد المحفظة",
|
||||||
"connect_metamask": "توصيل Metamask",
|
"connect_metamask": "توصيل Metamask",
|
||||||
"create_events_on": "إنشاء أحداث في:",
|
"create_events_on": "إنشاء أحداث في:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "تعيين إلى الافتراضي",
|
"set_to_default": "تعيين إلى الافتراضي",
|
||||||
"new_schedule_btn": "جدول جديد",
|
"new_schedule_btn": "جدول جديد",
|
||||||
"add_new_schedule": "إضافة جدول جديد",
|
"add_new_schedule": "إضافة جدول جديد",
|
||||||
|
"add_new_calendar": "إضافة رزنامة جديدة",
|
||||||
|
"set_calendar": "حدد أين سيتم إضافة الأحداث الجديدة عند الحجز.",
|
||||||
"delete_schedule": "حذف الجدول",
|
"delete_schedule": "حذف الجدول",
|
||||||
"schedule_created_successfully": "تم إنشاء جدول {{scheduleName}} بنجاح",
|
"schedule_created_successfully": "تم إنشاء جدول {{scheduleName}} بنجاح",
|
||||||
"availability_updated_successfully": "تم تحديث الأوقات المتاحة بنجاح",
|
"availability_updated_successfully": "تم تحديث الأوقات المتاحة بنجاح",
|
||||||
@@ -798,7 +837,7 @@
|
|||||||
"redirect_success_booking": "إعادة التوجيه عند الحجز ",
|
"redirect_success_booking": "إعادة التوجيه عند الحجز ",
|
||||||
"you_are_being_redirected": "ستتم إعادة توجيهك إلى {{ url }} خلال $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "ستتم إعادة توجيهك إلى {{ url }} خلال $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "لاستخدام هذه الميزة، تحتاج إلى الترقية إلى حساب Pro.",
|
"redirect_url_description": "إعادة التوجيه إلى عنوان URL مخصص بعد الحجز بنجاح",
|
||||||
"duplicate": "تكرار",
|
"duplicate": "تكرار",
|
||||||
"offer_seats": "عرض مقاعد",
|
"offer_seats": "عرض مقاعد",
|
||||||
"offer_seats_description": "عرض مقاعد للحجز (هذا يعطل الضيوف والتسجيل في الحجز)",
|
"offer_seats_description": "عرض مقاعد للحجز (هذا يعطل الضيوف والتسجيل في الحجز)",
|
||||||
@@ -877,7 +916,7 @@
|
|||||||
"choose_ways_put_cal_site": "اختر واحدة من الطرق التالية لوضع Cal على موقعك الإلكتروني.",
|
"choose_ways_put_cal_site": "اختر واحدة من الطرق التالية لوضع Cal على موقعك الإلكتروني.",
|
||||||
"setting_up_zapier": "إعداد دمج Zapier الخاص بك",
|
"setting_up_zapier": "إعداد دمج Zapier الخاص بك",
|
||||||
"generate_api_key": "إنشاء مفتاح API",
|
"generate_api_key": "إنشاء مفتاح API",
|
||||||
"generate_api_key_description": "إنشاء مفتاح API لاستخدامه مع Cal.com في",
|
"generate_api_key_description": "إنشاء مفتاح API لاستخدامه مع Cal.com على",
|
||||||
"your_unique_api_key": "مفتاح API الفريد الخاص بك",
|
"your_unique_api_key": "مفتاح API الفريد الخاص بك",
|
||||||
"copy_safe_api_key": "انسخ مفتاح API هذا واحفظه في مكان آمن. إذا فقدت هذا المفتاح، يتوجب عليك إنشاء مفتاح جديد.",
|
"copy_safe_api_key": "انسخ مفتاح API هذا واحفظه في مكان آمن. إذا فقدت هذا المفتاح، يتوجب عليك إنشاء مفتاح جديد.",
|
||||||
"zapier_setup_instructions": "<0>سجل الدخول إلى حساب Zapier الخاص بك وأنشئ Zap جديد.</0><1>حدد Cal.com كتطبيق Trigger لديك. اختر أيضًا حدث Trigger.</1><2>اختر حسابك ثم أدخل مفتاح API الفريد الخاص بك.</2><3>اختبر Trigger الخاص بك.</3><4>أنت جاهز!</4>",
|
"zapier_setup_instructions": "<0>سجل الدخول إلى حساب Zapier الخاص بك وأنشئ Zap جديد.</0><1>حدد Cal.com كتطبيق Trigger لديك. اختر أيضًا حدث Trigger.</1><2>اختر حسابك ثم أدخل مفتاح API الفريد الخاص بك.</2><3>اختبر Trigger الخاص بك.</3><4>أنت جاهز!</4>",
|
||||||
@@ -936,6 +975,7 @@
|
|||||||
"workflows": "سير العمل",
|
"workflows": "سير العمل",
|
||||||
"new_workflow_btn": "سير عمل جديد",
|
"new_workflow_btn": "سير عمل جديد",
|
||||||
"add_new_workflow": "إضافة سير عمل جديد",
|
"add_new_workflow": "إضافة سير عمل جديد",
|
||||||
|
"reschedule_event_trigger": "متى يتم إعادة جدولة الحدث",
|
||||||
"trigger": "مشغل",
|
"trigger": "مشغل",
|
||||||
"triggers": "مشغلين",
|
"triggers": "مشغلين",
|
||||||
"action": "إجراء",
|
"action": "إجراء",
|
||||||
@@ -963,10 +1003,13 @@
|
|||||||
"change_username_standard_to_premium": "عند التغيير من اسم مستخدم قياسي إلى اسم مستخدم مميز، سيتم نقلك إلى الدفع للترقية.",
|
"change_username_standard_to_premium": "عند التغيير من اسم مستخدم قياسي إلى اسم مستخدم مميز، سيتم نقلك إلى الدفع للترقية.",
|
||||||
"change_username_premium_to_standard": "عند التغيير من اسم مستخدم مميز إلى اسم مستخدم قياسي، سيتم نقلك إلى الدفع لخفض المستوى.",
|
"change_username_premium_to_standard": "عند التغيير من اسم مستخدم مميز إلى اسم مستخدم قياسي، سيتم نقلك إلى الدفع لخفض المستوى.",
|
||||||
"go_to_stripe_billing": "الذهاب إلى الفوترة",
|
"go_to_stripe_billing": "الذهاب إلى الفوترة",
|
||||||
|
"stripe_description": "يتطلب الدفع للحجز (0.5% + 0.10 يورو عمولة لكل معاملة)",
|
||||||
"trial_expired": "انتهت صلاحية الفترة التجريبية الخاصة بك",
|
"trial_expired": "انتهت صلاحية الفترة التجريبية الخاصة بك",
|
||||||
"remove_app": "إزالة التطبيق",
|
"remove_app": "إزالة التطبيق",
|
||||||
"yes_remove_app": "نعم، قم بإزالة التطبيق",
|
"yes_remove_app": "نعم، قم بإزالة التطبيق",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "هل أنت متأكد من أنك تريد إزالة هذا التطبيق؟",
|
"are_you_sure_you_want_to_remove_this_app": "هل أنت متأكد من أنك تريد إزالة هذا التطبيق؟",
|
||||||
|
"app_removed_successfully": "تمت إزالة التطبيق بنجاح",
|
||||||
|
"error_removing_app": "خطأ في إزالة التطبيق",
|
||||||
"web_conference": "مؤتمر عبر الإنترنت",
|
"web_conference": "مؤتمر عبر الإنترنت",
|
||||||
"number_for_sms_reminders": "رقم الهاتف (لتذكير الرسائل القصيرة)",
|
"number_for_sms_reminders": "رقم الهاتف (لتذكير الرسائل القصيرة)",
|
||||||
"requires_confirmation": "يتطلب التأكيد",
|
"requires_confirmation": "يتطلب التأكيد",
|
||||||
@@ -1022,20 +1065,235 @@
|
|||||||
"navigate": "تنقّل",
|
"navigate": "تنقّل",
|
||||||
"open": "فتح",
|
"open": "فتح",
|
||||||
"close": "إغلاق",
|
"close": "إغلاق",
|
||||||
"embed": "مُضمَن",
|
"team_feature_teams": "هذه ميزة في Team. قم بالترقية إلى Team لرؤية توفر فريقك.",
|
||||||
|
"team_feature_workflows": "هذه ميزة في Team. قم بالترقية إلى Team لأتمتة إشعارات الحدث والتذكير مع سير العمل.",
|
||||||
|
"show_eventtype_on_profile": "إظهار على الملف الشخصي",
|
||||||
|
"embed": "تضمين",
|
||||||
"new_username": "اسم مستخدم جديد",
|
"new_username": "اسم مستخدم جديد",
|
||||||
"current_username": "اسم المستخدم الحالي",
|
"current_username": "اسم المستخدم الحالي",
|
||||||
"example_1": "مثال 1",
|
"example_1": "مثال 1",
|
||||||
"example_2": "مثال 2",
|
"example_2": "مثال 2",
|
||||||
|
"additional_input_label": "تسمية الإدخال الاضافي",
|
||||||
"company_size": "حجم الشركة",
|
"company_size": "حجم الشركة",
|
||||||
"what_help_needed": "ما الذي تحتاج إلى مساعدة بشأنه؟",
|
"what_help_needed": "ما الذي تحتاج إلى مساعدة بشأنه؟",
|
||||||
"variable_format": "تنسيق المتغير",
|
"variable_format": "تنسيق المتغير",
|
||||||
|
"webhook_subscriber_url_reserved": "رابط مشترك Webhook معرّف بالفعل",
|
||||||
"custom_input_as_variable_info": "تجاهل جميع الأحرف الخاصة من تسمية الإدخال الإضافي (استخدم الأحرف والأرقام فقط)، واستخدم الحروف الكبيرة لجميع الأحرف واستبدل المساحات البيضاء بالشرط.",
|
"custom_input_as_variable_info": "تجاهل جميع الأحرف الخاصة من تسمية الإدخال الإضافي (استخدم الأحرف والأرقام فقط)، واستخدم الحروف الكبيرة لجميع الأحرف واستبدل المساحات البيضاء بالشرط.",
|
||||||
"using_additional_inputs_as_variables": "كيف أستخدم مدخلات إضافية كمتغيرات؟",
|
"using_additional_inputs_as_variables": "كيف أستخدم مدخلات إضافية كمتغيرات؟",
|
||||||
"download_desktop_app": "تحميل تطبيق سطح المكتب",
|
"download_desktop_app": "تحميل تطبيق سطح المكتب",
|
||||||
"set_ping_link": "تعيين رابط Ping",
|
"set_ping_link": "تعيين رابط Ping",
|
||||||
|
"rate_limit_exceeded": "تم تجاوز حد السعر",
|
||||||
|
"when_something_happens": "عندما يحدث شيء ما",
|
||||||
|
"action_is_performed": "يتم تنفيذ إجراء",
|
||||||
|
"test_action": "إجراء الاختبار",
|
||||||
|
"notification_sent": "تم إرسال الإشعار",
|
||||||
|
"no_input": "لا مدخلات",
|
||||||
|
"test_workflow_action": "اختبار إجراء سير العمل",
|
||||||
|
"send_sms": "إرسال رسالة نصية",
|
||||||
|
"send_sms_to_number": "هل أنت متأكد من رغبتك في إرسال رسالة قصيرة إلى {{number}}؟",
|
||||||
"missing_connected_calendar": "لا يوجد تقويم افتراضي متصل",
|
"missing_connected_calendar": "لا يوجد تقويم افتراضي متصل",
|
||||||
|
"connect_your_calendar_and_link": "يمكنك ربط رزنامتك من <1>هنا</1>.",
|
||||||
|
"default_calendar_selected": "الرزنامة الافتراضية",
|
||||||
|
"hide_from_profile": "إخفاء من الملف الشخصي",
|
||||||
|
"event_setup_tab_title": "إعداد الحدث",
|
||||||
|
"event_limit_tab_title": "الحدود",
|
||||||
|
"event_limit_tab_description": "ما تواتر مرات الحجز",
|
||||||
|
"event_advanced_tab_description": "إعدادات الرزنامة والمزيد...",
|
||||||
|
"event_advanced_tab_title": "متقدم",
|
||||||
|
"select_which_cal": "اختر أي رزنامة تريد إضافة الحجز إليها",
|
||||||
|
"custom_event_name": "اسم حدث مخصص",
|
||||||
|
"custom_event_name_description": "إنشاء أسماء أحداث مخصصة لعرضها في حدث الرزنامة",
|
||||||
|
"2fa_required": "ثمة حاجة إلى المصادقة الثنائية",
|
||||||
|
"incorrect_2fa": "رمز المصادقة الثنائية غير صحيح",
|
||||||
|
"which_event_type_apply": "ما نوع الحدث الذي سينطبق عليه هذا؟",
|
||||||
|
"no_workflows_description": "تعمل سير العمل على تمكين أتمتة إرسال الإشعارات والتذكيرات التي تمكنك من بناء عمليات حول الأحداث الخاصة بك.",
|
||||||
|
"create_workflow": "إنشاء سير عمل",
|
||||||
|
"do_this": "افعل هذا",
|
||||||
|
"turn_off": "إيقاف التشغيل",
|
||||||
|
"settings_updated_successfully": "تم تحديث الإعدادات بنجاح",
|
||||||
|
"error_updating_settings": "خطأ في تحديث الإعدادات",
|
||||||
|
"personal_cal_url": "عنوان Cal URL الخاص بي",
|
||||||
|
"bio_hint": "اكتب بضع جمل عن نفسك، والتي ستظهر على صفحة عنوان Url الشخصية لديك.",
|
||||||
|
"delete_account_modal_title": "حذف الحساب",
|
||||||
|
"confirm_delete_account_modal": "هل أنت متأكد من أنك تريد حذف حساب Cal.com الخاص بك؟",
|
||||||
|
"delete_my_account": "حذف حسابي",
|
||||||
|
"start_of_week": "بداية الأسبوع",
|
||||||
|
"select_calendars": "حدد الرزنامات التي تريد التحقق منها بحثًا عن تضاربات لمنع الحجوزات المزدوجة.",
|
||||||
|
"check_for_conflicts": "التحقق من وجود تضاربات",
|
||||||
|
"adding_events_to": "إضافة أحداث إلى",
|
||||||
|
"follow_system_preferences": "اتبع تفضيلات النظام",
|
||||||
|
"custom_brand_colors": "ألوان العلامة التجارية المخصصة",
|
||||||
|
"customize_your_brand_colors": "تخصيص لون العلامة التجارية الخاصة بك في صفحة الحجز.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "إزالة أي علامات تجارية ذات صلة بـCal ، أي 'تم تشغيلها من قبل Cal.'",
|
||||||
|
"profile_picture": "صورة الملف الشخصي",
|
||||||
|
"upload": "تحميل",
|
||||||
|
"web3": "الويب 3",
|
||||||
|
"rainbow_token_gated": "هذا النوع من الأحداث موجود وراء بوابة رمز.",
|
||||||
|
"rainbow_connect_wallet_gate": "قم بتوصيل محفظتك إذا كنت تملك <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "لا تحتوي محفظتك المتصلة على ما يكفي من 1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "قم بتوقيع طلب الرسالة على محفظتك.",
|
||||||
|
"rainbow_signature_error": "خطأ في طلب التوقيع من محفظتك.",
|
||||||
|
"token_address": "عنوان الرمز المميز",
|
||||||
|
"blockchain": "البلوكشين",
|
||||||
|
"old_password": "كلمة مرور قديمة",
|
||||||
|
"secure_password": "كلمة المرور الجديدة الآمنة كلياً",
|
||||||
|
"error_updating_password": "خطأ في تحديث كلمة المرور",
|
||||||
|
"two_factor_auth": "المصادقة الثنائية",
|
||||||
|
"recurring_event_tab_description": "إعداد جدول تكرار",
|
||||||
|
"today": "اليوم",
|
||||||
|
"appearance": "المظهر",
|
||||||
|
"appearance_subtitle": "إدارة إعدادات مظهر الحجز الخاص بك",
|
||||||
|
"my_account": "حسابي",
|
||||||
|
"general": "عام",
|
||||||
|
"calendars": "الرزنامات",
|
||||||
|
"2fa_auth": "المصادقة الثنائية",
|
||||||
|
"invoices": "الفواتير",
|
||||||
|
"embeds": "التضمينات",
|
||||||
|
"impersonation": "التقمّص",
|
||||||
|
"users": "المستخدمون",
|
||||||
|
"profile_description": "إدارة الإعدادات لملفك الرزنامة الشخصي لديك",
|
||||||
|
"general_description": "إدارة الإعدادات للغة والمنطقة الزمنية الخاصة بك",
|
||||||
|
"calendars_description": "اضبط كيفية تفاعل أنواع الأحداث لديك مع رزناماتك",
|
||||||
|
"appearance_description": "إدارة إعدادات مظهر الحجز الخاص بك",
|
||||||
|
"conferencing_description": "إدارة تطبيقات مؤتمرات الفيديو لديك لاجتماعاتك",
|
||||||
|
"password_description": "إدارة إعدادات كلمات مرور حسابك",
|
||||||
|
"2fa_description": "إدارة إعدادات كلمات مرور حسابك",
|
||||||
|
"we_just_need_basic_info": "نحتاج فقط إلى بعض المعلومات الأساسية لإعداد ملفك الشخصي.",
|
||||||
|
"skip": "تخطي",
|
||||||
|
"do_this_later": "القيام بهذا لاحقاً",
|
||||||
|
"set_availability_getting_started_subtitle_1": "تحديد الفترات الزمنية التي أنت فيها متاح",
|
||||||
|
"set_availability_getting_started_subtitle_2": "يمكنك تخصيص كل هذا في وقت لاحق في صفحة التوفر.",
|
||||||
|
"connect_calendars_from_app_store": "يمكنك إضافة المزيد من الرزنامات من متجر التطبيقات",
|
||||||
|
"connect_conference_apps": "ربط تطبيقات المؤتمرات",
|
||||||
|
"connect_calendar_apps": "ربط تطبيقات الرزنامة",
|
||||||
|
"connect_payment_apps": "ربط تطبيقات الدفع",
|
||||||
|
"connect_other_apps": "ربط تطبيقات أخرى",
|
||||||
|
"current_step_of_total": "الخطوة {{currentStep}} من {{maxSteps}}",
|
||||||
|
"add_variable": "إضافة متغير",
|
||||||
|
"custom_phone_number": "رقم هاتف مخصص",
|
||||||
|
"message_template": "نموذج رسالة",
|
||||||
|
"email_subject": "موضوع الرسالة الإلكترونية",
|
||||||
|
"add_dynamic_variables": "أضف متغيرات نص ديناميكية",
|
||||||
|
"event_name_info": "اسم نوع الحدث",
|
||||||
|
"event_date_info": "تاريخ الحدث",
|
||||||
|
"event_time_info": "وقت بدء الحدث",
|
||||||
|
"location_info": "موقع الحدث",
|
||||||
"organizer_name_info": "اسمك",
|
"organizer_name_info": "اسمك",
|
||||||
|
"additional_notes_info": "ملاحظات إضافية للحجز",
|
||||||
|
"attendee_name_info": "اسم الشخص صاحب الحجز",
|
||||||
|
"to": "إلى",
|
||||||
|
"attendee_required_enter_number": "سيتطلب هذا من الحضور إدخال رقم هاتف عند الحجز",
|
||||||
|
"workflow_turned_on_successfully": "تم تحديث سير العمل {{workflowName}} بنجاح {{offOn}}",
|
||||||
|
"download_responses": "تحميل الردود",
|
||||||
|
"create_your_first_form": "إنشاء أول استمارة",
|
||||||
|
"create_your_first_form_description": "يمكنك من خلال استمارات التوجيه طرح أسئلة التأهيل والتوجيه إلى الشخص/نوع الحدث المناسب.",
|
||||||
|
"create_your_first_webhook": "إنشاء أول Webhook",
|
||||||
|
"create_your_first_webhook_description": "يمكنك باستخدام Webhooks تلقي بيانات الاجتماع في الوقت الفعلي عندما يحدث شيء ما في Cal.com.",
|
||||||
|
"for_a_maximum_of": "كحد أقصى لـ",
|
||||||
|
"event_one": "حدث",
|
||||||
|
"event_other": "أحداث",
|
||||||
|
"profile_team_description": "إدارة إعدادات الملف الشخصي لفريقك",
|
||||||
|
"members_team_description": "المستخدمين الذين هم في المجموعة",
|
||||||
|
"team_url": "عنوان URL للفريق",
|
||||||
|
"delete_team": "حذف الفريق",
|
||||||
|
"team_members": "أعضاء الفريق",
|
||||||
|
"more": "المزيد",
|
||||||
|
"more_page_footer": "نعتبر تطبيق الهاتف المحمول امتداداً لتطبيق الويب، لكن يرجعى العودة لتطبيق الويب إذا كنت تقوم بأي إجراءات معقدة.",
|
||||||
|
"workflow_example_1": "إرسال رسائل نصية للحضور للتذكير قبل 24 ساعة من بدء الحدث",
|
||||||
|
"workflow_example_2": "إرسال رسالة نصية مخصصة عند إعادة جدولة الحدث للحضور",
|
||||||
|
"workflow_example_3": "إرسال بريد إلكتروني مخصص عندما يتم حجز حدث جديد للاستضافة",
|
||||||
|
"workflow_example_4": "إرسال رسائل نصية للحضور للتذكير قبل 1 ساعة من بدء الحدث",
|
||||||
|
"workflow_example_5": "إرسال رسالة نصية مخصصة عند إعادة جدولة الحدث للحضور",
|
||||||
|
"workflow_example_6": "إرسال بريد إلكتروني مخصص عندما يتم حجز حدث جديد للاستضافة",
|
||||||
|
"welcome_to_cal_header": "مرحبًا بك في Cal.com!",
|
||||||
|
"edit_form_later_subtitle": "سوف تكون قادراً على تعديل هذا لاحقاً.",
|
||||||
|
"connect_calendar_later": "سأقوم بتوصيل التقويم في وقت لاحق",
|
||||||
|
"set_my_availability_later": "سأحدد متى أكون متوفراً لاحقاً",
|
||||||
|
"problem_saving_user_profile": "حدثت مشكلة أثناء حفظ بياناتك. الرجاء المحاولة من جديد أو التواصل مع دعم العملاء.",
|
||||||
|
"purchase_missing_seats": "شراء المقاعد الناقصة",
|
||||||
|
"slot_length": "طول الفتحة",
|
||||||
|
"booking_appearance": "مظهر الحجز",
|
||||||
|
"appearance_team_description": "إدارة إعدادات مظهر الحجز الخاص بك",
|
||||||
|
"only_owner_change": "يمكن فقط لمالك هذا الفريق إجراء تغييرات على حجز الفريق ",
|
||||||
|
"team_disable_cal_branding_description": "إزالة أي علامات تجارية ذات صلة بـCal ، أي 'تم تشغيلها من قبل Cal'",
|
||||||
|
"invited_by_team": "دعاك {{teamName}} للانضمام إلى فريقهم كـ{{role}}",
|
||||||
|
"token_invalid_expired": "الرمز المميز إما غير صالح أو انتهت صلاحيته.",
|
||||||
|
"exchange_add": "الربط مع Microsoft Exchange",
|
||||||
|
"exchange_authentication": "طريقة المصادقة",
|
||||||
|
"exchange_authentication_standard": "المصادقة الأساسية",
|
||||||
|
"exchange_authentication_ntlm": "مصادقة NTLM",
|
||||||
|
"exchange_compression": "ضغط وفق Gzip",
|
||||||
|
"routing_forms_description": "يمكنك هنا رؤية جميع النماذج والمسارات التي أنشأتها.",
|
||||||
|
"add_new_form": "إضافة استمارة جديدة",
|
||||||
|
"form_description": "إنشاء استمارتك لتوجيه طالب حجز",
|
||||||
|
"copy_link_to_form": "نسخ رابط إلى الاستمارة",
|
||||||
|
"theme": "السمة",
|
||||||
|
"theme_applies_note": "ينطبق هذا فقط على صفحات الحجز العامة الخاصة بك",
|
||||||
"theme_light": "فاتح",
|
"theme_light": "فاتح",
|
||||||
"theme_dark": "داكن"
|
"theme_dark": "داكن",
|
||||||
|
"theme_system": "النظام الافتراضي",
|
||||||
|
"add_a_team": "إضافة فريق",
|
||||||
|
"saml_config": "إعدادات SAML",
|
||||||
|
"add_webhook_description": "تلقي بيانات الاجتماع في الوقت الحقيقي حالما يحدث شيء ما في Cal.com",
|
||||||
|
"triggers_when": "المشغلات عندما",
|
||||||
|
"test_webhook": "الرجاء إجراء اختبار ping قبل الإنشاء.",
|
||||||
|
"enable_webhook": "تمكين Webhook",
|
||||||
|
"add_webhook": "إضافة Webhook",
|
||||||
|
"webhook_edited_successfully": "تم حفظ Webhook",
|
||||||
|
"webhooks_description": "تلقي بيانات الاجتماع في الوقت الحقيقي عندما يحدث شيء ما في Cal.com",
|
||||||
|
"api_keys_description": "إنشاء مفاتيح API لاستخدامها للوصول إلى حسابك الخاص",
|
||||||
|
"new_api_key": "مفتاح API جديد",
|
||||||
|
"active": "نشط",
|
||||||
|
"api_key_updated": "تم تحديث اسم مفتاح API",
|
||||||
|
"api_key_update_failed": "خطأ في تحديث اسم مفتاح API",
|
||||||
|
"embeds_title": "تضمين HTML iframe",
|
||||||
|
"embeds_description": "تضمين جميع أنواع الأحداث لديك على موقعك على الإنترنت",
|
||||||
|
"create_first_api_key": "إنشاء أول مفتاح API لك",
|
||||||
|
"create_first_api_key_description": "تسمح مفاتيح API بتواصل التطبيقات الأخرى مع Cal.com",
|
||||||
|
"back_to_signin": "العودة لتسجيل الدخول",
|
||||||
|
"reset_link_sent": "تم إرسال رابط إعادة الضبط",
|
||||||
|
"password_reset_email": "ثمة بريد إلكتروني في طريقه إلى {{email}} مع تعليمات لإعادة تعيين كلمة المرور الخاصة بك.",
|
||||||
|
"password_reset_leading": "إذا لم تتلقَ رسالة إلكترونية قريباُ، تحقق من أن عنوان البريد الإلكتروني الذي أدخلته صحيح، وتحقق من مجلد البريد الطفيلي لديك، ثم تواصل مع قسم الدعم إذا استمرت المشكلة.",
|
||||||
|
"password_updated": "تم تحديث كلمة المرور!",
|
||||||
|
"pending_payment": "في انتظار الدفع",
|
||||||
|
"confirmation_page_rainbow": "رمز بوابة الحدث الخاص بك مع الرموز أو NFTs على Ethereum وPolygon وغيرها.",
|
||||||
|
"not_on_cal": "ليس على Cal.com",
|
||||||
|
"no_calendar_installed": "لا يوجد رزنامة مثبتة",
|
||||||
|
"no_calendar_installed_description": "لم تقم بعد بالاتصال بأي من التقويمات الخاصة بك",
|
||||||
|
"add_a_calendar": "إضافة رزنامة",
|
||||||
|
"change_email_hint": "قد تحتاج إلى تسجيل الخروج والعودة مجددًا لرؤية التغييرات التي تم تنفيذها",
|
||||||
|
"confirm_password_change_email": "الرجاء تأكيد كلمة المرور الخاصة بك قبل تغيير عنوان بريدك الإلكتروني",
|
||||||
|
"seats": "مقاعد",
|
||||||
|
"every_app_published": "كل تطبيق منشور على متجر تطبيقات Cal.com هو مصدر مفتوح ويتم اختباره بشكل شامل عن طريق مراجعات الأقران. لا يدعم Cal.com أو يصادق على هذه التطبيقات ما لم يتم نشرها بواسطة Cal.com. إذا واجهت محتوى أو سلوك غير مناسب يرجى الإبلاغ عن ذلك.",
|
||||||
|
"report_app": "الإبلاغ عن التطبيق",
|
||||||
|
"team_name_required": "اسم الفريق مطلوب",
|
||||||
|
"how_additional_inputs_as_variables": "كيفية استخدام مدخلات إضافية كمتغيرات",
|
||||||
|
"format": "التنسيق",
|
||||||
|
"uppercase_for_letters": "استخدام الحروف الكبيرة لجميع الأحرف",
|
||||||
|
"replace_whitespaces_underscores": "استبدال المساحات البيضاء بالشرطات السفلية",
|
||||||
|
"manage_billing": "إدارة الفواتير",
|
||||||
|
"manage_billing_description": "إدارة كل الأشياء المفوترة",
|
||||||
|
"billing_freeplan_title": "أنت حاليًا على الخطة المجانية",
|
||||||
|
"billing_freeplan_description": "نحن نعمل بشكل أفضل ضمن فرق. وسّع سير عملك مع أحداث الذهاب والإياب والأحداث الجماعية و صنع نماذج مسارات متقدمة",
|
||||||
|
"billing_freeplan_cta": "جرب الآن",
|
||||||
|
"billing_manage_details_title": "عرض تفاصيل الفوترة وإدارتها",
|
||||||
|
"billing_manage_details_description": "اعرض تفاصيل الفوترة وعدّلها، بالإضافة إلى إمكانية إلغاء الاشتراك.",
|
||||||
|
"billing_portal": "بوابة الفواتير",
|
||||||
|
"billing_help_title": "هل تحتاج إلى أي شيء آخر؟",
|
||||||
|
"billing_help_description": "إذا كنت تحتاج إلى أي مساعدة إضافية بخصوص الفوترة، فإن فريق الدعم لدينا في انتظارك لتقديم المساعدة.",
|
||||||
|
"billing_help_cta": "الاتصال بالدعم",
|
||||||
|
"ignore_special_characters": "تجاهل الأحرف الخاصة في تسمية الإدخال الإضافية لديك. استخدم فقط الأحرف والأرقام",
|
||||||
|
"retry": "إعادة المحاولة",
|
||||||
|
"fetching_calendars_error": "حدثت مشكلة أثناء حفظ بياناتك. الرجاء <1>المحاولة من جديد</1> أو التواصل مع دعم العملاء.",
|
||||||
|
"calendar_connection_fail": "فشل الاتصال بالتقويم",
|
||||||
|
"booking_confirmation_success": "تم تأكيد الحجز بنجاح",
|
||||||
|
"booking_confirmation_fail": "فشل تأكيد الحجز",
|
||||||
|
"we_wont_show_again": "لن نعرض هذا مرة أخرى",
|
||||||
|
"couldnt_update_timezone": "لم نتمكن من تحديث المنطقة الزمنية",
|
||||||
|
"updated_timezone_to": "تم تحديث المنطقة الزمنية إلى {{formattedCurrentTz}}",
|
||||||
|
"update_timezone": "تحديث المنطقة الزمنية",
|
||||||
|
"update_timezone_question": "تحديث المنطقة الزمنية؟",
|
||||||
|
"update_timezone_description": "يبدو أن منطقتك الزمنية المحلية قد تغيرت إلى {{formattedCurrentTz}}. من المهم جداً أن يكون لديك المنطقة الزمنية المناسبة لمنع الحجز في أوقات غير مرغوب فيها. هل تريد تحديثها؟",
|
||||||
|
"dont_update": "لا تقم بالتحديث"
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Pro obnovení hesla použijte odkaz níž",
|
"use_link_to_reset_password": "Pro obnovení hesla použijte odkaz níž",
|
||||||
"hey_there": "Zdravíme,",
|
"hey_there": "Zdravíme,",
|
||||||
"forgot_your_password_calcom": "Zapomněli jste heslo? - Cal.com",
|
"forgot_your_password_calcom": "Zapomněli jste heslo? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Typ události",
|
|
||||||
"delete_webhook_confirmation_message": "Opravdu chcete smazat tento webhook? Přestanete v reálném čase dostávat Cal.com data o schůzce na dané URL, pokud bude událost naplánována nebo zrušena.",
|
"delete_webhook_confirmation_message": "Opravdu chcete smazat tento webhook? Přestanete v reálném čase dostávat Cal.com data o schůzce na dané URL, pokud bude událost naplánována nebo zrušena.",
|
||||||
"confirm_delete_webhook": "Ano, smazat webhook",
|
"confirm_delete_webhook": "Ano, smazat webhook",
|
||||||
"edit_webhook": "Upravit webhook",
|
"edit_webhook": "Upravit webhook",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "Zobrazit veřejnou stránku",
|
"view_public_page": "Zobrazit veřejnou stránku",
|
||||||
"sign_out": "Odhlásit se",
|
"sign_out": "Odhlásit se",
|
||||||
"add_another": "Přidat další",
|
"add_another": "Přidat další",
|
||||||
|
"install_another": "Nainstalovat další",
|
||||||
"until": "do",
|
"until": "do",
|
||||||
"powered_by": "běží na",
|
"powered_by": "běží na",
|
||||||
"unavailable": "Nedostupný",
|
"unavailable": "Nedostupný",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "Zaškrtávací pole",
|
"checkbox": "Zaškrtávací pole",
|
||||||
"is_required": "Je vyžadováno",
|
"is_required": "Je vyžadováno",
|
||||||
"required": "Vyžadováno",
|
"required": "Vyžadováno",
|
||||||
|
"optional": "Nepovinné",
|
||||||
"input_type": "Typ pole",
|
"input_type": "Typ pole",
|
||||||
"rejected": "Zamítnuto",
|
"rejected": "Zamítnuto",
|
||||||
"unconfirmed": "Nepotvrzeno",
|
"unconfirmed": "Nepotvrzeno",
|
||||||
@@ -227,10 +228,12 @@
|
|||||||
"connect_your_calendar_instructions": "Připojit kalendář pro automatickou kontrolu časů, kdy nejste dostupní, a nově naplánovaných událostí.",
|
"connect_your_calendar_instructions": "Připojit kalendář pro automatickou kontrolu časů, kdy nejste dostupní, a nově naplánovaných událostí.",
|
||||||
"set_up_later": "Zprovoznit později",
|
"set_up_later": "Zprovoznit později",
|
||||||
"current_time": "Aktuální čas",
|
"current_time": "Aktuální čas",
|
||||||
|
"details": "Podrobnosti",
|
||||||
"welcome": "Vítejte",
|
"welcome": "Vítejte",
|
||||||
|
"welcome_back": "Vítejte zpět",
|
||||||
"welcome_to_calcom": "Vítejte na webu Cal.com",
|
"welcome_to_calcom": "Vítejte na webu Cal.com",
|
||||||
"welcome_instructions": "Řekněte nám vaše jméno a v jaké časové zóně se pohybujete. Později můžete tyto informace změnit.",
|
"welcome_instructions": "Řekněte nám vaše jméno a v jaké časové zóně se pohybujete. Později můžete tyto informace změnit.",
|
||||||
"connect_caldav": "Připojit se k CalDav serveru",
|
"connect_caldav": "Připojit se k CalDav (Beta)u",
|
||||||
"credentials_stored_and_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
"credentials_stored_and_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
||||||
"connect": "Připojit",
|
"connect": "Připojit",
|
||||||
"try_for_free": "Vyzkoušet zdarma",
|
"try_for_free": "Vyzkoušet zdarma",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "Kdy",
|
"when": "Kdy",
|
||||||
"where": "Kde",
|
"where": "Kde",
|
||||||
"add_to_calendar": "Přidat do kalendáře",
|
"add_to_calendar": "Přidat do kalendáře",
|
||||||
|
"add_another_calendar": "Přidat další kalendář",
|
||||||
"other": "Ostatní",
|
"other": "Ostatní",
|
||||||
"emailed_you_and_attendees": "Poslali jsme vám a ostatním účastníkům e-mail s pozvánkou a podrobnostmi.",
|
"emailed_you_and_attendees": "Poslali jsme vám a ostatním účastníkům e-mail s pozvánkou a podrobnostmi.",
|
||||||
"emailed_you_and_attendees_recurring": "Na první z těchto opakovaných událostí jsme vám a ostatním účastníkům poslali e-mail s pozvánkou a podrobnostmi.",
|
"emailed_you_and_attendees_recurring": "Na první z těchto opakovaných událostí jsme vám a ostatním účastníkům poslali e-mail s pozvánkou a podrobnostmi.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "Zadejte nové heslo, které chcete u účtu používat.",
|
"enter_new_password": "Zadejte nové heslo, které chcete u účtu používat.",
|
||||||
"reset_password": "Obnovit heslo",
|
"reset_password": "Obnovit heslo",
|
||||||
"change_your_password": "Změnit heslo",
|
"change_your_password": "Změnit heslo",
|
||||||
|
"show_password": "Zobrazit heslo",
|
||||||
|
"hide_password": "Skrýt heslo",
|
||||||
"try_again": "Zkusit znovu",
|
"try_again": "Zkusit znovu",
|
||||||
"request_is_expired": "Platnost tohoto požadavku vypršela.",
|
"request_is_expired": "Platnost tohoto požadavku vypršela.",
|
||||||
"reset_instructions": "Zadejte e-mailovou adresu přiřazenou k vašemu účtu. Pošleme vám na ni odkaz pro obnovení vašeho hesla.",
|
"reset_instructions": "Zadejte e-mailovou adresu přiřazenou k vašemu účtu. Pošleme vám na ni odkaz pro obnovení vašeho hesla.",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "Jakmile si někdo s vámi zarezervuje opakovanou schůzku, zobrazí se to zde.",
|
"recurring_bookings": "Jakmile si někdo s vámi zarezervuje opakovanou schůzku, zobrazí se to zde.",
|
||||||
"past_bookings": "Vaše proběhlé rezervace se zobrazí zde.",
|
"past_bookings": "Vaše proběhlé rezervace se zobrazí zde.",
|
||||||
"cancelled_bookings": "Vaše zrušené rezervace se zobrazí zde.",
|
"cancelled_bookings": "Vaše zrušené rezervace se zobrazí zde.",
|
||||||
|
"unconfirmed_bookings": "Vaše nepotvrzené rezervace se zobrazí zde.",
|
||||||
"on": "dne",
|
"on": "dne",
|
||||||
"and": "a",
|
"and": "a",
|
||||||
"calendar_shows_busy_between": "Kalendář vás zobrazuje jako nedostupného mezi",
|
"calendar_shows_busy_between": "Kalendář vás zobrazuje jako nedostupného mezi",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "Rezervace zrušena",
|
"booking_cancelled": "Rezervace zrušena",
|
||||||
"booking_rescheduled": "Rezervace přesunuta",
|
"booking_rescheduled": "Rezervace přesunuta",
|
||||||
"booking_created": "Rezervace vytvořena",
|
"booking_created": "Rezervace vytvořena",
|
||||||
|
"meeting_ended": "Schůzka skončila",
|
||||||
"form_submitted": "Formulář byl odeslán",
|
"form_submitted": "Formulář byl odeslán",
|
||||||
"event_triggers": "Eventy na základě akce",
|
"event_triggers": "Eventy na základě akce",
|
||||||
"subscriber_url": "URL pro odběry",
|
"subscriber_url": "URL pro odběry",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "Pojďme vytvořit prvního uživatele administrátora.",
|
"lets_create_first_administrator_user": "Pojďme vytvořit prvního uživatele administrátora.",
|
||||||
"new_member": "Nový člen",
|
"new_member": "Nový člen",
|
||||||
"invite": "Pozvat",
|
"invite": "Pozvat",
|
||||||
|
"add_team_members": "Přidat členy týmu",
|
||||||
|
"add_team_members_description": "Pozvěte další, aby se připojili k vašemu týmu",
|
||||||
|
"add_team_member": "Přidat člena týmu",
|
||||||
"invite_new_member": "Pozvat nového člena",
|
"invite_new_member": "Pozvat nového člena",
|
||||||
"invite_new_team_member": "Pozvat někoho do týmu.",
|
"invite_new_team_member": "Pozvat někoho do týmu.",
|
||||||
"change_member_role": "Změnit roli člena týmu",
|
"change_member_role": "Změnit roli člena týmu",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "Vytvořte svůj první tým a pozvěte další uživatele, aby s vámi spolupracovali.",
|
"create_first_team_and_invite_others": "Vytvořte svůj první tým a pozvěte další uživatele, aby s vámi spolupracovali.",
|
||||||
"create_team_to_get_started": "Začněte vytvořením týmu",
|
"create_team_to_get_started": "Začněte vytvořením týmu",
|
||||||
"teams": "Týmy",
|
"teams": "Týmy",
|
||||||
|
"team": "Tým",
|
||||||
"team_billing": "Fakturace týmů",
|
"team_billing": "Fakturace týmů",
|
||||||
"upgrade_to_flexible_pro_title": "Změnili jsme fakturaci pro týmy",
|
"upgrade_to_flexible_pro_title": "Změnili jsme fakturaci pro týmy",
|
||||||
"upgrade_to_flexible_pro_message": "Ve vašem týmu jsou členové bez místa. Upgradujte svůj Pro plán pro pokrytí chybějících míst.",
|
"upgrade_to_flexible_pro_message": "Ve vašem týmu jsou členové bez místa. Upgradujte svůj Pro plán pro pokrytí chybějících míst.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "Fakturace",
|
"billing": "Fakturace",
|
||||||
"manage_your_billing_info": "Spravujte své fakturační údaje a zrušte své předplatné.",
|
"manage_your_billing_info": "Spravujte své fakturační údaje a zrušte své předplatné.",
|
||||||
"availability": "Dostupnost",
|
"availability": "Dostupnost",
|
||||||
|
"edit_availability": "Upravit dostupnost",
|
||||||
"configure_availability": "Nastavit časy, kdy jste dostupní pro rezervace.",
|
"configure_availability": "Nastavit časy, kdy jste dostupní pro rezervace.",
|
||||||
|
"copy_times_to": "Kopírovat časy do",
|
||||||
"change_weekly_schedule": "Změnit týdenní pracovní dobu",
|
"change_weekly_schedule": "Změnit týdenní pracovní dobu",
|
||||||
"logo": "Logo",
|
"logo": "Logo",
|
||||||
"error": "Chyba",
|
"error": "Chyba",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "Název, který se zobrazí v kalendářích",
|
"event_name_tooltip": "Název, který se zobrazí v kalendářích",
|
||||||
"meeting_with_user": "Schůzka s {ATTENDEE}",
|
"meeting_with_user": "Schůzka s {ATTENDEE}",
|
||||||
"additional_inputs": "Další pole",
|
"additional_inputs": "Další pole",
|
||||||
|
"additional_input_description": "Před potvrzením rezervace vyžadovat od plánující osoby zadání dalších vstupů",
|
||||||
"label": "Popisek",
|
"label": "Popisek",
|
||||||
"placeholder": "Placeholder",
|
"placeholder": "Placeholder",
|
||||||
"type": "Typ",
|
"type": "Typ",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "Zakázat hosty",
|
"disable_guests": "Zakázat hosty",
|
||||||
"disable_guests_description": "Zakázat přidávání dalších hostů během rezervace.",
|
"disable_guests_description": "Zakázat přidávání dalších hostů během rezervace.",
|
||||||
"private_link": "Vygenerovat soukromou adresu URL",
|
"private_link": "Vygenerovat soukromou adresu URL",
|
||||||
|
"private_link_label": "Soukromý odkaz",
|
||||||
|
"private_link_hint": "Váš soukromý odkaz se po každém použití obnoví",
|
||||||
"copy_private_link": "Zkopírovat soukromý odkaz",
|
"copy_private_link": "Zkopírovat soukromý odkaz",
|
||||||
"private_link_description": "Vygenerujte soukromou adresu URL, kterou budete sdílet, aniž byste odhalili své uživatelské jméno ve službě Cal",
|
"private_link_description": "Vygenerujte soukromou adresu URL, kterou budete sdílet, aniž byste odhalili své uživatelské jméno ve službě Cal",
|
||||||
"invitees_can_schedule": "Pozvaní mohou plánovat",
|
"invitees_can_schedule": "Pozvaní mohou plánovat",
|
||||||
@@ -679,7 +696,7 @@
|
|||||||
"add_new_event_type": "Přidat nový typ události",
|
"add_new_event_type": "Přidat nový typ události",
|
||||||
"new_event_type_to_book_description": "Vytvořit nový typ události, ve které si lidé mohou rezervovat časy.",
|
"new_event_type_to_book_description": "Vytvořit nový typ události, ve které si lidé mohou rezervovat časy.",
|
||||||
"length": "Doba trvání",
|
"length": "Doba trvání",
|
||||||
"minimum_booking_notice": "Minimální upozornění na rezervaci",
|
"minimum_booking_notice": "Minimální potřebná doba",
|
||||||
"slot_interval": "Časové intervaly",
|
"slot_interval": "Časové intervaly",
|
||||||
"slot_interval_default": "Použít délku události (výchozí)",
|
"slot_interval_default": "Použít délku události (výchozí)",
|
||||||
"delete_event_type_description": "Opravdu chcete smazat tento typ události? Všichni, se kterými jsme tento odkaz sdíleli, ho nebudou moct používat pro rezervování.",
|
"delete_event_type_description": "Opravdu chcete smazat tento typ události? Všichni, se kterými jsme tento odkaz sdíleli, ho nebudou moct používat pro rezervování.",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "Opravdu chcete odstranit svůj účet na Cal.com? Všichni, se kterými jste sdíleli odkaz na účet, přijdou o možnost vytvářet rezervace a vy přijdete o uložené předvolby.",
|
"delete_account_confirmation_message": "Opravdu chcete odstranit svůj účet na Cal.com? Všichni, se kterými jste sdíleli odkaz na účet, přijdou o možnost vytvářet rezervace a vy přijdete o uložené předvolby.",
|
||||||
"integrations": "Integrace",
|
"integrations": "Integrace",
|
||||||
"apps": "Aplikace",
|
"apps": "Aplikace",
|
||||||
|
"category_apps": "Aplikace ({{category}})",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "Propojování lidí, technologií a pracoviště.",
|
"app_store_description": "Propojování lidí, technologií a pracoviště.",
|
||||||
"settings": "Nastavení",
|
"settings": "Nastavení",
|
||||||
"event_type_moved_successfully": "Typ události byl úspěšně přesunut",
|
"event_type_moved_successfully": "Typ události byl úspěšně přesunut",
|
||||||
|
"next_step_text": "Další krok",
|
||||||
"next_step": "Přeskočit krok",
|
"next_step": "Přeskočit krok",
|
||||||
"prev_step": "Předchozí krok",
|
"prev_step": "Předchozí krok",
|
||||||
|
"install": "Nainstalovat",
|
||||||
"installed": "Nainstalováno",
|
"installed": "Nainstalováno",
|
||||||
"active_install_one": "Aktivní instalace: {{count}}",
|
"active_install_one": "Aktivní instalace: {{count}}",
|
||||||
"active_install_other": "Aktivní instalace: {{count}}",
|
"active_install_other": "Aktivní instalace: {{count}}",
|
||||||
"globally_install": "Nainstalováno globálně",
|
"globally_install": "Nainstalováno globálně",
|
||||||
|
"app_successfully_installed": "Aplikace byla nainstalována",
|
||||||
|
"app_could_not_be_installed": "Aplikaci se nepodařilo nainstalovat",
|
||||||
"disconnect": "Odpojit",
|
"disconnect": "Odpojit",
|
||||||
"embed_your_calendar": "Vložte kalendář do vaší webové stránky",
|
"embed_your_calendar": "Vložte kalendář do vaší webové stránky",
|
||||||
"connect_your_favourite_apps": "Připojte své oblíbené aplikace.",
|
"connect_your_favourite_apps": "Připojte své oblíbené aplikace.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "Připojit další kalendář",
|
"connect_additional_calendar": "Připojit další kalendář",
|
||||||
"conferencing": "Konference",
|
"conferencing": "Konference",
|
||||||
"calendar": "Kalendář",
|
"calendar": "Kalendář",
|
||||||
|
"payments": "Platby",
|
||||||
"not_installed": "Nenainstalováno",
|
"not_installed": "Nenainstalováno",
|
||||||
"error_password_mismatch": "Hesla se neshodují.",
|
"error_password_mismatch": "Hesla se neshodují.",
|
||||||
"error_required_field": "Toto pole je povinné.",
|
"error_required_field": "Toto pole je povinné.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "Importovat z",
|
"import_from": "Importovat z",
|
||||||
"access_token": "Access token",
|
"access_token": "Access token",
|
||||||
"visit_roadmap": "Roadmapa",
|
"visit_roadmap": "Roadmapa",
|
||||||
|
"featured_categories": "Doporučené kategorie",
|
||||||
"popular_categories": "Oblíbené kategorie",
|
"popular_categories": "Oblíbené kategorie",
|
||||||
|
"number_apps_one": "Aplikace: {{count}}",
|
||||||
|
"number_apps_other": "Aplikace: {{count}}",
|
||||||
"trending_apps": "Populární aplikace",
|
"trending_apps": "Populární aplikace",
|
||||||
|
"explore_apps": "Aplikace ({{category}})",
|
||||||
"installed_apps": "Nainstalované aplikace",
|
"installed_apps": "Nainstalované aplikace",
|
||||||
|
"no_category_apps": "Žádné aplikace ({{kategorie}})",
|
||||||
|
"no_category_apps_description_calendar": "Přidejte aplikaci kalendáře, ať máte přehled v zájmu prevence dvojích rezervací",
|
||||||
|
"no_category_apps_description_conferencing": "Zkuste přidat aplikaci pro konference, která umožní propojit videohovory s vašimi klienty",
|
||||||
|
"no_category_apps_description_payment": "Přidejte platební aplikaci, která usnadní provádění transakcí mezi vámi a vašimi klienty",
|
||||||
|
"no_category_apps_description_other": "Přidejte jakýkoli jiný typ aplikace pro nejrůznější činnosti",
|
||||||
|
"installed_app_calendar_description": "Nastavte si kalendáře, ať můžete kontrolovat konflikty a zabránit tak dvojím rezervacím.",
|
||||||
|
"installed_app_conferencing_description": "Přidejte své oblíbené aplikace pro videokonference pro vaše schůzky",
|
||||||
|
"installed_app_payment_description": "Nakonfigurujte služby zpracování plateb, které se mají používat při strhávání plateb z klientů.",
|
||||||
|
"installed_app_other_description": "Všechny vaše nainstalované aplikace z ostatních kategorií.",
|
||||||
"empty_installed_apps_headline": "Nenainstalovány žádné aplikace",
|
"empty_installed_apps_headline": "Nenainstalovány žádné aplikace",
|
||||||
"empty_installed_apps_description": "Aplikace vám umožní zlepšit pracovní postupy a výrazně zkvalitnit plánování.",
|
"empty_installed_apps_description": "Aplikace vám umožní zlepšit pracovní postupy a výrazně zkvalitnit plánování.",
|
||||||
"empty_installed_apps_button": "Prozkoumejte App Store",
|
"empty_installed_apps_button": "Prozkoumejte App Store",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "Odebrat",
|
"remove": "Odebrat",
|
||||||
"add": "Přidat",
|
"add": "Přidat",
|
||||||
"installed_one": "Nainstalováno",
|
"installed_one": "Nainstalováno",
|
||||||
|
"installed_other": "Nainstalováno: {{count}}",
|
||||||
"verify_wallet": "Ověřit peněženku",
|
"verify_wallet": "Ověřit peněženku",
|
||||||
"connect_metamask": "Připojit Metamask",
|
"connect_metamask": "Připojit Metamask",
|
||||||
"create_events_on": "Vytvořit události v:",
|
"create_events_on": "Vytvořit události v:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "Nastavit jako výchozí",
|
"set_to_default": "Nastavit jako výchozí",
|
||||||
"new_schedule_btn": "Nový plán",
|
"new_schedule_btn": "Nový plán",
|
||||||
"add_new_schedule": "Přidat nový plán",
|
"add_new_schedule": "Přidat nový plán",
|
||||||
|
"add_new_calendar": "Přidání nového kalendáře",
|
||||||
|
"set_calendar": "Nastavte, kam se mají při rezervaci přidávat nové události.",
|
||||||
"delete_schedule": "Odstranit plán",
|
"delete_schedule": "Odstranit plán",
|
||||||
"schedule_created_successfully": "Plán {{scheduleName}} byl úspěšně vytvořen",
|
"schedule_created_successfully": "Plán {{scheduleName}} byl úspěšně vytvořen",
|
||||||
"availability_updated_successfully": "Dostupnost byla úspěšně aktualizována",
|
"availability_updated_successfully": "Dostupnost byla úspěšně aktualizována",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "Přesměrovat při rezervaci ",
|
"redirect_success_booking": "Přesměrovat při rezervaci ",
|
||||||
"you_are_being_redirected": "Budete přesměrováni na {{ url }} za $t(s, {\"count\": {{s}} }).",
|
"you_are_being_redirected": "Budete přesměrováni na {{ url }} za $t(s, {\"count\": {{s}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "Pokud chcete použít tuto funkci, musíte provést aktualizaci na účet Pro.",
|
|
||||||
"duplicate": "Duplikovat",
|
"duplicate": "Duplikovat",
|
||||||
"offer_seats": "Nabídka míst",
|
"offer_seats": "Nabídka míst",
|
||||||
"offer_seats_description": "Nabídnout místa rezervacím (tím se vypnou rezervace hostů a s potvrzením)",
|
"offer_seats_description": "Nabídnout místa rezervacím (tím se vypnou rezervace hostů a s potvrzením)",
|
||||||
@@ -809,7 +847,7 @@
|
|||||||
"booking_full": "Nejsou k dispozici žádná další místa",
|
"booking_full": "Nejsou k dispozici žádná další místa",
|
||||||
"api_keys": "Klíče API",
|
"api_keys": "Klíče API",
|
||||||
"api_key": "Klíč API",
|
"api_key": "Klíč API",
|
||||||
"test_api_key": "Testovací klíč API",
|
"test_api_key": "Otestovat klíč API",
|
||||||
"test_passed": "Test se zdařil!",
|
"test_passed": "Test se zdařil!",
|
||||||
"test_failed": "Test se nezdařil",
|
"test_failed": "Test se nezdařil",
|
||||||
"provide_api_key": "Zadejte klíč API",
|
"provide_api_key": "Zadejte klíč API",
|
||||||
@@ -883,7 +921,7 @@
|
|||||||
"zapier_setup_instructions": "<0>Přihlaste se ke svému účtu Zapier a vytvořte nový Zap.</0><1>Vyberte Cal.com jako svoji aplikaci Trigger. Také vyberte událost Trigger.</1><2>Vyberte si svůj účet a pak zadejte svůj unikátní klíč API.</2><3>Otestujte aplikaci Trigger.</3><4>Vše máte nastaveno!</4>",
|
"zapier_setup_instructions": "<0>Přihlaste se ke svému účtu Zapier a vytvořte nový Zap.</0><1>Vyberte Cal.com jako svoji aplikaci Trigger. Také vyberte událost Trigger.</1><2>Vyberte si svůj účet a pak zadejte svůj unikátní klíč API.</2><3>Otestujte aplikaci Trigger.</3><4>Vše máte nastaveno!</4>",
|
||||||
"install_zapier_app": "Nejdřív si z App Store nainstalujte aplikaci Zapier.",
|
"install_zapier_app": "Nejdřív si z App Store nainstalujte aplikaci Zapier.",
|
||||||
"connect_apple_server": "Připojit se k serveru Apple",
|
"connect_apple_server": "Připojit se k serveru Apple",
|
||||||
"connect_caldav_server": "Připojit se k CalDav serveru",
|
"connect_caldav_server": "Připojit se k CalDav (Beta)u",
|
||||||
"calendar_url": "URL kalendáře",
|
"calendar_url": "URL kalendáře",
|
||||||
"apple_server_generate_password": "Vygenerujte si specifické heslo pro aplikaci Cal.com na",
|
"apple_server_generate_password": "Vygenerujte si specifické heslo pro aplikaci Cal.com na",
|
||||||
"credentials_stored_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
"credentials_stored_encrypted": "Vaše přihlašovací údaje budou uloženy a zašifrovány.",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "Pracovní postupy",
|
"workflows": "Pracovní postupy",
|
||||||
"new_workflow_btn": "Nový pracovní postup",
|
"new_workflow_btn": "Nový pracovní postup",
|
||||||
"add_new_workflow": "Přidat nový pracovní postup",
|
"add_new_workflow": "Přidat nový pracovní postup",
|
||||||
|
"reschedule_event_trigger": "pokud je událost přeložena na jiný termín",
|
||||||
"trigger": "Spouštěč",
|
"trigger": "Spouštěč",
|
||||||
"triggers": "Spouštěče",
|
"triggers": "Spouštěče",
|
||||||
"action": "Akce",
|
"action": "Akce",
|
||||||
@@ -949,7 +988,7 @@
|
|||||||
"workflow_deleted_successfully": "Pracovní postup byl odstraněn",
|
"workflow_deleted_successfully": "Pracovní postup byl odstraněn",
|
||||||
"how_long_before": "Za jak dlouho začne událost?",
|
"how_long_before": "Za jak dlouho začne událost?",
|
||||||
"day_timeUnit": "dny",
|
"day_timeUnit": "dny",
|
||||||
"hour_timeUnit": "hodiny",
|
"hour_timeUnit": "h",
|
||||||
"minute_timeUnit": "min",
|
"minute_timeUnit": "min",
|
||||||
"new_workflow_heading": "Vytvořte svůj první pracovní postup",
|
"new_workflow_heading": "Vytvořte svůj první pracovní postup",
|
||||||
"new_workflow_description": "Pracovní postupy umožňují automatizovat zasílání upomínek a oznámení.",
|
"new_workflow_description": "Pracovní postupy umožňují automatizovat zasílání upomínek a oznámení.",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "Při změně uživatelského jména ze standardního na prémiové budete přesměrováni k platbě, po které přejdete na vyšší verzi.",
|
"change_username_standard_to_premium": "Při změně uživatelského jména ze standardního na prémiové budete přesměrováni k platbě, po které přejdete na vyšší verzi.",
|
||||||
"change_username_premium_to_standard": "Při změně uživatelského jména z prémiového na standardní budete přesměrováni k platbě, po které přejdete na nižší verzi.",
|
"change_username_premium_to_standard": "Při změně uživatelského jména z prémiového na standardní budete přesměrováni k platbě, po které přejdete na nižší verzi.",
|
||||||
"go_to_stripe_billing": "Přejít k fakturaci",
|
"go_to_stripe_billing": "Přejít k fakturaci",
|
||||||
|
"stripe_description": "Vyžadovat poplatek za rezervace (0,5 % + 0,10 € provize za transakci)",
|
||||||
"trial_expired": "Vaše zkušební verze vypršela",
|
"trial_expired": "Vaše zkušební verze vypršela",
|
||||||
"remove_app": "Odstranit aplikaci",
|
"remove_app": "Odstranit aplikaci",
|
||||||
"yes_remove_app": "Ano, odstranit aplikaci",
|
"yes_remove_app": "Ano, odstranit aplikaci",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "Opravdu chcete odstranit tuto aplikaci?",
|
"are_you_sure_you_want_to_remove_this_app": "Opravdu chcete odstranit tuto aplikaci?",
|
||||||
|
"app_removed_successfully": "Aplikace odstraněna",
|
||||||
|
"error_removing_app": "Chyba při odstraňování aplikace",
|
||||||
"web_conference": "Webová konference",
|
"web_conference": "Webová konference",
|
||||||
"number_for_sms_reminders": "Telefonní číslo (pro upomínky přes SMS)",
|
"number_for_sms_reminders": "Telefonní číslo (pro upomínky přes SMS)",
|
||||||
"requires_confirmation": "Vyžaduje potvrzení",
|
"requires_confirmation": "Vyžaduje potvrzení",
|
||||||
@@ -1022,18 +1064,209 @@
|
|||||||
"navigate": "Navigace",
|
"navigate": "Navigace",
|
||||||
"open": "Otevřít",
|
"open": "Otevřít",
|
||||||
"close": "Zavřít",
|
"close": "Zavřít",
|
||||||
|
"team_feature_teams": "Toto je funkce Team. Pokud chcete zobrazit dostupnost svého týmu, upgradujte na verzi Team.",
|
||||||
|
"team_feature_workflows": "Jedná se o funkci Team. Upgradujte na verzi Team, abyste mohli automatizovat upozornění na události a upomínky pomocí pracovních postupů.",
|
||||||
|
"show_eventtype_on_profile": "Zobrazit na profilu",
|
||||||
"embed": "Vložit",
|
"embed": "Vložit",
|
||||||
"new_username": "Nové uživatelské jméno",
|
"new_username": "Nové uživatelské jméno",
|
||||||
"current_username": "Současné uživatelské jméno",
|
"current_username": "Současné uživatelské jméno",
|
||||||
"example_1": "Příklad 1",
|
"example_1": "Příklad 1",
|
||||||
"example_2": "Příklad 2",
|
"example_2": "Příklad 2",
|
||||||
|
"additional_input_label": "Další vstupní štítek",
|
||||||
"company_size": "Velikost společnosti",
|
"company_size": "Velikost společnosti",
|
||||||
"what_help_needed": "S čím potřebujete pomoci?",
|
"what_help_needed": "S čím potřebujete pomoci?",
|
||||||
"variable_format": "Formát proměnné",
|
"variable_format": "Formát proměnné",
|
||||||
|
"webhook_subscriber_url_reserved": "Adresa URL odběratele webhooku je již definována",
|
||||||
|
"custom_input_as_variable_info": "Ignorujte všechny speciální znaky doplňkového vstupního štítku (používejte pouze písmena a číslice), používejte velká písmena a bílé znaky nahraďte podtržítky.",
|
||||||
"using_additional_inputs_as_variables": "Jak používat doplňkové vstupy jako proměnné?",
|
"using_additional_inputs_as_variables": "Jak používat doplňkové vstupy jako proměnné?",
|
||||||
"download_desktop_app": "Stáhněte si aplikaci pro stolní počítače",
|
"download_desktop_app": "Stáhněte si aplikaci pro stolní počítače",
|
||||||
"set_ping_link": "Nastavení odkazu Ping",
|
"set_ping_link": "Nastavení odkazu Ping",
|
||||||
|
"rate_limit_exceeded": "Byl překročen limit rychlosti",
|
||||||
|
"when_something_happens": "Pokud se něco stane",
|
||||||
|
"action_is_performed": "Provede se akce",
|
||||||
|
"test_action": "Testovací akce",
|
||||||
|
"notification_sent": "Oznámení odesláno",
|
||||||
|
"no_input": "Žádný vstup",
|
||||||
|
"test_workflow_action": "Testovací akce pracovního postupu",
|
||||||
|
"send_sms": "Odeslat SMS",
|
||||||
|
"send_sms_to_number": "Opravdu chcete odeslat SMS na číslo {{number}}?",
|
||||||
|
"missing_connected_calendar": "Není připojen žádný výchozí kalendář",
|
||||||
|
"connect_your_calendar_and_link": "Svůj kalendář můžete připojit <1>zde</1>.",
|
||||||
|
"default_calendar_selected": "Výchozí kalendář",
|
||||||
|
"hide_from_profile": "Nezobrazovat v profilu",
|
||||||
|
"event_setup_tab_title": "Nastavení události",
|
||||||
|
"event_limit_tab_title": "Omezení",
|
||||||
|
"event_limit_tab_description": "Jak často lze u vás provést rezervaci",
|
||||||
|
"event_advanced_tab_description": "Nastavení kalendáře a další...",
|
||||||
|
"event_advanced_tab_title": "Upřesnit",
|
||||||
|
"select_which_cal": "Vyberte kalendář, do kterého se mají přidávat rezervace",
|
||||||
|
"custom_event_name": "Vlastní název události",
|
||||||
|
"custom_event_name_description": "Vytvářejte vlastní názvy událostí, které se budou zobrazovat v kalendáři událostí",
|
||||||
|
"2fa_required": "Vyžadováno dvoufázové ověření",
|
||||||
|
"incorrect_2fa": "Nesprávný kód dvoufázového ověření",
|
||||||
|
"which_event_type_apply": "Na jaký typ události se to bude vztahovat?",
|
||||||
|
"no_workflows_description": "Pracovní postupy umožňují jednoduchou automatizaci zasílání oznámení a připomínek, což vám umožní vytvářet procesy v souvislosti s vašimi událostmi.",
|
||||||
|
"create_workflow": "Vytvoření pracovního postupu",
|
||||||
|
"do_this": "Provést",
|
||||||
|
"turn_off": "Vypnout",
|
||||||
|
"settings_updated_successfully": "Nastavení aktualizováno",
|
||||||
|
"error_updating_settings": "Chyba při aktualizaci nastavení",
|
||||||
|
"personal_cal_url": "Moje osobní adresa URL Cal",
|
||||||
|
"bio_hint": "Několik vět o vás. Obsah se zobrazí se na vaší osobní stránce URL.",
|
||||||
|
"delete_account_modal_title": "Odstranit účet",
|
||||||
|
"confirm_delete_account_modal": "Opravdu chcete odstranit svůj účet Cal.com?",
|
||||||
|
"delete_my_account": "Odstranit můj účet",
|
||||||
|
"start_of_week": "Začátek týdne",
|
||||||
|
"select_calendars": "Vyberte kalendáře, u kterých chcete kontrolovat konflikty v zájmu prevence dvojích rezervací.",
|
||||||
|
"check_for_conflicts": "Zkontrolovat konflikty",
|
||||||
|
"adding_events_to": "Přidání událostí do:",
|
||||||
|
"follow_system_preferences": "Řídit se předvolbami systému",
|
||||||
|
"custom_brand_colors": "Vlastní barvy značky",
|
||||||
|
"customize_your_brand_colors": "Vytvořte si rezervační stránku na míru v barvách své značky.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "Odstraní všechny značky související s Cal, tj. „Běží na platformě Cal.“",
|
||||||
|
"profile_picture": "Profilový obrázek",
|
||||||
|
"upload": "Nahrát",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "Tento typ události je uzamčený tokenem.",
|
||||||
|
"rainbow_connect_wallet_gate": "Propojte svoji peněženku, pokud vlastníte <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "Vaše propojená peněženka neobsahuje dostatek <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "Podepište zprávu s žádostí ve své peněžence.",
|
||||||
|
"rainbow_signature_error": "Chyba při vyžádání podpisu z vaší peněženky.",
|
||||||
|
"token_address": "Adresa tokenu",
|
||||||
|
"blockchain": "Blockchain",
|
||||||
|
"old_password": "Staré heslo",
|
||||||
|
"secure_password": "Vaše nové heslo se super zabezpečením",
|
||||||
|
"error_updating_password": "Chyba při aktualizaci hesla",
|
||||||
|
"two_factor_auth": "Dvoufázové ověření",
|
||||||
|
"recurring_event_tab_description": "Nastavení opakujícího se plánu",
|
||||||
|
"today": "dnes",
|
||||||
|
"appearance": "Vzhled",
|
||||||
|
"appearance_subtitle": "Správa nastavení vzhledu rezervace",
|
||||||
|
"my_account": "Můj účet",
|
||||||
|
"general": "Obecné",
|
||||||
|
"calendars": "Kalendáře",
|
||||||
|
"2fa_auth": "Dvoufázové ověření",
|
||||||
|
"invoices": "Faktury",
|
||||||
|
"embeds": "Vložení",
|
||||||
|
"impersonation": "Ztotožnění",
|
||||||
|
"users": "Uživatelé",
|
||||||
|
"profile_description": "Správa nastavení profilu Cal",
|
||||||
|
"general_description": "Správa nastavení jazyka a časového pásma",
|
||||||
|
"calendars_description": "Konfigurace způsobu interkace typů událostí s kalendáři",
|
||||||
|
"appearance_description": "Správa nastavení vzhledu rezervace",
|
||||||
|
"conferencing_description": "Správa videokonferenčních aplikací pro vaše schůzky",
|
||||||
|
"password_description": "Správa nastavení pro hesla vašich účtů",
|
||||||
|
"2fa_description": "Správa nastavení pro hesla vašich účtů",
|
||||||
|
"we_just_need_basic_info": "K nastavení vašeho profilu potřebujeme jen několik základních informací.",
|
||||||
|
"skip": "Přeskočit",
|
||||||
|
"do_this_later": "Provést později",
|
||||||
|
"set_availability_getting_started_subtitle_1": "Definujte časová rozpětí, kdy budete k dispozici",
|
||||||
|
"set_availability_getting_started_subtitle_2": "To vše si můžete přizpůsobit později na stránce dostupnosti.",
|
||||||
|
"connect_calendars_from_app_store": "Další kalendáře můžete přidat přes obchod s aplikacemi",
|
||||||
|
"connect_conference_apps": "Propojit konferenční aplikace",
|
||||||
|
"connect_calendar_apps": "Propojit kalendářové aplikace",
|
||||||
|
"connect_payment_apps": "Připojit platební aplikace",
|
||||||
|
"connect_other_apps": "Připojit další aplikace",
|
||||||
|
"current_step_of_total": "Krok {{currentStep}} / {{maxSteps}}",
|
||||||
|
"add_variable": "Přidat proměnnou",
|
||||||
|
"custom_phone_number": "Vlastní telefonní číslo",
|
||||||
|
"message_template": "Šablona zprávy",
|
||||||
|
"email_subject": "Předmět e-mailu",
|
||||||
|
"add_dynamic_variables": "Přidání dynamických textových proměnných",
|
||||||
|
"event_name_info": "Název typu události",
|
||||||
|
"event_date_info": "Datum události",
|
||||||
|
"event_time_info": "Čas začátku události",
|
||||||
|
"location_info": "Místo události",
|
||||||
"organizer_name_info": "Vaše jméno",
|
"organizer_name_info": "Vaše jméno",
|
||||||
|
"additional_notes_info": "Další poznámky k rezervaci",
|
||||||
|
"attendee_name_info": "Jméno osoby provádějící rezervaci",
|
||||||
|
"to": "Komu",
|
||||||
|
"attendee_required_enter_number": "Při rezervaci je nutné, aby účastník zadal telefonní číslo",
|
||||||
|
"workflow_turned_on_successfully": "Pracovní postup {{workflowName}} byl {{offOn}}",
|
||||||
|
"download_responses": "Stáhnout odpovědi",
|
||||||
|
"create_your_first_form": "Vytvořte svůj první formulář",
|
||||||
|
"create_your_first_form_description": "Pomocí adresných formulářů můžete klást kvalifikační otázky a adresovat je správné osobě nebo typu události.",
|
||||||
|
"create_your_first_webhook": "Vytvořte svůj první webhook",
|
||||||
|
"create_your_first_webhook_description": "Pomocí webhooků můžete přijímat data o schůzkách v reálném čase, pokud v Cal.com dojde k nějaké akci.",
|
||||||
|
"for_a_maximum_of": "Max. pro",
|
||||||
|
"event_one": "událost",
|
||||||
|
"event_other": "událostí",
|
||||||
|
"profile_team_description": "Správa nastavení profilu vašeho týmu",
|
||||||
|
"members_team_description": "Uživatelé, kteří jsou ve skupině",
|
||||||
|
"team_url": "Adresa URL týmu",
|
||||||
|
"delete_team": "Odstranit tým",
|
||||||
|
"team_members": "Členové týmu",
|
||||||
|
"more": "Více",
|
||||||
|
"more_page_footer": "Mobilní aplikaci považujeme za rozšíření webové aplikace. Pokud provádíte složitější akce, vraťte se prosím k webové aplikaci.",
|
||||||
|
"workflow_example_1": "Odeslat účastníkovi SMS upomínku 24 hodin před začátkem akce",
|
||||||
|
"workflow_example_2": "Odeslat účastníkovi vlastní SMS, pokud je událost přeložena na jiný termín",
|
||||||
|
"workflow_example_3": "Odeslat hostiteli vlastní e-mail, pokud je rezervována nová událost",
|
||||||
|
"workflow_example_4": "Odeslat účastníkovi upomínku 1 hodinu před začátkem akce",
|
||||||
|
"workflow_example_5": "Odeslat hostiteli vlastní e-mail, pokud je událost přeložena na jiný termín",
|
||||||
|
"workflow_example_6": "Odeslat hostiteli vlastní SMS, pokud je rezervována nová událost",
|
||||||
|
"welcome_to_cal_header": "Vítá vás Cal.com!",
|
||||||
|
"edit_form_later_subtitle": "Toto budete moci upravit později.",
|
||||||
|
"connect_calendar_later": "Připojím svůj kalendář později",
|
||||||
|
"set_my_availability_later": "Svou dostupnost nastavím později",
|
||||||
|
"problem_saving_user_profile": "Při ukládání vašich údajů došlo k problému. Zkuste to prosím znovu, případně se obraťte na zákaznickou podporu.",
|
||||||
|
"purchase_missing_seats": "Koupit chybějící místa",
|
||||||
|
"slot_length": "Délka slotu",
|
||||||
|
"booking_appearance": "Vzhled rezervace",
|
||||||
|
"appearance_team_description": "Správa nastavení vzhledu rezervace vašeho týmu",
|
||||||
|
"only_owner_change": "Změny v rezervaci týmu může provádět pouze jeho vlastník ",
|
||||||
|
"team_disable_cal_branding_description": "Odstraní všechny značky související s Cal, tj. „Běží na platformě Cal.“",
|
||||||
|
"invited_by_team": "Tým {{teamName}} vás pozval do svého týmu na pozici {{role}}",
|
||||||
|
"token_invalid_expired": "Token je buď neplatný, nebo jeho platnost vypršela.",
|
||||||
|
"exchange_add": "Propojit s Microsoft Exchange",
|
||||||
|
"exchange_authentication": "Metoda ověřování",
|
||||||
|
"exchange_authentication_standard": "Základní ověření",
|
||||||
|
"exchange_authentication_ntlm": "Ověřování NTLM",
|
||||||
|
"exchange_compression": "Komprese GZip",
|
||||||
|
"routing_forms_description": "Zde si můžete prohlédnout všechny vytvořené formuláře a trasy.",
|
||||||
|
"add_new_form": "Přidat nový formulář",
|
||||||
|
"form_description": "Vytvořte formulář, který adresujete rezervující osobě",
|
||||||
|
"copy_link_to_form": "Kopírovat odkaz na formulář",
|
||||||
|
"theme": "Motiv",
|
||||||
|
"theme_applies_note": "Toto se týká pouze vašich veřejných stránek s rezervacemi",
|
||||||
"theme_light": "Světlý",
|
"theme_light": "Světlý",
|
||||||
"theme_dark": "Tmavý"
|
"theme_dark": "Tmavý",
|
||||||
|
"theme_system": "Výchozí nastavení systému",
|
||||||
|
"add_a_team": "Přidat tým",
|
||||||
|
"saml_config": "Konfig. SAML",
|
||||||
|
"add_webhook_description": "Přijímejte data o schůzkách v reálném čase, pokud v Cal.com dojde k nějaké akci",
|
||||||
|
"triggers_when": "Spustí se, pokud:",
|
||||||
|
"test_webhook": "Před vytvořením proveďte test ping.",
|
||||||
|
"enable_webhook": "Povolit webhook",
|
||||||
|
"add_webhook": "Přidat webhook",
|
||||||
|
"webhook_edited_successfully": "Webhook uložen",
|
||||||
|
"webhooks_description": "Přijímejte data o schůzkách v reálném čase, pokud v Cal.com dojde k nějaké akci",
|
||||||
|
"api_keys_description": "Vygenerujte klíče API pro přístup k vlastnímu účtu",
|
||||||
|
"new_api_key": "Nový klíč API",
|
||||||
|
"active": "Aktivní",
|
||||||
|
"api_key_updated": "Aktualizace názvu klíče API",
|
||||||
|
"api_key_update_failed": "Chyba při aktualizaci názvu klíče API",
|
||||||
|
"embeds_title": "Vložení rámce HTML iframe",
|
||||||
|
"embeds_description": "Vložte všechny typy událostí na vaši webovou stránku",
|
||||||
|
"create_first_api_key": "Vytvořte svůj první klíč API",
|
||||||
|
"create_first_api_key_description": "Klíče API umožňují ostatním aplikacím komunikovat se službou Cal.com",
|
||||||
|
"back_to_signin": "Zpět na přihlášení",
|
||||||
|
"reset_link_sent": "Odkaz pro obnovení odeslán",
|
||||||
|
"password_reset_email": "Na adresu {{email}} je na cestě e-mail s pokyny k obnovení hesla.",
|
||||||
|
"password_updated": "Heslo aktualizováno!",
|
||||||
|
"pending_payment": "Čeká se na platbu",
|
||||||
|
"confirmation_page_rainbow": "Zamkněte svoji událost pomocí tokenů nebo NFT na platformách Ethereum, Polygon a dalších.",
|
||||||
|
"not_on_cal": "Nenachází se na Cal.com",
|
||||||
|
"no_calendar_installed": "Není nainstalován kalendář",
|
||||||
|
"no_calendar_installed_description": "Ještě jste nepropojili žádný ze svých kalendářů",
|
||||||
|
"add_a_calendar": "Přidejte kalendář",
|
||||||
|
"change_email_hint": "Možná se budete muset odhlásit a znovu přihlásit, aby se změny projevily",
|
||||||
|
"confirm_password_change_email": "Před změnou e-mailové adresy potvrďte své heslo",
|
||||||
|
"seats": "míst",
|
||||||
|
"every_app_published": "Každá aplikace zveřejněná v obchodě s aplikacemi na Cal.com má otevřený zdrojový kód a je důkladně testována prostřednictvím vzájemného hodnocení. Společnost Cal.com, Inc. nicméně tyto aplikace neschvaluje ani necertifikuje, pokud nejsou zveřejněny přímo společností Cal.com. Pokud se setkáte s nevhodným obsahem nebo chováním, nahlaste to.",
|
||||||
|
"report_app": "Nahlásit aplikaci",
|
||||||
|
"billing_manage_details_title": "Zobrazit a spravovat fakturační údaje",
|
||||||
|
"billing_manage_details_description": "Zobrazit a upravovat fakturační údaje, možnost zrušit předplatné.",
|
||||||
|
"billing_help_title": "Potřebujete ještě něco?",
|
||||||
|
"billing_help_description": "Pokud potřebujete další pomoc s fakturací, náš tým podpory je zde, aby vám pomohl."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
|
"use_link_to_reset_password": "Benutzen Sie den Link, um Ihr Passwort zurückzusetzen",
|
||||||
"hey_there": "Hallo,",
|
"hey_there": "Hallo,",
|
||||||
"forgot_your_password_calcom": "Passwort vergessen? - Cal.com",
|
"forgot_your_password_calcom": "Passwort vergessen? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Event-Typ",
|
|
||||||
"delete_webhook_confirmation_message": "Sind Sie sicher, dass Sie diesen Webhook löschen möchten? Sie werden keine Cal.com Termindaten mehr erhalten.",
|
"delete_webhook_confirmation_message": "Sind Sie sicher, dass Sie diesen Webhook löschen möchten? Sie werden keine Cal.com Termindaten mehr erhalten.",
|
||||||
"confirm_delete_webhook": "Ja, Webhook löschen",
|
"confirm_delete_webhook": "Ja, Webhook löschen",
|
||||||
"edit_webhook": "Webhook bearbeiten",
|
"edit_webhook": "Webhook bearbeiten",
|
||||||
@@ -189,7 +188,7 @@
|
|||||||
"secret": "Passwort",
|
"secret": "Passwort",
|
||||||
"leave_blank_to_remove_secret": "Leer lassen, um Passwort zu entfernen",
|
"leave_blank_to_remove_secret": "Leer lassen, um Passwort zu entfernen",
|
||||||
"webhook_secret_key_description": "Stellen Sie sicher, dass Ihr Server aus Sicherheitsgründen nur die erwarteten Cal.com-Anfragen empfängt",
|
"webhook_secret_key_description": "Stellen Sie sicher, dass Ihr Server aus Sicherheitsgründen nur die erwarteten Cal.com-Anfragen empfängt",
|
||||||
"secret_meeting": "Geheimes Termin",
|
"secret_meeting": "Geheimer Termin",
|
||||||
"login_instead": "Stattdessen anmelden",
|
"login_instead": "Stattdessen anmelden",
|
||||||
"already_have_an_account": "Haben Sie bereits ein Konto?",
|
"already_have_an_account": "Haben Sie bereits ein Konto?",
|
||||||
"create_account": "Konto erstellen",
|
"create_account": "Konto erstellen",
|
||||||
@@ -245,7 +244,7 @@
|
|||||||
"where": "Wo",
|
"where": "Wo",
|
||||||
"add_to_calendar": "Zum Kalender hinzufügen",
|
"add_to_calendar": "Zum Kalender hinzufügen",
|
||||||
"add_another_calendar": "Einen weiteren Kalender hinzufügen",
|
"add_another_calendar": "Einen weiteren Kalender hinzufügen",
|
||||||
"other": "Anderes",
|
"other": "Sonstige",
|
||||||
"emailed_you_and_attendees": "Wir haben Ihnen und den anderen Teilnehmern eine Einladung zum Kalender mit allen Details zugeschickt.",
|
"emailed_you_and_attendees": "Wir haben Ihnen und den anderen Teilnehmern eine Einladung zum Kalender mit allen Details zugeschickt.",
|
||||||
"emailed_you_and_attendees_recurring": "Wir haben Ihnn und den anderen Teilnemern eine Kalendereinladung für den ersten Termin dieses wiederkehrendem Ereignisses gesendet.",
|
"emailed_you_and_attendees_recurring": "Wir haben Ihnn und den anderen Teilnemern eine Kalendereinladung für den ersten Termin dieses wiederkehrendem Ereignisses gesendet.",
|
||||||
"emailed_you_and_any_other_attendees": "Wir haben Ihnen und allen anderen Teilnehmer diesen Informationen per E-Mail geschickt.",
|
"emailed_you_and_any_other_attendees": "Wir haben Ihnen und allen anderen Teilnehmer diesen Informationen per E-Mail geschickt.",
|
||||||
@@ -255,7 +254,7 @@
|
|||||||
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} muss noch die Terminreihe des wiederkehrenden Termins bestätigen oder ablehnen.",
|
"user_needs_to_confirm_or_reject_booking_recurring": "{{user}} muss noch die Terminreihe des wiederkehrenden Termins bestätigen oder ablehnen.",
|
||||||
"meeting_is_scheduled": "Dieser Termin ist geplant",
|
"meeting_is_scheduled": "Dieser Termin ist geplant",
|
||||||
"meeting_is_scheduled_recurring": "Ihr wiederkehrender Termin wurde geplant",
|
"meeting_is_scheduled_recurring": "Ihr wiederkehrender Termin wurde geplant",
|
||||||
"submitted": "Ihr Termin wurde gebuhct",
|
"submitted": "Ihr Termin wurde gebucht",
|
||||||
"submitted_recurring": "Ihr wiederkehrender Termin wurde gebucht",
|
"submitted_recurring": "Ihr wiederkehrender Termin wurde gebucht",
|
||||||
"booking_submitted": "Ihre Buchung wurde versandt",
|
"booking_submitted": "Ihre Buchung wurde versandt",
|
||||||
"booking_submitted_recurring": "Ihre wiederkehrende Buchung wurde versandt",
|
"booking_submitted_recurring": "Ihre wiederkehrende Buchung wurde versandt",
|
||||||
@@ -266,6 +265,8 @@
|
|||||||
"enter_new_password": "Geben Sie das neue Passwort ein.",
|
"enter_new_password": "Geben Sie das neue Passwort ein.",
|
||||||
"reset_password": "Passwort zurücksetzen",
|
"reset_password": "Passwort zurücksetzen",
|
||||||
"change_your_password": "Passwort ändern",
|
"change_your_password": "Passwort ändern",
|
||||||
|
"show_password": "Passwort anzeigen",
|
||||||
|
"hide_password": "Passwort verbergen",
|
||||||
"try_again": "Erneut versuchen",
|
"try_again": "Erneut versuchen",
|
||||||
"request_is_expired": "Diese Anfrage ist abgelaufen.",
|
"request_is_expired": "Diese Anfrage ist abgelaufen.",
|
||||||
"reset_instructions": "Geben Sie die E-Mail-Adresse Ihres Kontos ein und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.",
|
"reset_instructions": "Geben Sie die E-Mail-Adresse Ihres Kontos ein und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.",
|
||||||
@@ -355,6 +356,7 @@
|
|||||||
"meeting_ended": "Meeting beendet",
|
"meeting_ended": "Meeting beendet",
|
||||||
"form_submitted": "Formular gesendet",
|
"form_submitted": "Formular gesendet",
|
||||||
"event_triggers": "Ereignis-Auslöser",
|
"event_triggers": "Ereignis-Auslöser",
|
||||||
|
"subscriber_url": "Subscriber-URL",
|
||||||
"create_new_webhook": "Einen neuen Webhook erstellen",
|
"create_new_webhook": "Einen neuen Webhook erstellen",
|
||||||
"webhooks": "Webhooks",
|
"webhooks": "Webhooks",
|
||||||
"team_webhooks": "Team Webhooks",
|
"team_webhooks": "Team Webhooks",
|
||||||
@@ -465,7 +467,7 @@
|
|||||||
"host_phone_number": "Ihre Telefonnummer",
|
"host_phone_number": "Ihre Telefonnummer",
|
||||||
"enter_phone_number": "Telefonnummer eingeben",
|
"enter_phone_number": "Telefonnummer eingeben",
|
||||||
"reschedule": "Neuplanen",
|
"reschedule": "Neuplanen",
|
||||||
"reschedule_this": "Stattdessen verschie",
|
"reschedule_this": "Stattdessen verschieben",
|
||||||
"book_a_team_member": "Teammitglied stattdessen buchen",
|
"book_a_team_member": "Teammitglied stattdessen buchen",
|
||||||
"or": "ODER",
|
"or": "ODER",
|
||||||
"go_back": "Zurück",
|
"go_back": "Zurück",
|
||||||
@@ -494,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "Lass uns als erstes den Administrator Benutzer anlegen.",
|
"lets_create_first_administrator_user": "Lass uns als erstes den Administrator Benutzer anlegen.",
|
||||||
"new_member": "Neues Mitglied",
|
"new_member": "Neues Mitglied",
|
||||||
"invite": "Einladen",
|
"invite": "Einladen",
|
||||||
|
"add_team_members": "Teammitglieder hinzufügen",
|
||||||
|
"add_team_members_description": "Lade andere ein, deinem Team beizutreten",
|
||||||
|
"add_team_member": "Teammitglied hinzufügen",
|
||||||
"invite_new_member": "Ein neues Mitglied einladen",
|
"invite_new_member": "Ein neues Mitglied einladen",
|
||||||
"invite_new_team_member": "Laden Sie jemanden in Ihr Team ein.",
|
"invite_new_team_member": "Laden Sie jemanden in Ihr Team ein.",
|
||||||
"change_member_role": "Rolle des Teammitglieds ändern",
|
"change_member_role": "Rolle des Teammitglieds ändern",
|
||||||
@@ -629,6 +634,7 @@
|
|||||||
"availability": "Verfügbarkeit",
|
"availability": "Verfügbarkeit",
|
||||||
"edit_availability": "Verfügbarkeit editieren",
|
"edit_availability": "Verfügbarkeit editieren",
|
||||||
"configure_availability": "Konfigurieren Sie die Zeiten, in denen Sie für Buchungen zur Verfügung stehen.",
|
"configure_availability": "Konfigurieren Sie die Zeiten, in denen Sie für Buchungen zur Verfügung stehen.",
|
||||||
|
"copy_times_to": "Zeiten kopieren in",
|
||||||
"change_weekly_schedule": "Wöchentliche Termine ändern",
|
"change_weekly_schedule": "Wöchentliche Termine ändern",
|
||||||
"logo": "Logo",
|
"logo": "Logo",
|
||||||
"error": "Fehler",
|
"error": "Fehler",
|
||||||
@@ -643,6 +649,7 @@
|
|||||||
"event_name_tooltip": "Der Name, der in Kalendern angezeigt wird",
|
"event_name_tooltip": "Der Name, der in Kalendern angezeigt wird",
|
||||||
"meeting_with_user": "Meeting mit {ATTENDEE}",
|
"meeting_with_user": "Meeting mit {ATTENDEE}",
|
||||||
"additional_inputs": "Zusätzliche Notizen",
|
"additional_inputs": "Zusätzliche Notizen",
|
||||||
|
"additional_input_description": "Erfordert die Eingabe zusätzlicher Eingaben durch den Planer vor der Buchungsbestätigung",
|
||||||
"label": "Bezeichnung",
|
"label": "Bezeichnung",
|
||||||
"placeholder": "Placeholder",
|
"placeholder": "Placeholder",
|
||||||
"type": "Typ",
|
"type": "Typ",
|
||||||
@@ -725,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "Zusätzlichen Kalender verbinden",
|
"connect_additional_calendar": "Zusätzlichen Kalender verbinden",
|
||||||
"conferencing": "Videokonferenzen",
|
"conferencing": "Videokonferenzen",
|
||||||
"calendar": "Kalender",
|
"calendar": "Kalender",
|
||||||
|
"payments": "Zahlungen",
|
||||||
"not_installed": "Nicht installiert",
|
"not_installed": "Nicht installiert",
|
||||||
"error_password_mismatch": "Passwörter stimmen nicht überein.",
|
"error_password_mismatch": "Passwörter stimmen nicht überein.",
|
||||||
"error_required_field": "Dieses Feld ist erforderlich.",
|
"error_required_field": "Dieses Feld ist erforderlich.",
|
||||||
@@ -765,6 +773,15 @@
|
|||||||
"trending_apps": "Angesagte Apps",
|
"trending_apps": "Angesagte Apps",
|
||||||
"explore_apps": "{{category}} Apps",
|
"explore_apps": "{{category}} Apps",
|
||||||
"installed_apps": "Installierte Apps",
|
"installed_apps": "Installierte Apps",
|
||||||
|
"no_category_apps": "Keine {{category}} Apps",
|
||||||
|
"no_category_apps_description_calendar": "Fügen Sie eine Kalender-App hinzu, in der nach Konflikten gesucht werden soll, um Doppelbuchungen zu vermeiden",
|
||||||
|
"no_category_apps_description_conferencing": "Versuchen Sie, eine Konferenz-App hinzuzufügen, um Videoanrufe mit Ihren Kunden zu integrieren",
|
||||||
|
"no_category_apps_description_payment": "Fügen Sie eine Zahlungs-App hinzu, um die Transaktion zwischen Ihnen und Ihren Kunden zu erleichtern",
|
||||||
|
"no_category_apps_description_other": "Füge jede beliebige andere Art von App hinzu, um alle möglichen Dinge zu tun",
|
||||||
|
"installed_app_calendar_description": "Legen Sie den/die Kalender in denen nach Konflikten gesucht werden sollen fest, um Doppelbuchungen zu vermeiden.",
|
||||||
|
"installed_app_conferencing_description": "Fügen Sie Ihre liebsten Videokonferenz-Apps für Ihre Meetings hinzu",
|
||||||
|
"installed_app_payment_description": "Konfigurieren Sie die Zahlungsdienstleister, welcher bei der Belastung Ihrer Kunden verwendet werden sollen.",
|
||||||
|
"installed_app_other_description": "Alle von Ihnen installierten Apps aus anderen Kategorien.",
|
||||||
"empty_installed_apps_headline": "Keine Apps installiert",
|
"empty_installed_apps_headline": "Keine Apps installiert",
|
||||||
"empty_installed_apps_description": "Apps erlauben es Ihnen, Ihren Arbeitsfluss zu verbessern und Ihre Planung viel besser zu gestalten.",
|
"empty_installed_apps_description": "Apps erlauben es Ihnen, Ihren Arbeitsfluss zu verbessern und Ihre Planung viel besser zu gestalten.",
|
||||||
"empty_installed_apps_button": "Entdecken Sie den App Store",
|
"empty_installed_apps_button": "Entdecken Sie den App Store",
|
||||||
@@ -803,6 +820,8 @@
|
|||||||
"set_to_default": "Auf Standard setzen",
|
"set_to_default": "Auf Standard setzen",
|
||||||
"new_schedule_btn": "Neuer Verfügbarkeitsplan",
|
"new_schedule_btn": "Neuer Verfügbarkeitsplan",
|
||||||
"add_new_schedule": "Neuen Verfügbarkeitsplan hinzufügen",
|
"add_new_schedule": "Neuen Verfügbarkeitsplan hinzufügen",
|
||||||
|
"add_new_calendar": "Neuen Kalender hinzufügen",
|
||||||
|
"set_calendar": "Legen Sie fest, wo neue Events hinzugefügt werden sollen, wenn Sie gebucht werden.",
|
||||||
"delete_schedule": "Verfügbarkeitsplan löschen",
|
"delete_schedule": "Verfügbarkeitsplan löschen",
|
||||||
"schedule_created_successfully": "{{scheduleName}} -Verfügbarkeitsplan erfolgreich erstellt",
|
"schedule_created_successfully": "{{scheduleName}} -Verfügbarkeitsplan erfolgreich erstellt",
|
||||||
"availability_updated_successfully": "Verfügbarkeit erfolgreich aktualisiert",
|
"availability_updated_successfully": "Verfügbarkeit erfolgreich aktualisiert",
|
||||||
@@ -818,7 +837,6 @@
|
|||||||
"redirect_success_booking": "Weiterleitung bei Buchung ",
|
"redirect_success_booking": "Weiterleitung bei Buchung ",
|
||||||
"you_are_being_redirected": "Sie werden in $t(second, {\"count\": {{seconds}} }) auf {{ url }} weitergeleitet.",
|
"you_are_being_redirected": "Sie werden in $t(second, {\"count\": {{seconds}} }) auf {{ url }} weitergeleitet.",
|
||||||
"external_redirect_url": "Externe Umleitungs-URL - Beginnt mit https://",
|
"external_redirect_url": "Externe Umleitungs-URL - Beginnt mit https://",
|
||||||
"redirect_url_upgrade_description": "Um diese Funktion nutzen zu können, müssen Sie ein Upgrade auf einen Pro-Account durchführen.",
|
|
||||||
"duplicate": "Duplizieren",
|
"duplicate": "Duplizieren",
|
||||||
"offer_seats": "Plätze anbieten",
|
"offer_seats": "Plätze anbieten",
|
||||||
"offer_seats_description": "Bieten Sie Plätze für Buchungen an (dies deaktiviert Gäste & Opt-in-Buchungen)",
|
"offer_seats_description": "Bieten Sie Plätze für Buchungen an (dies deaktiviert Gäste & Opt-in-Buchungen)",
|
||||||
@@ -984,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "Da Sie von einem Standard- zu einem Premium-Benutzernamen wechseln, werden Sie zum Upgrade zur Kasse gebracht.",
|
"change_username_standard_to_premium": "Da Sie von einem Standard- zu einem Premium-Benutzernamen wechseln, werden Sie zum Upgrade zur Kasse gebracht.",
|
||||||
"change_username_premium_to_standard": "Da Sie von einem Premium- zu einem Standard-Benutzernamen wechseln, werden Sie zum Downgrade zur Kasse gebracht.",
|
"change_username_premium_to_standard": "Da Sie von einem Premium- zu einem Standard-Benutzernamen wechseln, werden Sie zum Downgrade zur Kasse gebracht.",
|
||||||
"go_to_stripe_billing": "Zur Abrechnung",
|
"go_to_stripe_billing": "Zur Abrechnung",
|
||||||
|
"stripe_description": "Zahlung für Buchungen (0,5 % + 0,10 € Provision pro Transaktion)",
|
||||||
"trial_expired": "Ihre Testversion ist abgelaufen",
|
"trial_expired": "Ihre Testversion ist abgelaufen",
|
||||||
"remove_app": "App entfernen",
|
"remove_app": "App entfernen",
|
||||||
"yes_remove_app": "Ja, App entfernen",
|
"yes_remove_app": "Ja, App entfernen",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "Sind Sie sicher, dass Sie diese App entfernen möchten?",
|
"are_you_sure_you_want_to_remove_this_app": "Sind Sie sicher, dass Sie diese App entfernen möchten?",
|
||||||
|
"app_removed_successfully": "App erfolgreich entfernt",
|
||||||
|
"error_removing_app": "Fehler beim Entfernen der App",
|
||||||
"web_conference": "Webkonferenz",
|
"web_conference": "Webkonferenz",
|
||||||
"number_for_sms_reminders": "Telefonnummer (für SMS-Erinnerungen)",
|
"number_for_sms_reminders": "Telefonnummer (für SMS-Erinnerungen)",
|
||||||
"requires_confirmation": "Erfordert Bestätigung",
|
"requires_confirmation": "Erfordert Bestätigung",
|
||||||
@@ -1043,6 +1064,8 @@
|
|||||||
"navigate": "Navigieren",
|
"navigate": "Navigieren",
|
||||||
"open": "Öffnen",
|
"open": "Öffnen",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
|
"team_feature_teams": "Dies ist eine Team-Funktion. Sie müssen auf die Team-Version upgraden, um die Verfügbarkeit Ihres Teams zu sehen.",
|
||||||
|
"team_feature_workflows": "Dies ist eine Team-Funktion. Sie müssen auf die Team-Version upgraden, um Ihre Termin-Benachrichtigungen und Erinnerungen mit Workflows zu automatisieren.",
|
||||||
"show_eventtype_on_profile": "Im Profil anzeigen",
|
"show_eventtype_on_profile": "Im Profil anzeigen",
|
||||||
"embed": "Einbetten",
|
"embed": "Einbetten",
|
||||||
"new_username": "Neuer Benutzername",
|
"new_username": "Neuer Benutzername",
|
||||||
@@ -1058,10 +1081,10 @@
|
|||||||
"using_additional_inputs_as_variables": "Wie kann ich zusätzliche Eingaben als Variablen verwenden?",
|
"using_additional_inputs_as_variables": "Wie kann ich zusätzliche Eingaben als Variablen verwenden?",
|
||||||
"download_desktop_app": "Desktop-App herunterladen",
|
"download_desktop_app": "Desktop-App herunterladen",
|
||||||
"set_ping_link": "Ping-Link festlegen",
|
"set_ping_link": "Ping-Link festlegen",
|
||||||
"rate_limit_exceeded": "Bewertungslimit überschritten",
|
"rate_limit_exceeded": "Anmeldeversuchsgrenze überschritten",
|
||||||
"when_something_happens": "Wenn etwas passiert",
|
"when_something_happens": "Wenn etwas passiert",
|
||||||
"action_is_performed": "Eine Aktion wird ausgeführt",
|
"action_is_performed": "Eine Aktion wird ausgeführt",
|
||||||
"test_action": "Test-Aktion",
|
"test_action": "Aktion testen",
|
||||||
"notification_sent": "Benachrichtigung gesendet",
|
"notification_sent": "Benachrichtigung gesendet",
|
||||||
"no_input": "Kein Input",
|
"no_input": "Kein Input",
|
||||||
"test_workflow_action": "Workflow-Aktion testen",
|
"test_workflow_action": "Workflow-Aktion testen",
|
||||||
@@ -1076,10 +1099,13 @@
|
|||||||
"event_limit_tab_description": "Wie oft können Sie gebucht werden",
|
"event_limit_tab_description": "Wie oft können Sie gebucht werden",
|
||||||
"event_advanced_tab_description": "Kalendereinstellungen & mehr...",
|
"event_advanced_tab_description": "Kalendereinstellungen & mehr...",
|
||||||
"event_advanced_tab_title": "Erweitert",
|
"event_advanced_tab_title": "Erweitert",
|
||||||
|
"select_which_cal": "Wählen Sie den Kalender aus, zu dem Buchungen hinzugefügt werden sollen",
|
||||||
"custom_event_name": "Eigener Ereignisname",
|
"custom_event_name": "Eigener Ereignisname",
|
||||||
|
"custom_event_name_description": "Erstellen Sie benutzerdefinierte Ereignisnamen, die im Kalenderereignis angezeigt werden sollen",
|
||||||
"2fa_required": "Zwei-Faktor-Authentifizierung erforderlich",
|
"2fa_required": "Zwei-Faktor-Authentifizierung erforderlich",
|
||||||
"incorrect_2fa": "Falscher Zwei-Faktor-Authentifizierungscode",
|
"incorrect_2fa": "Falscher Zwei-Faktor-Authentifizierungscode",
|
||||||
"which_event_type_apply": "Auf welchen Ereignistyp wird dies angewandt?",
|
"which_event_type_apply": "Auf welchen Ereignistyp wird dies angewandt?",
|
||||||
|
"no_workflows_description": "Workflows ermöglichen die einfache Automatisierung des Versands von Benachrichtigungen und Erinnerungen, so dass Sie Prozesse rund um Ihre Ereignisse erstellen können.",
|
||||||
"create_workflow": "Einen Workflow erstellen",
|
"create_workflow": "Einen Workflow erstellen",
|
||||||
"do_this": "Mache dies",
|
"do_this": "Mache dies",
|
||||||
"turn_off": "Abschalten",
|
"turn_off": "Abschalten",
|
||||||
@@ -1088,8 +1114,10 @@
|
|||||||
"personal_cal_url": "Meine persönliche Cal. com URL",
|
"personal_cal_url": "Meine persönliche Cal. com URL",
|
||||||
"bio_hint": "Schreiben Sie eine kurze Beschreibung, welche auf Ihrer persönlichen Url-Seite erscheinen wird.",
|
"bio_hint": "Schreiben Sie eine kurze Beschreibung, welche auf Ihrer persönlichen Url-Seite erscheinen wird.",
|
||||||
"delete_account_modal_title": "Account löschen",
|
"delete_account_modal_title": "Account löschen",
|
||||||
|
"confirm_delete_account_modal": "Sind Sie sicher, dass Sie Ihr Cal.com-Konto löschen möchten?",
|
||||||
"delete_my_account": "Meinen Account löschen",
|
"delete_my_account": "Meinen Account löschen",
|
||||||
"start_of_week": "Wochenstart",
|
"start_of_week": "Wochenstart",
|
||||||
|
"select_calendars": "Wählen Sie aus, in welchen Kalendern Sie nach Konflikten suchen wollen, um Doppelbuchungen zu vermeiden.",
|
||||||
"check_for_conflicts": "Auf Konflikte prüfen",
|
"check_for_conflicts": "Auf Konflikte prüfen",
|
||||||
"adding_events_to": "Ereignisse hinzufügen zu",
|
"adding_events_to": "Ereignisse hinzufügen zu",
|
||||||
"follow_system_preferences": "Systemeinstellungen folgen",
|
"follow_system_preferences": "Systemeinstellungen folgen",
|
||||||
@@ -1101,32 +1129,46 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"web3": "Web3",
|
"web3": "Web3",
|
||||||
"rainbow_token_gated": "Dieser Ereignistyp ist durch einen Token geschützt.",
|
"rainbow_token_gated": "Dieser Ereignistyp ist durch einen Token geschützt.",
|
||||||
|
"rainbow_connect_wallet_gate": "Verbinden Sie Ihre Wallet, falls Sie <1>{{name}}</1> (<3>{{symbol}}</3>) besitzen.",
|
||||||
|
"rainbow_insufficient_balance": "Ihre verbundene Wallet enthält nicht genug <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "Unterschreiben Sie die Nachrichtenanfrage in Ihrer Wallet.",
|
||||||
|
"rainbow_signature_error": "Fehler beim Anfordern der Signatur von Ihrer Wallet.",
|
||||||
"token_address": "Adresse des Token",
|
"token_address": "Adresse des Token",
|
||||||
"blockchain": "Blockchain",
|
"blockchain": "Blockchain",
|
||||||
"old_password": "Altes Passwort",
|
"old_password": "Altes Passwort",
|
||||||
"secure_password": "Ihr sicheres neues Passwort",
|
"secure_password": "Ihr sicheres neues Passwort",
|
||||||
"error_updating_password": "Fehler beim aktualisieren des Passworts",
|
"error_updating_password": "Fehler beim aktualisieren des Passworts",
|
||||||
"two_factor_auth": "Zwei-Faktor-Authentifizierung",
|
"two_factor_auth": "Zwei-Faktor-Authentifizierung",
|
||||||
|
"recurring_event_tab_description": "Einen wiederholenden Zeitplan einrichten",
|
||||||
"today": "heute",
|
"today": "heute",
|
||||||
"appearance": "Aussehen",
|
"appearance": "Darstellung",
|
||||||
|
"appearance_subtitle": "Einstellungen für Ihre Buchungsdarstellung verwalten",
|
||||||
"my_account": "Mein Account",
|
"my_account": "Mein Account",
|
||||||
"general": "Allgemein",
|
"general": "Allgemein",
|
||||||
"calendars": "Kalender",
|
"calendars": "Kalender",
|
||||||
"2fa_auth": "2 Faktor-Authentifizierung",
|
"2fa_auth": "2 Faktor-Authentifizierung",
|
||||||
"invoices": "Rechnungen",
|
"invoices": "Rechnungen",
|
||||||
|
"embeds": "Embeds",
|
||||||
"impersonation": "Benutzeridentitätswechsel",
|
"impersonation": "Benutzeridentitätswechsel",
|
||||||
"users": "Benutzer",
|
"users": "Benutzer",
|
||||||
"profile_description": "Einstellungen für Ihr Cal.com Profil verwalten",
|
"profile_description": "Einstellungen für Ihr Cal.com Profil verwalten",
|
||||||
"general_description": "Einstellungen für Ihre Sprache und Zeitzone verwalten",
|
"general_description": "Einstellungen für Ihre Sprache und Zeitzone verwalten",
|
||||||
"calendars_description": "Konfigurieren Sie, wie Ihre Event-Typen mit Ihren Kalendern interagieren sollen",
|
"calendars_description": "Konfigurieren Sie, wie Ihre Event-Typen mit Ihren Kalendern interagieren sollen",
|
||||||
|
"appearance_description": "Einstellungen für Ihre Buchungsdarstellung verwalten",
|
||||||
"conferencing_description": "Verwalten Sie Ihre Video-Konferenz-Apps für Ihre Meetings",
|
"conferencing_description": "Verwalten Sie Ihre Video-Konferenz-Apps für Ihre Meetings",
|
||||||
"password_description": "Einstellungen für Ihre Konto-Passwörter verwalten",
|
"password_description": "Einstellungen für Ihre Konto-Passwörter verwalten",
|
||||||
|
"2fa_description": "Einstellungen für Ihre Konto-Passwörter verwalten",
|
||||||
"we_just_need_basic_info": "Wir benötigen nur ein paar grundlegende Informationen, um Ihr Profil einzurichten.",
|
"we_just_need_basic_info": "Wir benötigen nur ein paar grundlegende Informationen, um Ihr Profil einzurichten.",
|
||||||
"skip": "Überspringen",
|
"skip": "Überspringen",
|
||||||
"do_this_later": "Später machen",
|
"do_this_later": "Später machen",
|
||||||
"set_availability_getting_started_subtitle_1": "Zeiträume definieren, in denen Sie verfügbar sind",
|
"set_availability_getting_started_subtitle_1": "Zeiträume definieren, in denen Sie verfügbar sind",
|
||||||
"set_availability_getting_started_subtitle_2": "Sie können dies alles später auf der Verfügbarkeitsseite anpassen.",
|
"set_availability_getting_started_subtitle_2": "Sie können dies alles später auf der Verfügbarkeitsseite anpassen.",
|
||||||
"connect_calendars_from_app_store": "Sie können weitere Kalender aus dem App-Store hinzufügen",
|
"connect_calendars_from_app_store": "Sie können weitere Kalender aus dem App-Store hinzufügen",
|
||||||
|
"connect_conference_apps": "Konferenz-Apps verbinden",
|
||||||
|
"connect_calendar_apps": "Kalender-Apps verbinden",
|
||||||
|
"connect_payment_apps": "Zahlungs-Apps verbinden",
|
||||||
|
"connect_other_apps": "Andere Apps verbinden",
|
||||||
|
"current_step_of_total": "Schritt {{currentStep}} von {{maxSteps}}",
|
||||||
"add_variable": "Variable hinzufügen",
|
"add_variable": "Variable hinzufügen",
|
||||||
"custom_phone_number": "Benutzerdefinierte Telefonnummer",
|
"custom_phone_number": "Benutzerdefinierte Telefonnummer",
|
||||||
"message_template": "Nachrichtenvorlage",
|
"message_template": "Nachrichtenvorlage",
|
||||||
@@ -1138,13 +1180,25 @@
|
|||||||
"location_info": "Der Ort des Events",
|
"location_info": "Der Ort des Events",
|
||||||
"organizer_name_info": "Ihr Name",
|
"organizer_name_info": "Ihr Name",
|
||||||
"additional_notes_info": "Die zusätzlichen Anmerkungen der Buchung",
|
"additional_notes_info": "Die zusätzlichen Anmerkungen der Buchung",
|
||||||
"attendee_name_info": "Der Name der Buchenden",
|
"attendee_name_info": "Name der buchenden Person",
|
||||||
"to": "An",
|
"to": "An",
|
||||||
"attendee_required_enter_number": "Hier muss der Teilnehmer bei der Buchung eine Telefonnummer eingeben",
|
"attendee_required_enter_number": "Hier muss der Teilnehmer bei der Buchung eine Telefonnummer eingeben",
|
||||||
|
"workflow_turned_on_successfully": "{{workflowName}} Workflow erfolgreich {{offOn}}geschaltet",
|
||||||
"download_responses": "Antworten herunterladen",
|
"download_responses": "Antworten herunterladen",
|
||||||
"create_your_first_form": "Erstellen Sie Ihr erstes Formular",
|
"create_your_first_form": "Erstellen Sie Ihr erstes Formular",
|
||||||
|
"create_your_first_form_description": "Mithilfe von Leitungsformularen können Sie qualifizierende Fragen stellen und zur richtigen Person oder zum richtigen Veranstaltungstyp weiterleiten.",
|
||||||
|
"create_your_first_webhook": "Erstellen Sie Ihren ersten Webhook",
|
||||||
|
"create_your_first_webhook_description": "Mit Webhooks können Sie Meetingdaten in Echtzeit erhalten, sobald etwas auf Cal.com passiert.",
|
||||||
"for_a_maximum_of": "Für maximal",
|
"for_a_maximum_of": "Für maximal",
|
||||||
|
"event_one": "Ereignis",
|
||||||
|
"event_other": "Ereignisse",
|
||||||
|
"profile_team_description": "Einstellungen für Ihr Teamprofil verwalten",
|
||||||
|
"members_team_description": "Benutzer in der Gruppe",
|
||||||
|
"team_url": "Team-URL",
|
||||||
|
"delete_team": "Team löschen",
|
||||||
|
"team_members": "Teammitglieder",
|
||||||
"more": "Mehr",
|
"more": "Mehr",
|
||||||
|
"more_page_footer": "Wir betrachten die mobile Anwendung als Erweiterung der Web-Anwendung. Wenn Sie komplizierte Aktionen durchführen, verwenden Sie bitte die Web-Anwendung.",
|
||||||
"workflow_example_1": "Eine Erinnerung per Mail an die Teilnehmer verschicken, 24 Stunden bevor das Event startet",
|
"workflow_example_1": "Eine Erinnerung per Mail an die Teilnehmer verschicken, 24 Stunden bevor das Event startet",
|
||||||
"workflow_example_2": "Eine Erinnerung per SMS an die Teilnehmer verschicken, eine Stunde bevor das Event startet",
|
"workflow_example_2": "Eine Erinnerung per SMS an die Teilnehmer verschicken, eine Stunde bevor das Event startet",
|
||||||
"workflow_example_3": "Sende eine E-Mail an den Veranstalter, wenn das Ereignis abgebrochen wird",
|
"workflow_example_3": "Sende eine E-Mail an den Veranstalter, wenn das Ereignis abgebrochen wird",
|
||||||
@@ -1156,15 +1210,63 @@
|
|||||||
"connect_calendar_later": "Ich verbinde meinen Kalender später",
|
"connect_calendar_later": "Ich verbinde meinen Kalender später",
|
||||||
"set_my_availability_later": "Ich werde meine Verfügbarkeit später festlegen",
|
"set_my_availability_later": "Ich werde meine Verfügbarkeit später festlegen",
|
||||||
"problem_saving_user_profile": "Beim Speichern Ihrer Daten ist ein Problem aufgetreten. Bitte versuchen Sie es erneut oder wenden Sie sich an den Support.",
|
"problem_saving_user_profile": "Beim Speichern Ihrer Daten ist ein Problem aufgetreten. Bitte versuchen Sie es erneut oder wenden Sie sich an den Support.",
|
||||||
|
"purchase_missing_seats": "Fehlende Plätze kaufen",
|
||||||
|
"slot_length": "Zeitfensterlänge",
|
||||||
|
"booking_appearance": "Darstellung der Buchungsseite",
|
||||||
|
"appearance_team_description": "Einstellungen für die Buchungsdarstellung Ihres Teams verwalten",
|
||||||
|
"only_owner_change": "Nur der Besitzer dieses Teams kann Änderungen an den Buchungen des Teams vornehmen ",
|
||||||
|
"team_disable_cal_branding_description": "Entfernt alle Cal-bezogenen Markenzeichen, z.B. 'Powered by Cal.'",
|
||||||
|
"invited_by_team": "{{teamName}} hat Sie eingeladen, dem Team als {{role}} beizutreten",
|
||||||
"token_invalid_expired": "Token ist entweder ungültig oder abgelaufen.",
|
"token_invalid_expired": "Token ist entweder ungültig oder abgelaufen.",
|
||||||
"exchange_add": "Mit Microsoft Exchange verbinden",
|
"exchange_add": "Mit Microsoft Exchange verbinden",
|
||||||
"exchange_authentication": "Authentifizierungsmethode",
|
"exchange_authentication": "Authentifizierungsmethode",
|
||||||
"exchange_authentication_standard": "Basisauthentifizierung",
|
"exchange_authentication_standard": "Basisauthentifizierung",
|
||||||
"exchange_authentication_ntlm": "NTLM-Authentifizierung",
|
"exchange_authentication_ntlm": "NTLM-Authentifizierung",
|
||||||
"exchange_compression": "GZip-Kompression",
|
"exchange_compression": "GZip-Kompression",
|
||||||
|
"routing_forms_description": "Hier sehen Sie alle Formulare und Weiterleitungen, die Sie erstellt haben.",
|
||||||
|
"add_new_form": "Neues Formular hinzufügen",
|
||||||
|
"form_description": "Erstellen Sie Ihr Formular, um einen Bucher zu anzuleiten",
|
||||||
|
"copy_link_to_form": "Link in Formular kopieren",
|
||||||
|
"theme": "Theme",
|
||||||
|
"theme_applies_note": "Dies gilt nur für Ihre öffentlichen Buchungsseiten",
|
||||||
"theme_light": "Hell",
|
"theme_light": "Hell",
|
||||||
"theme_dark": "Dunkel",
|
"theme_dark": "Dunkel",
|
||||||
|
"theme_system": "Systemstandard",
|
||||||
|
"add_a_team": "Team hinzufügen",
|
||||||
|
"saml_config": "SAML-Konfiguration",
|
||||||
|
"add_webhook_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas auf Cal.com passiert",
|
||||||
|
"triggers_when": "Löst aus, wenn",
|
||||||
|
"test_webhook": "Bitte führen Sie einen Pingtest vor der Erstellung durch.",
|
||||||
|
"enable_webhook": "Webhook aktivieren",
|
||||||
|
"add_webhook": "Webhook hinzufügen",
|
||||||
|
"webhook_edited_successfully": "Webhook gespeichert",
|
||||||
|
"webhooks_description": "Erhalten Sie Meetingdaten in Echtzeit, wenn etwas auf Cal.com passiert",
|
||||||
|
"api_keys_description": "Generieren Sie API-Schlüssel für den Zugriff auf Ihren eigenen Account",
|
||||||
|
"new_api_key": "Neuer API-Schlüssel",
|
||||||
|
"active": "Aktiv",
|
||||||
|
"api_key_updated": "API-Schlüsselname aktualisiert",
|
||||||
|
"api_key_update_failed": "Fehler beim Aktualisieren des API-Schlüsselnamens",
|
||||||
|
"embeds_title": "HTML iframe-Einbettung",
|
||||||
|
"embeds_description": "Alle Event-Typen auf Ihrer Website einbetten",
|
||||||
|
"create_first_api_key": "Erstellen Sie Ihren ersten API-Schlüssel",
|
||||||
|
"create_first_api_key_description": "API-Schlüssel erlauben es anderen Apps, mit Cal.com zu kommunizieren",
|
||||||
"back_to_signin": "Zurück zur Anmeldung",
|
"back_to_signin": "Zurück zur Anmeldung",
|
||||||
|
"reset_link_sent": "Zurücksetzungslink gesendet",
|
||||||
|
"password_reset_email": "Eine E-Mail mit Anweisungen zum Zurücksetzen Ihres Passworts ist auf dem Weg zu {{email}}.",
|
||||||
"password_updated": "Passwort aktualisiert!",
|
"password_updated": "Passwort aktualisiert!",
|
||||||
"pending_payment": "Zahlung ausstehend"
|
"pending_payment": "Zahlung ausstehend",
|
||||||
|
"confirmation_page_rainbow": "Sperren Sie Ihr Ereignis hinter Tokens oder NFTs auf Ethereum, Polygon und mehr.",
|
||||||
|
"not_on_cal": "Nicht auf Cal.com",
|
||||||
|
"no_calendar_installed": "Kein Kalender installiert",
|
||||||
|
"no_calendar_installed_description": "Sie haben noch keinen Ihrer Kalender verbunden",
|
||||||
|
"add_a_calendar": "Kalender hinzufügen",
|
||||||
|
"change_email_hint": "Möglicherweise müssen Sie sich aus- und einloggen, um jegliche Änderung wirksam zu machen",
|
||||||
|
"confirm_password_change_email": "Bitte bestätigen Sie Ihr Passwort, bevor Sie Ihre E-Mail-Adresse ändern",
|
||||||
|
"seats": "Plätze",
|
||||||
|
"every_app_published": "Jede App, die im Cal.com App Store veröffentlicht wird, ist Open Source und gründlich durch Peer Reviews getestet. Cal.com, Inc. unterstützt oder zertifiziert diese Apps jedoch nicht, es sei denn, sie werden von Cal.com veröffentlicht. Wenn Sie auf unangemessene Inhalte oder Verhaltensweisen stoßen, melden Sie diese bitte.",
|
||||||
|
"report_app": "App melden",
|
||||||
|
"billing_manage_details_title": "Ihre Rechnungsdetails ansehen und verwalten",
|
||||||
|
"billing_manage_details_description": "Rechnungsdaten ansehen, bearbeiten oder Abonnement kündigen.",
|
||||||
|
"billing_help_title": "Brauchen Sie etwas anderes?",
|
||||||
|
"billing_help_description": "Wenn Sie weitere Hilfe bei der Rechnungsstellung benötigen, hilft Ihnen unser Support-Team gerne weiter."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Use the link below to reset your password",
|
"use_link_to_reset_password": "Use the link below to reset your password",
|
||||||
"hey_there": "Hey there,",
|
"hey_there": "Hey there,",
|
||||||
"forgot_your_password_calcom": "Forgot your password? - Cal.com",
|
"forgot_your_password_calcom": "Forgot your password? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Event Type",
|
|
||||||
"delete_webhook_confirmation_message": "Are you sure you want to delete this webhook? You will no longer receive Cal.com meeting data at a specified URL, in real-time, when an event is scheduled or canceled.",
|
"delete_webhook_confirmation_message": "Are you sure you want to delete this webhook? You will no longer receive Cal.com meeting data at a specified URL, in real-time, when an event is scheduled or canceled.",
|
||||||
"confirm_delete_webhook": "Yes, delete webhook",
|
"confirm_delete_webhook": "Yes, delete webhook",
|
||||||
"edit_webhook": "Edit Webhook",
|
"edit_webhook": "Edit Webhook",
|
||||||
@@ -206,7 +205,6 @@
|
|||||||
"2fa_enter_six_digit_code": "Enter the six-digit code from your authenticator app below.",
|
"2fa_enter_six_digit_code": "Enter the six-digit code from your authenticator app below.",
|
||||||
"create_an_account": "Create an account",
|
"create_an_account": "Create an account",
|
||||||
"dont_have_an_account": "Don't have an account?",
|
"dont_have_an_account": "Don't have an account?",
|
||||||
"i_dont_have_an_account": "I don't have an account",
|
|
||||||
"2fa_code": "Two-Factor Code",
|
"2fa_code": "Two-Factor Code",
|
||||||
"sign_in_account": "Sign in to your account",
|
"sign_in_account": "Sign in to your account",
|
||||||
"sign_in": "Sign in",
|
"sign_in": "Sign in",
|
||||||
@@ -235,7 +233,7 @@
|
|||||||
"welcome_back": "Welcome back",
|
"welcome_back": "Welcome back",
|
||||||
"welcome_to_calcom": "Welcome to Cal.com",
|
"welcome_to_calcom": "Welcome to Cal.com",
|
||||||
"welcome_instructions": "Tell us what to call you and let us know what timezone you’re in. You’ll be able to edit this later.",
|
"welcome_instructions": "Tell us what to call you and let us know what timezone you’re in. You’ll be able to edit this later.",
|
||||||
"connect_caldav": "Connect to CalDav Server",
|
"connect_caldav": "Connect to CalDav (Beta)",
|
||||||
"credentials_stored_and_encrypted": "Your credentials will be stored and encrypted.",
|
"credentials_stored_and_encrypted": "Your credentials will be stored and encrypted.",
|
||||||
"connect": "Connect",
|
"connect": "Connect",
|
||||||
"try_for_free": "Try it for free",
|
"try_for_free": "Try it for free",
|
||||||
@@ -315,6 +313,7 @@
|
|||||||
"past_bookings": "Your past bookings will show up here.",
|
"past_bookings": "Your past bookings will show up here.",
|
||||||
"cancelled_bookings": "Your cancelled bookings will show up here.",
|
"cancelled_bookings": "Your cancelled bookings will show up here.",
|
||||||
"unconfirmed_bookings": "Your unconfirmed bookings will show up here.",
|
"unconfirmed_bookings": "Your unconfirmed bookings will show up here.",
|
||||||
|
"unconfirmed_bookings_tooltip": "Unconfirmed bookings",
|
||||||
"on": "on",
|
"on": "on",
|
||||||
"and": "and",
|
"and": "and",
|
||||||
"calendar_shows_busy_between": "Your calendar shows you as busy between",
|
"calendar_shows_busy_between": "Your calendar shows you as busy between",
|
||||||
@@ -447,7 +446,7 @@
|
|||||||
"sunday": "Sunday",
|
"sunday": "Sunday",
|
||||||
"all_booked_today": "All booked today.",
|
"all_booked_today": "All booked today.",
|
||||||
"slots_load_fail": "Could not load the available time slots.",
|
"slots_load_fail": "Could not load the available time slots.",
|
||||||
"additional_guests": "Add guest",
|
"additional_guests": "Add guests",
|
||||||
"your_name": "Your name",
|
"your_name": "Your name",
|
||||||
"email_address": "Email address",
|
"email_address": "Email address",
|
||||||
"enter_valid_email": "Please enter a valid email",
|
"enter_valid_email": "Please enter a valid email",
|
||||||
@@ -634,7 +633,6 @@
|
|||||||
"billing": "Billing",
|
"billing": "Billing",
|
||||||
"manage_your_billing_info": "Manage your billing information and cancel your subscription.",
|
"manage_your_billing_info": "Manage your billing information and cancel your subscription.",
|
||||||
"availability": "Availability",
|
"availability": "Availability",
|
||||||
"availability_title": "{{availabilityTitle}} | Availability",
|
|
||||||
"edit_availability": "Edit availability",
|
"edit_availability": "Edit availability",
|
||||||
"configure_availability": "Configure times when you are available for bookings.",
|
"configure_availability": "Configure times when you are available for bookings.",
|
||||||
"copy_times_to": "Copy times to",
|
"copy_times_to": "Copy times to",
|
||||||
@@ -840,7 +838,7 @@
|
|||||||
"redirect_success_booking": "Redirect on booking ",
|
"redirect_success_booking": "Redirect on booking ",
|
||||||
"you_are_being_redirected": "You are being redirected to {{ url }} in $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "You are being redirected to {{ url }} in $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "In order to use this feature, you need to upgrade to a Pro account.",
|
"redirect_url_description": "Redirect to a custom URL after a successful booking",
|
||||||
"duplicate": "Duplicate",
|
"duplicate": "Duplicate",
|
||||||
"offer_seats": "Offer seats",
|
"offer_seats": "Offer seats",
|
||||||
"offer_seats_description": "Offer seats for booking. This automatically disables guest & opt-in bookings.",
|
"offer_seats_description": "Offer seats for booking. This automatically disables guest & opt-in bookings.",
|
||||||
@@ -925,13 +923,13 @@
|
|||||||
"zapier_setup_instructions": "<0>Log into your Zapier account and create a new Zap.</0><1>Select Cal.com as your Trigger app. Also choose a Trigger event.</1><2>Choose your account and then enter your Unique API Key.</2><3>Test your Trigger.</3><4>You're set!</4>",
|
"zapier_setup_instructions": "<0>Log into your Zapier account and create a new Zap.</0><1>Select Cal.com as your Trigger app. Also choose a Trigger event.</1><2>Choose your account and then enter your Unique API Key.</2><3>Test your Trigger.</3><4>You're set!</4>",
|
||||||
"install_zapier_app": "Please first install the Zapier App in the app store.",
|
"install_zapier_app": "Please first install the Zapier App in the app store.",
|
||||||
"connect_apple_server": "Connect to Apple Server",
|
"connect_apple_server": "Connect to Apple Server",
|
||||||
"connect_caldav_server": "Connect to CalDav Server",
|
"connect_caldav_server": "Connect to CalDav (Beta)",
|
||||||
"calendar_url": "Calendar URL",
|
"calendar_url": "Calendar URL",
|
||||||
"apple_server_generate_password": "Generate an app specific password to use with Cal.com at",
|
"apple_server_generate_password": "Generate an app specific password to use with Cal.com at",
|
||||||
"credentials_stored_encrypted": "Your credentials will be stored and encrypted.",
|
"credentials_stored_encrypted": "Your credentials will be stored and encrypted.",
|
||||||
"it_stored_encrypted": "It will be stored and encrypted.",
|
"it_stored_encrypted": "It will be stored and encrypted.",
|
||||||
"go_to_app_store": "Go to App Store",
|
"go_to_app_store": "Go to App Store",
|
||||||
"calendar_error": "Something went wrong, try reconnecting your calendar with all necessary permissions",
|
"calendar_error": "Try reconnecting your calendar with all necessary permissions",
|
||||||
"set_your_phone_number": "Set a phone number for the meeting",
|
"set_your_phone_number": "Set a phone number for the meeting",
|
||||||
"calendar_no_busy_slots": "There are no busy slots",
|
"calendar_no_busy_slots": "There are no busy slots",
|
||||||
"display_location_label": "Display on booking page",
|
"display_location_label": "Display on booking page",
|
||||||
@@ -1197,12 +1195,12 @@
|
|||||||
"event_one": "event",
|
"event_one": "event",
|
||||||
"event_other": "events",
|
"event_other": "events",
|
||||||
"profile_team_description": "Manage settings for your team profile",
|
"profile_team_description": "Manage settings for your team profile",
|
||||||
"members_team_description": "Users that are in the group. Apes together strong!",
|
"members_team_description": "Users that are in the group",
|
||||||
"team_url": "Team URL",
|
"team_url": "Team URL",
|
||||||
"delete_team": "Delete Team",
|
"delete_team": "Delete Team",
|
||||||
"team_members": "Team members",
|
"team_members": "Team members",
|
||||||
"more": "More",
|
"more": "More",
|
||||||
"more_page_footer": "We view the mobile application as an extension of the web application. If you are performing any complication actions, please refer back to the web application.",
|
"more_page_footer": "We view the mobile application as an extension of the web application. If you are performing any complicated actions, please refer back to the web application.",
|
||||||
"workflow_example_1": "Send SMS reminder 24 hours before event starts to attendee",
|
"workflow_example_1": "Send SMS reminder 24 hours before event starts to attendee",
|
||||||
"workflow_example_2": "Send custom SMS when event is rescheduled to attendee",
|
"workflow_example_2": "Send custom SMS when event is rescheduled to attendee",
|
||||||
"workflow_example_3": "Send custom email when new event is booked to host",
|
"workflow_example_3": "Send custom email when new event is booked to host",
|
||||||
@@ -1256,9 +1254,9 @@
|
|||||||
"create_first_api_key_description": "API keys allow other apps to communicate with Cal.com",
|
"create_first_api_key_description": "API keys allow other apps to communicate with Cal.com",
|
||||||
"back_to_signin": "Back to sign in",
|
"back_to_signin": "Back to sign in",
|
||||||
"reset_link_sent": "Reset link sent",
|
"reset_link_sent": "Reset link sent",
|
||||||
"password_reset_email":"An email is on it’s way to {{email}} with instructions to reset your password.",
|
"password_reset_email": "An email is on it’s way to {{email}} with instructions to reset your password.",
|
||||||
"password_reset_leading":"If you did not receive the email soon, check that the email address you entered is correct, check your spam folder or reach out to support if the issue persists.",
|
"password_reset_leading": "If you don't receive an email soon, check that the email address you entered is correct, check your spam folder or reach out to support if the issue persists.",
|
||||||
"password_updated":"Password updated!",
|
"password_updated": "Password updated!",
|
||||||
"pending_payment": "Pending payment",
|
"pending_payment": "Pending payment",
|
||||||
"confirmation_page_rainbow": "Token gate your event with tokens or NFTs on Ethereum, Polygon, and more.",
|
"confirmation_page_rainbow": "Token gate your event with tokens or NFTs on Ethereum, Polygon, and more.",
|
||||||
"not_on_cal": "Not on Cal.com",
|
"not_on_cal": "Not on Cal.com",
|
||||||
@@ -1267,5 +1265,39 @@
|
|||||||
"add_a_calendar": "Add a calendar",
|
"add_a_calendar": "Add a calendar",
|
||||||
"change_email_hint": "You may need to log out and back in to see any change take effect",
|
"change_email_hint": "You may need to log out and back in to see any change take effect",
|
||||||
"confirm_password_change_email": "Please confirm your password before changing your email address",
|
"confirm_password_change_email": "Please confirm your password before changing your email address",
|
||||||
"seats": "seats"
|
"seats": "seats",
|
||||||
|
"every_app_published": "Every app published on the Cal.com App Store is open source and thoroughly tested via peer reviews. Nevertheless, Cal.com, Inc. does not endorse or certify these apps unless they are published by Cal.com. If you encounter inappropriate content or behaviour please report it.",
|
||||||
|
"report_app": "Report app",
|
||||||
|
"team_name_required": "Team name required",
|
||||||
|
"how_additional_inputs_as_variables": "How to use Additional Inputs as Variables",
|
||||||
|
"format": "Format",
|
||||||
|
"uppercase_for_letters": "Use uppercase for all letters",
|
||||||
|
"replace_whitespaces_underscores": "Replace whitespaces with underscores",
|
||||||
|
"manage_billing": "Manage billing",
|
||||||
|
"manage_billing_description": "Manage all things billing",
|
||||||
|
"billing_freeplan_title": "You're currently on the FREE plan",
|
||||||
|
"billing_freeplan_description": "We work better in teams. Extend your workflows with round-robin and collective events and make advanced routing forms",
|
||||||
|
"billing_freeplan_cta": "Try now",
|
||||||
|
"billing_manage_details_title": "View and manage your billing details",
|
||||||
|
"billing_manage_details_description": "View and edit your billing details, as well as cancel your subscription.",
|
||||||
|
"billing_portal": "Billing portal",
|
||||||
|
"billing_help_title": "Need anything else?",
|
||||||
|
"billing_help_description": "If you need any further help with billing, our support team are here to help.",
|
||||||
|
"billing_help_cta": "Contact support",
|
||||||
|
"ignore_special_characters": "Ignore special characters in your Additional Input label. Use only letters and numbers",
|
||||||
|
"retry": "Retry",
|
||||||
|
"fetching_calendars_error": "There was a problem fetching your calendars. Please <1>try again</1> or reach out to customer support.",
|
||||||
|
"calendar_connection_fail": "Calendar connection failed",
|
||||||
|
"booking_confirmation_success": "Booking confirmation succeeded",
|
||||||
|
"booking_confirmation_fail": "Booking confirmation failed",
|
||||||
|
"we_wont_show_again": "We won't show this again",
|
||||||
|
"couldnt_update_timezone": "We couldn't update the timezone",
|
||||||
|
"updated_timezone_to": "Updated timezone to {{formattedCurrentTz}}",
|
||||||
|
"update_timezone": "Update timezone",
|
||||||
|
"update_timezone_question": "Update Timezone?",
|
||||||
|
"update_timezone_description": "It seems like your local timezone has changed to {{formattedCurrentTz}}. It's very important to have the correct timezone to prevent bookings at undesired times. Do you want to update it?",
|
||||||
|
"dont_update": "Don't update",
|
||||||
|
"email_address_action": "send email to a specific email address",
|
||||||
|
"after_event_trigger": "after event ends",
|
||||||
|
"how_long_after": "How long after event ends?"
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Utilice el enlace de abajo para restablecer su contraseña",
|
"use_link_to_reset_password": "Utilice el enlace de abajo para restablecer su contraseña",
|
||||||
"hey_there": "Hola,",
|
"hey_there": "Hola,",
|
||||||
"forgot_your_password_calcom": "¿Has olvidado tu contraseña? - Cal.com",
|
"forgot_your_password_calcom": "¿Has olvidado tu contraseña? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Tipo de Evento",
|
|
||||||
"delete_webhook_confirmation_message": "¿Está seguro de que desea eliminar este webhook? Ya no recibirá datos de reuniones de Cal.com en una URL específica, en tiempo real, cuando se programe o cancele un evento.",
|
"delete_webhook_confirmation_message": "¿Está seguro de que desea eliminar este webhook? Ya no recibirá datos de reuniones de Cal.com en una URL específica, en tiempo real, cuando se programe o cancele un evento.",
|
||||||
"confirm_delete_webhook": "Sí, elimina este webhook",
|
"confirm_delete_webhook": "Sí, elimina este webhook",
|
||||||
"edit_webhook": "Editar Webhook",
|
"edit_webhook": "Editar Webhook",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "Ver página pública",
|
"view_public_page": "Ver página pública",
|
||||||
"sign_out": "Cerrar sesión",
|
"sign_out": "Cerrar sesión",
|
||||||
"add_another": "Añadir otro",
|
"add_another": "Añadir otro",
|
||||||
|
"install_another": "Instalar otro",
|
||||||
"until": "hasta el",
|
"until": "hasta el",
|
||||||
"powered_by": "con tecnología de",
|
"powered_by": "con tecnología de",
|
||||||
"unavailable": "Indisponible",
|
"unavailable": "Indisponible",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "Casilla",
|
"checkbox": "Casilla",
|
||||||
"is_required": "Es requerido",
|
"is_required": "Es requerido",
|
||||||
"required": "Requerido",
|
"required": "Requerido",
|
||||||
|
"optional": "Opcional",
|
||||||
"input_type": "Tipo de entrada",
|
"input_type": "Tipo de entrada",
|
||||||
"rejected": "Rechazado",
|
"rejected": "Rechazado",
|
||||||
"unconfirmed": "Sin confirmar",
|
"unconfirmed": "Sin confirmar",
|
||||||
@@ -227,7 +228,9 @@
|
|||||||
"connect_your_calendar_instructions": "Conecta tu calendario para comprobar automáticamente los horarios ocupados y los nuevos eventos a medida que se programan.",
|
"connect_your_calendar_instructions": "Conecta tu calendario para comprobar automáticamente los horarios ocupados y los nuevos eventos a medida que se programan.",
|
||||||
"set_up_later": "Configurar más tarde",
|
"set_up_later": "Configurar más tarde",
|
||||||
"current_time": "Hora Actual",
|
"current_time": "Hora Actual",
|
||||||
|
"details": "Detalles",
|
||||||
"welcome": "Bienvenido",
|
"welcome": "Bienvenido",
|
||||||
|
"welcome_back": "Bienvenido de nuevo",
|
||||||
"welcome_to_calcom": "Bienvenido a Cal.com",
|
"welcome_to_calcom": "Bienvenido a Cal.com",
|
||||||
"welcome_instructions": "Cuéntanos cómo llamarte y dinos la zona horaria en la que estás. Podrás editarla más tarde.",
|
"welcome_instructions": "Cuéntanos cómo llamarte y dinos la zona horaria en la que estás. Podrás editarla más tarde.",
|
||||||
"connect_caldav": "Conectar con el servidor de CalDav",
|
"connect_caldav": "Conectar con el servidor de CalDav",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "Cuándo",
|
"when": "Cuándo",
|
||||||
"where": "Donde",
|
"where": "Donde",
|
||||||
"add_to_calendar": "Añadir al Calendario",
|
"add_to_calendar": "Añadir al Calendario",
|
||||||
|
"add_another_calendar": "Añadir otro calendario",
|
||||||
"other": "Otro",
|
"other": "Otro",
|
||||||
"emailed_you_and_attendees": "Le enviamos a usted y a los demás asistentes una invitación al calendario con todos los detalles.",
|
"emailed_you_and_attendees": "Le enviamos a usted y a los demás asistentes una invitación al calendario con todos los detalles.",
|
||||||
"emailed_you_and_attendees_recurring": "Le enviamos a usted y a los demás asistentes una invitación al calendario para el primero de estos eventos recurrentes.",
|
"emailed_you_and_attendees_recurring": "Le enviamos a usted y a los demás asistentes una invitación al calendario para el primero de estos eventos recurrentes.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "Introduce la nueva contraseña que te gustaría para tu cuenta.",
|
"enter_new_password": "Introduce la nueva contraseña que te gustaría para tu cuenta.",
|
||||||
"reset_password": "Restablecer Contraseña",
|
"reset_password": "Restablecer Contraseña",
|
||||||
"change_your_password": "Cambiar Contraseña",
|
"change_your_password": "Cambiar Contraseña",
|
||||||
|
"show_password": "Mostrar contraseña",
|
||||||
|
"hide_password": "Ocultar contraseña",
|
||||||
"try_again": "Volver a Intentarlo",
|
"try_again": "Volver a Intentarlo",
|
||||||
"request_is_expired": "Esta solicitud ha caducado.",
|
"request_is_expired": "Esta solicitud ha caducado.",
|
||||||
"reset_instructions": "Introduzca el email asociado a su cuenta y le enviaremos un enlace para restablecer su contraseña.",
|
"reset_instructions": "Introduzca el email asociado a su cuenta y le enviaremos un enlace para restablecer su contraseña.",
|
||||||
@@ -288,7 +294,7 @@
|
|||||||
"cannot_cancel_booking": "No puedes cancelar esta reserva",
|
"cannot_cancel_booking": "No puedes cancelar esta reserva",
|
||||||
"reschedule_instead": "En su lugar, también puedes reprogramarlo.",
|
"reschedule_instead": "En su lugar, también puedes reprogramarlo.",
|
||||||
"event_is_in_the_past": "El evento es en el pasado",
|
"event_is_in_the_past": "El evento es en el pasado",
|
||||||
"cancelling_event_recurring": "El evento es una instancia de un evento recurrente.",
|
"cancelling_event_recurring": "El evento es un caso de un evento recurrente.",
|
||||||
"cancelling_all_recurring": "Todas estas son instancias restantes en el evento recurrente.",
|
"cancelling_all_recurring": "Todas estas son instancias restantes en el evento recurrente.",
|
||||||
"error_with_status_code_occured": "Se produjo un error con el código de estado {{status}}.",
|
"error_with_status_code_occured": "Se produjo un error con el código de estado {{status}}.",
|
||||||
"booking_already_cancelled": "Esta reserva ya fue cancelada",
|
"booking_already_cancelled": "Esta reserva ya fue cancelada",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "Tan pronto como alguien reserve una reunión recurrente con usted, aparecerá aquí.",
|
"recurring_bookings": "Tan pronto como alguien reserve una reunión recurrente con usted, aparecerá aquí.",
|
||||||
"past_bookings": "Sus reservas pasadas aparecerán aquí.",
|
"past_bookings": "Sus reservas pasadas aparecerán aquí.",
|
||||||
"cancelled_bookings": "Las reservas canceladas aparecerán aquí.",
|
"cancelled_bookings": "Las reservas canceladas aparecerán aquí.",
|
||||||
|
"unconfirmed_bookings": "Las reservas sin confirmar aparecerán aquí.",
|
||||||
"on": "en",
|
"on": "en",
|
||||||
"and": "y",
|
"and": "y",
|
||||||
"calendar_shows_busy_between": "Tu calendario te muestra como ocupado entre",
|
"calendar_shows_busy_between": "Tu calendario te muestra como ocupado entre",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "Reserva Cancelada",
|
"booking_cancelled": "Reserva Cancelada",
|
||||||
"booking_rescheduled": "Reserva habilitada",
|
"booking_rescheduled": "Reserva habilitada",
|
||||||
"booking_created": "Reserva Creada",
|
"booking_created": "Reserva Creada",
|
||||||
|
"meeting_ended": "Reunión finalizada",
|
||||||
"form_submitted": "Formulario enviado",
|
"form_submitted": "Formulario enviado",
|
||||||
"event_triggers": "Activadores de Eventos",
|
"event_triggers": "Activadores de Eventos",
|
||||||
"subscriber_url": "Url del suscriptor",
|
"subscriber_url": "Url del suscriptor",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "Vamos a crear el primer usuario administrador.",
|
"lets_create_first_administrator_user": "Vamos a crear el primer usuario administrador.",
|
||||||
"new_member": "Nuevo Miembro",
|
"new_member": "Nuevo Miembro",
|
||||||
"invite": "Invitación",
|
"invite": "Invitación",
|
||||||
|
"add_team_members": "Añadir miembros del equipo",
|
||||||
|
"add_team_members_description": "Invite a otros para unirse a su equipo",
|
||||||
|
"add_team_member": "Añadir miembro del equipo",
|
||||||
"invite_new_member": "Invita a un Nuevo Miembro",
|
"invite_new_member": "Invita a un Nuevo Miembro",
|
||||||
"invite_new_team_member": "Invita a alguien a tu equipo.",
|
"invite_new_team_member": "Invita a alguien a tu equipo.",
|
||||||
"change_member_role": "Cambiar rol del miembro del equipo",
|
"change_member_role": "Cambiar rol del miembro del equipo",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "Crea tu primer equipo e invita a otros usuarios a trabajar contigo.",
|
"create_first_team_and_invite_others": "Crea tu primer equipo e invita a otros usuarios a trabajar contigo.",
|
||||||
"create_team_to_get_started": "Crea un equipo para empezar",
|
"create_team_to_get_started": "Crea un equipo para empezar",
|
||||||
"teams": "Equipos",
|
"teams": "Equipos",
|
||||||
|
"team": "Equipo",
|
||||||
"team_billing": "Facturación del equipo",
|
"team_billing": "Facturación del equipo",
|
||||||
"upgrade_to_flexible_pro_title": "Hemos cambiado la facturación de los equipos",
|
"upgrade_to_flexible_pro_title": "Hemos cambiado la facturación de los equipos",
|
||||||
"upgrade_to_flexible_pro_message": "Hay miembros en tu equipo sin asiento. Actualiza al plan Pro para cubrir los asientos restantes.",
|
"upgrade_to_flexible_pro_message": "Hay miembros en tu equipo sin asiento. Actualiza al plan Pro para cubrir los asientos restantes.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "Facturación",
|
"billing": "Facturación",
|
||||||
"manage_your_billing_info": "Gestione su información de facturación y cancele su suscripción.",
|
"manage_your_billing_info": "Gestione su información de facturación y cancele su suscripción.",
|
||||||
"availability": "Disponibilidad",
|
"availability": "Disponibilidad",
|
||||||
|
"edit_availability": "Editar disponibilidad",
|
||||||
"configure_availability": "Configure los horarios en los que está disponible para realizar reservas.",
|
"configure_availability": "Configure los horarios en los que está disponible para realizar reservas.",
|
||||||
|
"copy_times_to": "Copiar tiempos en",
|
||||||
"change_weekly_schedule": "Cambia tu Horario Semanal",
|
"change_weekly_schedule": "Cambia tu Horario Semanal",
|
||||||
"logo": "Logotipo",
|
"logo": "Logotipo",
|
||||||
"error": "Error",
|
"error": "Error",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "Nombre que aparecerá en los calendarios",
|
"event_name_tooltip": "Nombre que aparecerá en los calendarios",
|
||||||
"meeting_with_user": "Reunión con {ATTENDEE}",
|
"meeting_with_user": "Reunión con {ATTENDEE}",
|
||||||
"additional_inputs": "Campos Adicionales",
|
"additional_inputs": "Campos Adicionales",
|
||||||
|
"additional_input_description": "Requerir que el planificador introduzca entradas adicionales antes de confirmar la reserva",
|
||||||
"label": "Etiqueta",
|
"label": "Etiqueta",
|
||||||
"placeholder": "Marcador de posición",
|
"placeholder": "Marcador de posición",
|
||||||
"type": "Tipo",
|
"type": "Tipo",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "Desactivar Invitados",
|
"disable_guests": "Desactivar Invitados",
|
||||||
"disable_guests_description": "Desactiva agregar invitados adicionales al hacer la reserva.",
|
"disable_guests_description": "Desactiva agregar invitados adicionales al hacer la reserva.",
|
||||||
"private_link": "Generar una URL privada",
|
"private_link": "Generar una URL privada",
|
||||||
|
"private_link_label": "Enlace privado",
|
||||||
|
"private_link_hint": "Su enlace privado se regenera después de cada uso",
|
||||||
"copy_private_link": "Copiar enlace privado",
|
"copy_private_link": "Copiar enlace privado",
|
||||||
"private_link_description": "Generar una URL privada para compartir sin exponer su nombre de usuario de Cal",
|
"private_link_description": "Generar una URL privada para compartir sin exponer su nombre de usuario de Cal",
|
||||||
"invitees_can_schedule": "Los invitados pueden programar",
|
"invitees_can_schedule": "Los invitados pueden programar",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "¿Estás seguro de que quieres eliminar tu cuenta de Cal.com? Cualquier persona con la que hayas compartido el enlace de tu cuenta ya no podrá reservar con ella y cualquier preferencia que hayas guardado se perderá.",
|
"delete_account_confirmation_message": "¿Estás seguro de que quieres eliminar tu cuenta de Cal.com? Cualquier persona con la que hayas compartido el enlace de tu cuenta ya no podrá reservar con ella y cualquier preferencia que hayas guardado se perderá.",
|
||||||
"integrations": "Integraciones",
|
"integrations": "Integraciones",
|
||||||
"apps": "Aplicaciones",
|
"apps": "Aplicaciones",
|
||||||
|
"category_apps": "Aplicaciones {{category}}",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "Conectar personas, tecnología y lugar de trabajo.",
|
"app_store_description": "Conectar personas, tecnología y lugar de trabajo.",
|
||||||
"settings": "Ajustes",
|
"settings": "Ajustes",
|
||||||
"event_type_moved_successfully": "El tipo de evento se ha movido correctamente",
|
"event_type_moved_successfully": "El tipo de evento se ha movido correctamente",
|
||||||
|
"next_step_text": "Siguiente paso",
|
||||||
"next_step": "Saltar paso",
|
"next_step": "Saltar paso",
|
||||||
"prev_step": "Paso anterior",
|
"prev_step": "Paso anterior",
|
||||||
|
"install": "Instalar",
|
||||||
"installed": "Instalado",
|
"installed": "Instalado",
|
||||||
"active_install_one": "{{count}} instalación activa",
|
"active_install_one": "{{count}} instalación activa",
|
||||||
"active_install_other": "{{count}} instalaciones activas",
|
"active_install_other": "{{count}} instalaciones activas",
|
||||||
"globally_install": "Instalada globalmente",
|
"globally_install": "Instalada globalmente",
|
||||||
|
"app_successfully_installed": "Aplicación instalada correctamente",
|
||||||
|
"app_could_not_be_installed": "No se ha podido instalar la aplicación",
|
||||||
"disconnect": "Desconectar",
|
"disconnect": "Desconectar",
|
||||||
"embed_your_calendar": "Incorpora tu calendario en tu página web",
|
"embed_your_calendar": "Incorpora tu calendario en tu página web",
|
||||||
"connect_your_favourite_apps": "Conecta tus aplicaciones favoritas.",
|
"connect_your_favourite_apps": "Conecta tus aplicaciones favoritas.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "Conectar calendario adicional",
|
"connect_additional_calendar": "Conectar calendario adicional",
|
||||||
"conferencing": "Conferencias",
|
"conferencing": "Conferencias",
|
||||||
"calendar": "Calendario",
|
"calendar": "Calendario",
|
||||||
|
"payments": "Pagos",
|
||||||
"not_installed": "No instalado",
|
"not_installed": "No instalado",
|
||||||
"error_password_mismatch": "Las contraseñas no coinciden.",
|
"error_password_mismatch": "Las contraseñas no coinciden.",
|
||||||
"error_required_field": "Este campo es requerido.",
|
"error_required_field": "Este campo es requerido.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "Importar desde",
|
"import_from": "Importar desde",
|
||||||
"access_token": "Token de acceso",
|
"access_token": "Token de acceso",
|
||||||
"visit_roadmap": "Hoja de ruta",
|
"visit_roadmap": "Hoja de ruta",
|
||||||
|
"featured_categories": "Categorías destacadas",
|
||||||
"popular_categories": "Categorías populares",
|
"popular_categories": "Categorías populares",
|
||||||
|
"number_apps_one": "{{count}} aplicación",
|
||||||
|
"number_apps_other": "{{count}} aplicaciones",
|
||||||
"trending_apps": "Aplicaciones populares",
|
"trending_apps": "Aplicaciones populares",
|
||||||
|
"explore_apps": "Aplicaciones {{category}}",
|
||||||
"installed_apps": "Aplicaciones instaladas",
|
"installed_apps": "Aplicaciones instaladas",
|
||||||
|
"no_category_apps": "No hay aplicaciones {{category}}",
|
||||||
|
"no_category_apps_description_calendar": "Añada una aplicación de calendario para comprobar si hay conflictos y evitar reservas dobles",
|
||||||
|
"no_category_apps_description_conferencing": "Intente añadir una aplicación de conferencias para integrar las videollamadas con sus clientes",
|
||||||
|
"no_category_apps_description_payment": "Añada una aplicación de pagos para facilitar las transacciones con sus clientes",
|
||||||
|
"no_category_apps_description_other": "Añada cualquier otro tipo de aplicación para hacer todo tipo de tareas",
|
||||||
|
"installed_app_calendar_description": "Configure los calendarios para comprobar conflictos y evitar reservas dobles.",
|
||||||
|
"installed_app_conferencing_description": "Añada sus aplicaciones de videoconferencia favoritas para sus reuniones",
|
||||||
|
"installed_app_payment_description": "Configure qué servicios de procesamiento de pagos se van a usar al cobrarles a sus clientes.",
|
||||||
|
"installed_app_other_description": "Todas sus aplicaciones instaladas de otras categorías.",
|
||||||
"empty_installed_apps_headline": "No hay aplicaciones instaladas",
|
"empty_installed_apps_headline": "No hay aplicaciones instaladas",
|
||||||
"empty_installed_apps_description": "Las aplicaciones le permiten mejorar su flujo de trabajo y mejorar su tiempo calendario de forma significativa.",
|
"empty_installed_apps_description": "Las aplicaciones le permiten mejorar su flujo de trabajo y mejorar su tiempo calendario de forma significativa.",
|
||||||
"empty_installed_apps_button": "Explore la tienda de aplicaciones",
|
"empty_installed_apps_button": "Explore la tienda de aplicaciones",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "Eliminar",
|
"remove": "Eliminar",
|
||||||
"add": "Añadir",
|
"add": "Añadir",
|
||||||
"installed_one": "Instalado",
|
"installed_one": "Instalado",
|
||||||
|
"installed_other": "{{count}} instaladas",
|
||||||
"verify_wallet": "Verificar billetera",
|
"verify_wallet": "Verificar billetera",
|
||||||
"connect_metamask": "Conectar Metamask",
|
"connect_metamask": "Conectar Metamask",
|
||||||
"create_events_on": "Crear eventos en:",
|
"create_events_on": "Crear eventos en:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "Establecer como predeterminado",
|
"set_to_default": "Establecer como predeterminado",
|
||||||
"new_schedule_btn": "Nuevo horario",
|
"new_schedule_btn": "Nuevo horario",
|
||||||
"add_new_schedule": "Añadir un nuevo horario",
|
"add_new_schedule": "Añadir un nuevo horario",
|
||||||
|
"add_new_calendar": "Añadir un calendario nuevo",
|
||||||
|
"set_calendar": "Especifique dónde se añadirán los eventos nuevos cuando haya reservado.",
|
||||||
"delete_schedule": "Eliminar horario",
|
"delete_schedule": "Eliminar horario",
|
||||||
"schedule_created_successfully": "Horario {{scheduleName}} creado con éxito",
|
"schedule_created_successfully": "Horario {{scheduleName}} creado con éxito",
|
||||||
"availability_updated_successfully": "Disponibilidad actualizada correctamente",
|
"availability_updated_successfully": "Disponibilidad actualizada correctamente",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "Redirigir al reservar ",
|
"redirect_success_booking": "Redirigir al reservar ",
|
||||||
"you_are_being_redirected": "Serás redirigido a {{ url }} en $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "Serás redirigido a {{ url }} en $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "Para poder usar esta función, necesita actualizarse a una cuenta Pro.",
|
|
||||||
"duplicate": "Duplicar",
|
"duplicate": "Duplicar",
|
||||||
"offer_seats": "Ofrecer plazas",
|
"offer_seats": "Ofrecer plazas",
|
||||||
"offer_seats_description": "Ofrecer asientos para las reservas (desactiva las reservas de invitados y lsa optativas)",
|
"offer_seats_description": "Ofrecer asientos para las reservas (desactiva las reservas de invitados y lsa optativas)",
|
||||||
@@ -883,7 +921,7 @@
|
|||||||
"zapier_setup_instructions": "<0>Inicie sesión en su cuenta de Zapier y cree un nuevo Zap.</0><1>Seleccione Cal.com cómo su aplicación Trigger. También elija su evento Trigger.</1><2>Seleccione su cuenta e ingrese su Clave API única.</2><3>Pruebe su Trigger.</3><4>¡Listo!</4>",
|
"zapier_setup_instructions": "<0>Inicie sesión en su cuenta de Zapier y cree un nuevo Zap.</0><1>Seleccione Cal.com cómo su aplicación Trigger. También elija su evento Trigger.</1><2>Seleccione su cuenta e ingrese su Clave API única.</2><3>Pruebe su Trigger.</3><4>¡Listo!</4>",
|
||||||
"install_zapier_app": "Instale primero la aplicación Zapier desde la App Store.",
|
"install_zapier_app": "Instale primero la aplicación Zapier desde la App Store.",
|
||||||
"connect_apple_server": "Conectar con Apple Server",
|
"connect_apple_server": "Conectar con Apple Server",
|
||||||
"connect_caldav_server": "Conectar con CalDav Server",
|
"connect_caldav_server": "Conectar con CalDav (Beta)",
|
||||||
"calendar_url": "URL del calendario",
|
"calendar_url": "URL del calendario",
|
||||||
"apple_server_generate_password": "Genere una contraseña específica de la aplicación para utilizarla con Cal.com en",
|
"apple_server_generate_password": "Genere una contraseña específica de la aplicación para utilizarla con Cal.com en",
|
||||||
"credentials_stored_encrypted": "Sus credenciales serán almacenadas y cifradas.",
|
"credentials_stored_encrypted": "Sus credenciales serán almacenadas y cifradas.",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "Flujos de trabajo",
|
"workflows": "Flujos de trabajo",
|
||||||
"new_workflow_btn": "Flujo de trabajo nuevo",
|
"new_workflow_btn": "Flujo de trabajo nuevo",
|
||||||
"add_new_workflow": "Agregar un flujo de trabajo nuevo",
|
"add_new_workflow": "Agregar un flujo de trabajo nuevo",
|
||||||
|
"reschedule_event_trigger": "cuando el evento se vuelva a programar",
|
||||||
"trigger": "Desencadenante",
|
"trigger": "Desencadenante",
|
||||||
"triggers": "Desencadenantes",
|
"triggers": "Desencadenantes",
|
||||||
"action": "Acción",
|
"action": "Acción",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "Como estás cambiando de un nombre de usuario estándar a un nombre de usuario premium, se te llevará al pago para actualizarlo.",
|
"change_username_standard_to_premium": "Como estás cambiando de un nombre de usuario estándar a un nombre de usuario premium, se te llevará al pago para actualizarlo.",
|
||||||
"change_username_premium_to_standard": "Como estás cambiando de un nombre de usuario premium a un nombre de usuario estándar, se te llevará al pago para bajar de categoría.",
|
"change_username_premium_to_standard": "Como estás cambiando de un nombre de usuario premium a un nombre de usuario estándar, se te llevará al pago para bajar de categoría.",
|
||||||
"go_to_stripe_billing": "Ir a facturación",
|
"go_to_stripe_billing": "Ir a facturación",
|
||||||
|
"stripe_description": "Se requiere un pago para las reservas (0,5 % + 0,10 € de comisión por transacción)",
|
||||||
"trial_expired": "Tu prueba ha caducado",
|
"trial_expired": "Tu prueba ha caducado",
|
||||||
"remove_app": "Eliminar aplicación",
|
"remove_app": "Eliminar aplicación",
|
||||||
"yes_remove_app": "Sí, eliminar aplicación",
|
"yes_remove_app": "Sí, eliminar aplicación",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "¿Está seguro de que desea eliminar esta aplicación?",
|
"are_you_sure_you_want_to_remove_this_app": "¿Está seguro de que desea eliminar esta aplicación?",
|
||||||
|
"app_removed_successfully": "Aplicación eliminada correctamente",
|
||||||
|
"error_removing_app": "Error al eliminar la aplicación",
|
||||||
"web_conference": "Conferencia web",
|
"web_conference": "Conferencia web",
|
||||||
"number_for_sms_reminders": "Número de teléfono (para recordatorios de SMS)",
|
"number_for_sms_reminders": "Número de teléfono (para recordatorios de SMS)",
|
||||||
"requires_confirmation": "Requiere confirmación",
|
"requires_confirmation": "Requiere confirmación",
|
||||||
@@ -1022,18 +1064,209 @@
|
|||||||
"navigate": "Navegar",
|
"navigate": "Navegar",
|
||||||
"open": "Abrir",
|
"open": "Abrir",
|
||||||
"close": "Cerrar",
|
"close": "Cerrar",
|
||||||
|
"team_feature_teams": "Esta es una función Team. Actualice a Team para ver la disponibilidad de su equipo.",
|
||||||
|
"team_feature_workflows": "Esta es una función Team. Actualice a Team para automatizar los recordadorios y las notificaciones de eventos con flujos de trabajo.",
|
||||||
|
"show_eventtype_on_profile": "Mostrar en perfil",
|
||||||
"embed": "Insertar",
|
"embed": "Insertar",
|
||||||
"new_username": "Nombre de usuario nuevo",
|
"new_username": "Nombre de usuario nuevo",
|
||||||
"current_username": "Nombre de usuario actual",
|
"current_username": "Nombre de usuario actual",
|
||||||
"example_1": "Ejemplo 1",
|
"example_1": "Ejemplo 1",
|
||||||
"example_2": "Ejemplo 2",
|
"example_2": "Ejemplo 2",
|
||||||
|
"additional_input_label": "Etiqueta de entrada adicional",
|
||||||
"company_size": "Tamaño de la empresa",
|
"company_size": "Tamaño de la empresa",
|
||||||
"what_help_needed": "¿Con qué necesitas ayuda?",
|
"what_help_needed": "¿Con qué necesitas ayuda?",
|
||||||
"variable_format": "Formato variable",
|
"variable_format": "Formato variable",
|
||||||
|
"webhook_subscriber_url_reserved": "La URL del suscriptor de Webhook ya está definida",
|
||||||
|
"custom_input_as_variable_info": "Ignore todos los caracteres especiales de la etiqueta de entrada adicional (utilice solo letras y números), utilice mayúsculas para todas las letras y sustituya los espacios en blanco por guiones bajos.",
|
||||||
"using_additional_inputs_as_variables": "¿Cómo usar entradas adicionales como variables?",
|
"using_additional_inputs_as_variables": "¿Cómo usar entradas adicionales como variables?",
|
||||||
"download_desktop_app": "Descargar la aplicación de escritorio",
|
"download_desktop_app": "Descargar la aplicación de escritorio",
|
||||||
"set_ping_link": "Establecer enlace Ping",
|
"set_ping_link": "Establecer enlace Ping",
|
||||||
|
"rate_limit_exceeded": "Límite de tasa excedido",
|
||||||
|
"when_something_happens": "Cuando algo sucede",
|
||||||
|
"action_is_performed": "Se realiza una acción",
|
||||||
|
"test_action": "Probar acción",
|
||||||
|
"notification_sent": "Notificación enviada",
|
||||||
|
"no_input": "No hay entrada",
|
||||||
|
"test_workflow_action": "Probar acción de flujo de trabajo",
|
||||||
|
"send_sms": "Enviar SMS",
|
||||||
|
"send_sms_to_number": "¿Está seguro de que desea enviar un SMS al {{number}}?",
|
||||||
|
"missing_connected_calendar": "No hay ningún calendario predeterminado conectado",
|
||||||
|
"connect_your_calendar_and_link": "Puede conectar su calendario desde <1>aquí</1>.",
|
||||||
|
"default_calendar_selected": "Calendario predeterminado",
|
||||||
|
"hide_from_profile": "Ocultar del perfil",
|
||||||
|
"event_setup_tab_title": "Configuración del evento",
|
||||||
|
"event_limit_tab_title": "Límites",
|
||||||
|
"event_limit_tab_description": "Con qué frecuencia se puede reservar",
|
||||||
|
"event_advanced_tab_description": "Ajustes del calendario y más...",
|
||||||
|
"event_advanced_tab_title": "Avanzado",
|
||||||
|
"select_which_cal": "Seleccione a qué calendario añadir reservas",
|
||||||
|
"custom_event_name": "Nombre de evento personalizado",
|
||||||
|
"custom_event_name_description": "Cree nombres de eventos personalizados para que el evento aparezca en el calendario",
|
||||||
|
"2fa_required": "Se requiere autenticación de dos factores",
|
||||||
|
"incorrect_2fa": "Código de autenticación de dos factores incorrecto",
|
||||||
|
"which_event_type_apply": "¿A qué tipo de evento se aplicará esto?",
|
||||||
|
"no_workflows_description": "Los flujos de trabajo permiten una automatización simple para enviar notificaciones y recordatorios que le permiten crear procesos para sus eventos.",
|
||||||
|
"create_workflow": "Crear un flujo de trabajo",
|
||||||
|
"do_this": "Hacer esto",
|
||||||
|
"turn_off": "Apagar",
|
||||||
|
"settings_updated_successfully": "Configuración actualizada correctamente",
|
||||||
|
"error_updating_settings": "Error al actualizar la configuración",
|
||||||
|
"personal_cal_url": "Mi URL personal de Cal",
|
||||||
|
"bio_hint": "Algunas frases sobre usted, esta información aparecerá en la página de su URL personal.",
|
||||||
|
"delete_account_modal_title": "Eliminar cuenta",
|
||||||
|
"confirm_delete_account_modal": "¿Está seguro que desea eliminar su cuenta de Cal.com?",
|
||||||
|
"delete_my_account": "Eliminar mi cuenta",
|
||||||
|
"start_of_week": "Inicio de la semana",
|
||||||
|
"select_calendars": "Seleccione los calendarios en los que desee comprobar conflictos para evitar reservas dobles.",
|
||||||
|
"check_for_conflicts": "Comprobar conflictos",
|
||||||
|
"adding_events_to": "Agregando eventos a",
|
||||||
|
"follow_system_preferences": "Siga las preferencias del sistema",
|
||||||
|
"custom_brand_colors": "Colores de marca personalizados",
|
||||||
|
"customize_your_brand_colors": "Personalice el color de su propia marca en su página de reservas.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "Elimina cualquier marca relacionada con Cal, p. ej., \"Powered by Cal\".",
|
||||||
|
"profile_picture": "Imagen de perfil",
|
||||||
|
"upload": "Cargar",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "Este tipo de evento tiene acceso cerrado por token.",
|
||||||
|
"rainbow_connect_wallet_gate": "Conecte su billetera si posee <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "Su billetera conectada no contiene suficiente <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "Firme la solicitud de mensaje en su billetera.",
|
||||||
|
"rainbow_signature_error": "Error al solicitar la firma desde su billetera.",
|
||||||
|
"token_address": "Dirección del token",
|
||||||
|
"blockchain": "Blockchain",
|
||||||
|
"old_password": "Contraseña anterior",
|
||||||
|
"secure_password": "Su contraseña nueva supersegura",
|
||||||
|
"error_updating_password": "Error al actualizar la contraseña",
|
||||||
|
"two_factor_auth": "Autenticación de dos factores",
|
||||||
|
"recurring_event_tab_description": "Configurar un calendario repetitivo",
|
||||||
|
"today": "hoy",
|
||||||
|
"appearance": "Aspecto",
|
||||||
|
"appearance_subtitle": "Administre los ajustes para el aspecto de su reserva",
|
||||||
|
"my_account": "Mi cuenta",
|
||||||
|
"general": "General",
|
||||||
|
"calendars": "Calendarios",
|
||||||
|
"2fa_auth": "Autenticación de dos factores",
|
||||||
|
"invoices": "Facturas",
|
||||||
|
"embeds": "Inserciones",
|
||||||
|
"impersonation": "Suplantación",
|
||||||
|
"users": "Usuarios",
|
||||||
|
"profile_description": "Administre los ajustes para su perfil de Cal",
|
||||||
|
"general_description": "Administre los ajustes para su idioma y zona horaria",
|
||||||
|
"calendars_description": "Configure cómo deben interactuar sus tipos de eventos con sus calendarios",
|
||||||
|
"appearance_description": "Administre los ajustes para el aspecto de su reserva",
|
||||||
|
"conferencing_description": "Administre sus aplicaciones de videoconferencia para sus reuniones",
|
||||||
|
"password_description": "Administre los ajustes para las contraseñas de su cuenta",
|
||||||
|
"2fa_description": "Administre los ajustes para las contraseñas de su cuenta",
|
||||||
|
"we_just_need_basic_info": "Solo necesitamos información básica para configurar su perfil.",
|
||||||
|
"skip": "Omitir",
|
||||||
|
"do_this_later": "Hacerlo más tarde",
|
||||||
|
"set_availability_getting_started_subtitle_1": "Defina los intervalos de tiempo en los que esté disponible",
|
||||||
|
"set_availability_getting_started_subtitle_2": "Puede personalizar todo esto más tarde en la página de disponibilidad.",
|
||||||
|
"connect_calendars_from_app_store": "Puede añadir más calendarios desde la tienda de aplicaciones",
|
||||||
|
"connect_conference_apps": "Conectar aplicaciones de conferencia",
|
||||||
|
"connect_calendar_apps": "Conectar aplicaciones de calendario",
|
||||||
|
"connect_payment_apps": "Conectar aplicaciones de pago",
|
||||||
|
"connect_other_apps": "Conectar otras aplicaciones",
|
||||||
|
"current_step_of_total": "Paso {{currentStep}} de {{maxSteps}}",
|
||||||
|
"add_variable": "Añadir variable",
|
||||||
|
"custom_phone_number": "Número de teléfono personalizado",
|
||||||
|
"message_template": "Plantilla de mensaje",
|
||||||
|
"email_subject": "Asunto del correo electrónico",
|
||||||
|
"add_dynamic_variables": "Añadir variables de texto dinámico",
|
||||||
|
"event_name_info": "El nombre del tipo de evento",
|
||||||
|
"event_date_info": "La fecha del evento",
|
||||||
|
"event_time_info": "La hora de inicio del evento",
|
||||||
|
"location_info": "La ubicación del evento",
|
||||||
"organizer_name_info": "Tu Nombre",
|
"organizer_name_info": "Tu Nombre",
|
||||||
|
"additional_notes_info": "Las notas adicionales de la reserva",
|
||||||
|
"attendee_name_info": "El nombre de la persona que reserva",
|
||||||
|
"to": "Para",
|
||||||
|
"attendee_required_enter_number": "Será necesario que el asistente introduzca un número de teléfono al reservar",
|
||||||
|
"workflow_turned_on_successfully": "El flujo de trabajo {{workflowName}} se ajustó como {{offOn}} correctamente",
|
||||||
|
"download_responses": "Descargar respuestas",
|
||||||
|
"create_your_first_form": "Cree su primer formulario",
|
||||||
|
"create_your_first_form_description": "Con los formularios de orientación puede hacer preguntas de cualificación y llegar a la persona o tipo de evento correctos.",
|
||||||
|
"create_your_first_webhook": "Cree su primer Webhook",
|
||||||
|
"create_your_first_webhook_description": "Con Webhooks puede recibir datos de reuniones en tiempo real cuando suceda algo en Cal.com.",
|
||||||
|
"for_a_maximum_of": "Para un máximo de",
|
||||||
|
"event_one": "evento",
|
||||||
|
"event_other": "eventos",
|
||||||
|
"profile_team_description": "Administre ajustes para el perfil de su equipo",
|
||||||
|
"members_team_description": "Usuarios que están en el grupo",
|
||||||
|
"team_url": "URL del equipo",
|
||||||
|
"delete_team": "Eliminar equipo",
|
||||||
|
"team_members": "Miembros del equipo",
|
||||||
|
"more": "Más",
|
||||||
|
"more_page_footer": "Vemos la aplicación móvil como una extensión de la aplicación web. Si está realizando acciones complicadas, consulte la aplicación web.",
|
||||||
|
"workflow_example_1": "Enviar recordatorio por SMS al asistente 24 horas antes de que el evento comience",
|
||||||
|
"workflow_example_2": "Enviar SMS personalizado al asistente cuando se cambie la planificación del evento",
|
||||||
|
"workflow_example_3": "Enviar correo electrónico personalizado al anfitrión cuando se reserve un evento nuevo",
|
||||||
|
"workflow_example_4": "Enviar recordatorio por correo electrónico al asistente 1 hora antes de que el evento comience",
|
||||||
|
"workflow_example_5": "Enviar correo electrónico personalizado al anfitrión cuando se cambie la planificación del evento",
|
||||||
|
"workflow_example_6": "Enviar SMS personalizado al anfitrión cuando se reserve un evento nuevo",
|
||||||
|
"welcome_to_cal_header": "¡Bienvenido a Cal.com!",
|
||||||
|
"edit_form_later_subtitle": "Podrá editarlo más tarde.",
|
||||||
|
"connect_calendar_later": "Conectaré mi calendario más tarde",
|
||||||
|
"set_my_availability_later": "Indicaré mi disponibilidad más tarde",
|
||||||
|
"problem_saving_user_profile": "Se produjo un problema al guardar sus datos. Inténtelo de nuevo o póngase en contacto con el servicio de atención al cliente.",
|
||||||
|
"purchase_missing_seats": "Comprar licencias que faltan",
|
||||||
|
"slot_length": "Duración de franja",
|
||||||
|
"booking_appearance": "Aspecto de la reserva",
|
||||||
|
"appearance_team_description": "Administre los ajustes para el aspecto de la reserva de su equipo",
|
||||||
|
"only_owner_change": "Solo el propietario de este equipo puede hacer cambios en la reserva del equipo ",
|
||||||
|
"team_disable_cal_branding_description": "Elimina cualquier marca relacionada con Cal, p. ej., \"Powered by Cal\"",
|
||||||
|
"invited_by_team": "{{teamName}} le invitó a unirse a su equipo como {{role}}",
|
||||||
|
"token_invalid_expired": "El token no es válido o ha caducado.",
|
||||||
|
"exchange_add": "Conectar a Microsoft Exchange",
|
||||||
|
"exchange_authentication": "Método de autenticación",
|
||||||
|
"exchange_authentication_standard": "Autenticación básica",
|
||||||
|
"exchange_authentication_ntlm": "Autenticación NTLM",
|
||||||
|
"exchange_compression": "Compresión GZip",
|
||||||
|
"routing_forms_description": "Puede ver todos los formularios y rutas que ha creado aquí.",
|
||||||
|
"add_new_form": "Añadir formulario nuevo",
|
||||||
|
"form_description": "Cree su formulario para dirigirlo a un agente de reservas",
|
||||||
|
"copy_link_to_form": "Copiar enlace al formulario",
|
||||||
|
"theme": "Tema",
|
||||||
|
"theme_applies_note": "Solo se aplica a sus páginas de reservas públicas",
|
||||||
"theme_light": "Claro",
|
"theme_light": "Claro",
|
||||||
"theme_dark": "Oscuro"
|
"theme_dark": "Oscuro",
|
||||||
|
"theme_system": "Predeterminado del sistema",
|
||||||
|
"add_a_team": "Añadir un equipo",
|
||||||
|
"saml_config": "Configuración de SAML",
|
||||||
|
"add_webhook_description": "Reciba datos de reuniones en tiempo real cuando suceda algo en Cal.com",
|
||||||
|
"triggers_when": "Se activa cuando",
|
||||||
|
"test_webhook": "Antes de crear, ejecute una prueba de ping.",
|
||||||
|
"enable_webhook": "Activar Webhook",
|
||||||
|
"add_webhook": "Añadir Webhook",
|
||||||
|
"webhook_edited_successfully": "Webhook guardado",
|
||||||
|
"webhooks_description": "Reciba datos de reuniones en tiempo real cuando suceda algo en Cal.com",
|
||||||
|
"api_keys_description": "Genere claves API para acceder a su propia cuenta",
|
||||||
|
"new_api_key": "Clave API nueva",
|
||||||
|
"active": "Activo",
|
||||||
|
"api_key_updated": "Nombre de clave API actualizado",
|
||||||
|
"api_key_update_failed": "Error al actualizar el nombre de la clave API",
|
||||||
|
"embeds_title": "Inserción de iframe HTML",
|
||||||
|
"embeds_description": "Inserte todos sus tipos de eventos en su sitio web",
|
||||||
|
"create_first_api_key": "Cree su primera clave API",
|
||||||
|
"create_first_api_key_description": "Las claves API permiten a otras aplicaciones comunicarse con Cal.com",
|
||||||
|
"back_to_signin": "Volver a iniciar sesión",
|
||||||
|
"reset_link_sent": "Enlace de restablecimiento enviado",
|
||||||
|
"password_reset_email": "Se ha enviado un correo electrónico a {{email}} con instrucciones para restablecer su contraseña.",
|
||||||
|
"password_updated": "¡Contraseña actualizada!",
|
||||||
|
"pending_payment": "Pago pendiente",
|
||||||
|
"confirmation_page_rainbow": "Cierre el acceso a su evento con tokens o NFT en Ethereum, Polygon, etc.",
|
||||||
|
"not_on_cal": "No está en Cal.com",
|
||||||
|
"no_calendar_installed": "No hay ningún calendario instalado",
|
||||||
|
"no_calendar_installed_description": "Aún no ha conectado ninguno de sus calendarios",
|
||||||
|
"add_a_calendar": "Añadir un calendario",
|
||||||
|
"change_email_hint": "Quizá necesite cerrar sesión y volver a entrar para ver que el cambio surta efecto",
|
||||||
|
"confirm_password_change_email": "Confirme su contraseña antes de cambiar su dirección de correo electrónico",
|
||||||
|
"seats": "asientos",
|
||||||
|
"every_app_published": "Las aplicaciones publicadas en la tienda de aplicaciones de Cal.com son de código abierto y se han sometido a pruebas exhaustivas con las reseñas de pares. Sin embargo, Cal.com, Inc. no avala ni certifica estas aplicaciones a menos que Cal.com las haya publicado expresamente. Si encuentra contenido o comportamiento inapropiados, informe de ello.",
|
||||||
|
"report_app": "Denunciar aplicación",
|
||||||
|
"billing_manage_details_title": "Ver y administrar sus datos de facturación",
|
||||||
|
"billing_manage_details_description": "Vea y edite sus datos de facturación, así como cancele su suscripción.",
|
||||||
|
"billing_help_title": "¿Necesita algo más?",
|
||||||
|
"billing_help_description": "Si necesita más ayuda con la facturación, nuestro equipo de soporte está aquí para ayudarlo."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Utilisez le lien ci-dessous pour réinitialiser votre mot de passe",
|
"use_link_to_reset_password": "Utilisez le lien ci-dessous pour réinitialiser votre mot de passe",
|
||||||
"hey_there": "Salut,",
|
"hey_there": "Salut,",
|
||||||
"forgot_your_password_calcom": "Mot de passe oublié ? - Cal.com",
|
"forgot_your_password_calcom": "Mot de passe oublié ? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Type d'événement",
|
|
||||||
"delete_webhook_confirmation_message": "Êtes-vous sûr de vouloir supprimer ce webhook ? Vous ne recevrez plus les données de réunion de Cal.com à une URL spécifiée, en temps réel, lorsqu'un événement est programmé ou annulé.",
|
"delete_webhook_confirmation_message": "Êtes-vous sûr de vouloir supprimer ce webhook ? Vous ne recevrez plus les données de réunion de Cal.com à une URL spécifiée, en temps réel, lorsqu'un événement est programmé ou annulé.",
|
||||||
"confirm_delete_webhook": "Oui, supprimer le webhook",
|
"confirm_delete_webhook": "Oui, supprimer le webhook",
|
||||||
"edit_webhook": "Modifier le webhook",
|
"edit_webhook": "Modifier le webhook",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "Voir la page publique",
|
"view_public_page": "Voir la page publique",
|
||||||
"sign_out": "Se déconnecter",
|
"sign_out": "Se déconnecter",
|
||||||
"add_another": "Ajouter un autre",
|
"add_another": "Ajouter un autre",
|
||||||
|
"install_another": "Installer un(e) autre",
|
||||||
"until": "jusqu'au",
|
"until": "jusqu'au",
|
||||||
"powered_by": "alimenté par",
|
"powered_by": "alimenté par",
|
||||||
"unavailable": "Indisponible",
|
"unavailable": "Indisponible",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "Case à cocher",
|
"checkbox": "Case à cocher",
|
||||||
"is_required": "Est obligatoire",
|
"is_required": "Est obligatoire",
|
||||||
"required": "Obligatoire",
|
"required": "Obligatoire",
|
||||||
|
"optional": "Facultatif",
|
||||||
"input_type": "Type d'entrée",
|
"input_type": "Type d'entrée",
|
||||||
"rejected": "Refusé",
|
"rejected": "Refusé",
|
||||||
"unconfirmed": "Non confirmé",
|
"unconfirmed": "Non confirmé",
|
||||||
@@ -227,7 +228,9 @@
|
|||||||
"connect_your_calendar_instructions": "Connectez votre calendrier pour vérifier automatiquement vos disponibilités au fur et à mesure qu'elles évoluent.",
|
"connect_your_calendar_instructions": "Connectez votre calendrier pour vérifier automatiquement vos disponibilités au fur et à mesure qu'elles évoluent.",
|
||||||
"set_up_later": "Configurer plus tard",
|
"set_up_later": "Configurer plus tard",
|
||||||
"current_time": "Heure actuelle",
|
"current_time": "Heure actuelle",
|
||||||
|
"details": "Détails",
|
||||||
"welcome": "Bienvenue",
|
"welcome": "Bienvenue",
|
||||||
|
"welcome_back": "Bienvenue de nouveau",
|
||||||
"welcome_to_calcom": "Bienvenue sur Cal.com",
|
"welcome_to_calcom": "Bienvenue sur Cal.com",
|
||||||
"welcome_instructions": "Dites-nous comment nous devons vous appeler et votre fuseau horaire. Vous pourrez modifier ceci plus tard.",
|
"welcome_instructions": "Dites-nous comment nous devons vous appeler et votre fuseau horaire. Vous pourrez modifier ceci plus tard.",
|
||||||
"connect_caldav": "Se connecter au serveur CalDav",
|
"connect_caldav": "Se connecter au serveur CalDav",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "Quand",
|
"when": "Quand",
|
||||||
"where": "Où",
|
"where": "Où",
|
||||||
"add_to_calendar": "Ajouter au calendrier",
|
"add_to_calendar": "Ajouter au calendrier",
|
||||||
|
"add_another_calendar": "Ajouter un autre calendrier",
|
||||||
"other": "Autre",
|
"other": "Autre",
|
||||||
"emailed_you_and_attendees": "Nous vous avons envoyé, à vous et aux autres participants, une invitation par e-mail avec tous les détails.",
|
"emailed_you_and_attendees": "Nous vous avons envoyé, à vous et aux autres participants, une invitation par e-mail avec tous les détails.",
|
||||||
"emailed_you_and_attendees_recurring": "Nous vous avons envoyé, à vous et aux autres participants, une invitation au calendrier pour le premier de ces événements récurrents.",
|
"emailed_you_and_attendees_recurring": "Nous vous avons envoyé, à vous et aux autres participants, une invitation au calendrier pour le premier de ces événements récurrents.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "Entrez le nouveau mot de passe que vous souhaitez pour votre compte.",
|
"enter_new_password": "Entrez le nouveau mot de passe que vous souhaitez pour votre compte.",
|
||||||
"reset_password": "Réinitialiser le mot de passe",
|
"reset_password": "Réinitialiser le mot de passe",
|
||||||
"change_your_password": "Modifiez votre mot de passe",
|
"change_your_password": "Modifiez votre mot de passe",
|
||||||
|
"show_password": "Afficher le mot de passe",
|
||||||
|
"hide_password": "Masquer le mot de passe",
|
||||||
"try_again": "Réessayer",
|
"try_again": "Réessayer",
|
||||||
"request_is_expired": "Cette requête est expirée.",
|
"request_is_expired": "Cette requête est expirée.",
|
||||||
"reset_instructions": "Saisissez l'adresse e-mail associée à votre compte et nous vous enverrons un lien pour réinitialiser votre mot de passe.",
|
"reset_instructions": "Saisissez l'adresse e-mail associée à votre compte et nous vous enverrons un lien pour réinitialiser votre mot de passe.",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "Dès que quelqu'un réserve une réunion récurrente avec vous, elle apparaît ici.",
|
"recurring_bookings": "Dès que quelqu'un réserve une réunion récurrente avec vous, elle apparaît ici.",
|
||||||
"past_bookings": "Vos réservations passées apparaîtront ici.",
|
"past_bookings": "Vos réservations passées apparaîtront ici.",
|
||||||
"cancelled_bookings": "Vos réservations annulées apparaîtront ici.",
|
"cancelled_bookings": "Vos réservations annulées apparaîtront ici.",
|
||||||
|
"unconfirmed_bookings": "Vos réservations non confirmées apparaîtront ici.",
|
||||||
"on": "le",
|
"on": "le",
|
||||||
"and": "et",
|
"and": "et",
|
||||||
"calendar_shows_busy_between": "Votre calendrier vous montre comme étant occupé entre",
|
"calendar_shows_busy_between": "Votre calendrier vous montre comme étant occupé entre",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "Réservation Annulée",
|
"booking_cancelled": "Réservation Annulée",
|
||||||
"booking_rescheduled": "Réservation Modifiée",
|
"booking_rescheduled": "Réservation Modifiée",
|
||||||
"booking_created": "Réservation Créée",
|
"booking_created": "Réservation Créée",
|
||||||
|
"meeting_ended": "Réunion terminée",
|
||||||
"form_submitted": "Formulaire envoyé",
|
"form_submitted": "Formulaire envoyé",
|
||||||
"event_triggers": "Déclencheurs d'événements",
|
"event_triggers": "Déclencheurs d'événements",
|
||||||
"subscriber_url": "URL de l'abonné",
|
"subscriber_url": "URL de l'abonné",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "Nous allons créer le premier utilisateur administrateur.",
|
"lets_create_first_administrator_user": "Nous allons créer le premier utilisateur administrateur.",
|
||||||
"new_member": "Nouveau membre",
|
"new_member": "Nouveau membre",
|
||||||
"invite": "Inviter",
|
"invite": "Inviter",
|
||||||
|
"add_team_members": "Ajouter des membres de l'équipe",
|
||||||
|
"add_team_members_description": "Invitez d'autres personnes à rejoindre votre équipe",
|
||||||
|
"add_team_member": "Ajouter un membre de l'équipe",
|
||||||
"invite_new_member": "Inviter un nouveau membre",
|
"invite_new_member": "Inviter un nouveau membre",
|
||||||
"invite_new_team_member": "Invitez quelqu'un à rejoindre votre équipe.",
|
"invite_new_team_member": "Invitez quelqu'un à rejoindre votre équipe.",
|
||||||
"change_member_role": "Changer le rôle du membre de l'équipe",
|
"change_member_role": "Changer le rôle du membre de l'équipe",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "Créez votre première équipe et invitez d'autres utilisateurs à travailler avec vous.",
|
"create_first_team_and_invite_others": "Créez votre première équipe et invitez d'autres utilisateurs à travailler avec vous.",
|
||||||
"create_team_to_get_started": "Créer une équipe pour commencer",
|
"create_team_to_get_started": "Créer une équipe pour commencer",
|
||||||
"teams": "Équipes",
|
"teams": "Équipes",
|
||||||
|
"team": "Équipe",
|
||||||
"team_billing": "Facturation d'équipe",
|
"team_billing": "Facturation d'équipe",
|
||||||
"upgrade_to_flexible_pro_title": "Nous avons modifié la facturation pour les équipes",
|
"upgrade_to_flexible_pro_title": "Nous avons modifié la facturation pour les équipes",
|
||||||
"upgrade_to_flexible_pro_message": "Des membres dans votre équipe n'ont pas de place. Mettez à niveau votre offre pro pour couvrir les places manquantes.",
|
"upgrade_to_flexible_pro_message": "Des membres dans votre équipe n'ont pas de place. Mettez à niveau votre offre pro pour couvrir les places manquantes.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "Facturation",
|
"billing": "Facturation",
|
||||||
"manage_your_billing_info": "Gérez vos informations de facturation et annulez votre abonnement.",
|
"manage_your_billing_info": "Gérez vos informations de facturation et annulez votre abonnement.",
|
||||||
"availability": "Disponibilité",
|
"availability": "Disponibilité",
|
||||||
|
"edit_availability": "Modifier la disponibilité",
|
||||||
"configure_availability": "Déclarez les moments où vous êtes disponible pour un rendez-vous.",
|
"configure_availability": "Déclarez les moments où vous êtes disponible pour un rendez-vous.",
|
||||||
|
"copy_times_to": "Copier les heures vers",
|
||||||
"change_weekly_schedule": "Modifier votre planning hebdomadaire",
|
"change_weekly_schedule": "Modifier votre planning hebdomadaire",
|
||||||
"logo": "Logo",
|
"logo": "Logo",
|
||||||
"error": "Erreur",
|
"error": "Erreur",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "Le nom qui apparaîtra dans les calendriers",
|
"event_name_tooltip": "Le nom qui apparaîtra dans les calendriers",
|
||||||
"meeting_with_user": "Rendez-vous avec {ATTENDEE}",
|
"meeting_with_user": "Rendez-vous avec {ATTENDEE}",
|
||||||
"additional_inputs": "Entrées additionnelles",
|
"additional_inputs": "Entrées additionnelles",
|
||||||
|
"additional_input_description": "Exiger que le planificateur saisisse des entrées supplémentaires avant que la réservation soit confirmée",
|
||||||
"label": "Libellé",
|
"label": "Libellé",
|
||||||
"placeholder": "Placeholder",
|
"placeholder": "Placeholder",
|
||||||
"type": "Type",
|
"type": "Type",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "Désactiver les invité. es",
|
"disable_guests": "Désactiver les invité. es",
|
||||||
"disable_guests_description": "Désactiver l'ajout d'invité·es supplémentaires lors de la réservation.",
|
"disable_guests_description": "Désactiver l'ajout d'invité·es supplémentaires lors de la réservation.",
|
||||||
"private_link": "Générer une URL privée",
|
"private_link": "Générer une URL privée",
|
||||||
|
"private_link_label": "Lien privé",
|
||||||
|
"private_link_hint": "Votre lien privé sera régénéré après chaque utilisation",
|
||||||
"copy_private_link": "Copier le lien privé",
|
"copy_private_link": "Copier le lien privé",
|
||||||
"private_link_description": "Générer une URL privée à partager sans exposer votre nom d'utilisateur Cal",
|
"private_link_description": "Générer une URL privée à partager sans exposer votre nom d'utilisateur Cal",
|
||||||
"invitees_can_schedule": "Les invité·es peuvent réserver",
|
"invitees_can_schedule": "Les invité·es peuvent réserver",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "Êtes-vous sûr de vouloir supprimer votre compte Cal.com ? Toute personne avec qui vous avez partagé le lien de votre compte ne pourra plus réserver en utilisant ce lien et toutes les préférences que vous avez enregistrées seront perdues.",
|
"delete_account_confirmation_message": "Êtes-vous sûr de vouloir supprimer votre compte Cal.com ? Toute personne avec qui vous avez partagé le lien de votre compte ne pourra plus réserver en utilisant ce lien et toutes les préférences que vous avez enregistrées seront perdues.",
|
||||||
"integrations": "Intégrations",
|
"integrations": "Intégrations",
|
||||||
"apps": "Applications",
|
"apps": "Applications",
|
||||||
|
"category_apps": "Applications {{category}}",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "Connecter les personnes, la technologie et l'espace de travail.",
|
"app_store_description": "Connecter les personnes, la technologie et l'espace de travail.",
|
||||||
"settings": "Paramètres",
|
"settings": "Paramètres",
|
||||||
"event_type_moved_successfully": "Le type d'évènement a bien été déplacé",
|
"event_type_moved_successfully": "Le type d'évènement a bien été déplacé",
|
||||||
|
"next_step_text": "Prochaine étape",
|
||||||
"next_step": "Passer l'étape",
|
"next_step": "Passer l'étape",
|
||||||
"prev_step": "Étape précédente",
|
"prev_step": "Étape précédente",
|
||||||
|
"install": "Installer",
|
||||||
"installed": "Installé",
|
"installed": "Installé",
|
||||||
"active_install_one": "{{count}} installation active",
|
"active_install_one": "{{count}} installation active",
|
||||||
"active_install_other": "{{count}} installations actives",
|
"active_install_other": "{{count}} installations actives",
|
||||||
"globally_install": "Installation globale",
|
"globally_install": "Installation globale",
|
||||||
|
"app_successfully_installed": "Application installée avec succès",
|
||||||
|
"app_could_not_be_installed": "Impossible d'installer l'application",
|
||||||
"disconnect": "Déconnecter",
|
"disconnect": "Déconnecter",
|
||||||
"embed_your_calendar": "Intégrez votre calendrier dans votre page web",
|
"embed_your_calendar": "Intégrez votre calendrier dans votre page web",
|
||||||
"connect_your_favourite_apps": "Connectez vos applications favorites.",
|
"connect_your_favourite_apps": "Connectez vos applications favorites.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "Connecter un calendrier supplémentaire",
|
"connect_additional_calendar": "Connecter un calendrier supplémentaire",
|
||||||
"conferencing": "Conférence",
|
"conferencing": "Conférence",
|
||||||
"calendar": "Calendrier",
|
"calendar": "Calendrier",
|
||||||
|
"payments": "Paiements",
|
||||||
"not_installed": "Non installé",
|
"not_installed": "Non installé",
|
||||||
"error_password_mismatch": "Les mots de passe ne correspondent pas.",
|
"error_password_mismatch": "Les mots de passe ne correspondent pas.",
|
||||||
"error_required_field": "Ce champ est requis.",
|
"error_required_field": "Ce champ est requis.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "Importer depuis",
|
"import_from": "Importer depuis",
|
||||||
"access_token": "Jeton d'accès",
|
"access_token": "Jeton d'accès",
|
||||||
"visit_roadmap": "Feuille de route",
|
"visit_roadmap": "Feuille de route",
|
||||||
|
"featured_categories": "Catégories en vedette",
|
||||||
"popular_categories": "Catégories populaires",
|
"popular_categories": "Catégories populaires",
|
||||||
|
"number_apps_one": "{{count}} Application",
|
||||||
|
"number_apps_other": "{{count}} Applications",
|
||||||
"trending_apps": "Applications populaires",
|
"trending_apps": "Applications populaires",
|
||||||
|
"explore_apps": "{{category}} applications",
|
||||||
"installed_apps": "Applications installées",
|
"installed_apps": "Applications installées",
|
||||||
|
"no_category_apps": "Aucune application {{category}}",
|
||||||
|
"no_category_apps_description_calendar": "Ajouter une application de calendrier pour vérifier les conflits et éviter les doubles réservations",
|
||||||
|
"no_category_apps_description_conferencing": "Essayez d'ajouter une application de conférence pour interconnecter les appels vidéo avec vos clients",
|
||||||
|
"no_category_apps_description_payment": "Ajouter une application de paiement pour faciliter les transactions entre vous et vos clients",
|
||||||
|
"no_category_apps_description_other": "Ajouter n'importe quel autre type d'application pour faire toutes sortes de choses",
|
||||||
|
"installed_app_calendar_description": "Définir le(s) calendrier(s) pour vérifier les conflits pour éviter les doubles réservations.",
|
||||||
|
"installed_app_conferencing_description": "Ajoutez vos applications de vidéoconférence préférées pour vos réunions",
|
||||||
|
"installed_app_payment_description": "Configurez les services de traitement de paiement à utiliser lors de la facturation de vos clients.",
|
||||||
|
"installed_app_other_description": "Toutes vos applications installées à partir d'autres catégories.",
|
||||||
"empty_installed_apps_headline": "Aucune application installée",
|
"empty_installed_apps_headline": "Aucune application installée",
|
||||||
"empty_installed_apps_description": "Les applications vous permettent d'améliorer votre flux de travail et votre processus de planification de façon significative.",
|
"empty_installed_apps_description": "Les applications vous permettent d'améliorer votre flux de travail et votre processus de planification de façon significative.",
|
||||||
"empty_installed_apps_button": "Explorer l'App Store",
|
"empty_installed_apps_button": "Explorer l'App Store",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "Supprimer",
|
"remove": "Supprimer",
|
||||||
"add": "Ajouter",
|
"add": "Ajouter",
|
||||||
"installed_one": "Installé",
|
"installed_one": "Installé",
|
||||||
|
"installed_other": "{{count}} installé(e)(s)",
|
||||||
"verify_wallet": "Vérifier le portefeuille",
|
"verify_wallet": "Vérifier le portefeuille",
|
||||||
"connect_metamask": "Connecter Metamask",
|
"connect_metamask": "Connecter Metamask",
|
||||||
"create_events_on": "Créer des événements le :",
|
"create_events_on": "Créer des événements le :",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "Définir par défaut",
|
"set_to_default": "Définir par défaut",
|
||||||
"new_schedule_btn": "Nouveau programme",
|
"new_schedule_btn": "Nouveau programme",
|
||||||
"add_new_schedule": "Ajouter un nouveau programme",
|
"add_new_schedule": "Ajouter un nouveau programme",
|
||||||
|
"add_new_calendar": "Ajouter un nouveau calendrier",
|
||||||
|
"set_calendar": "Définir où ajouter de nouveaux événements lors de la réservation.",
|
||||||
"delete_schedule": "Supprimer le programme",
|
"delete_schedule": "Supprimer le programme",
|
||||||
"schedule_created_successfully": "{{scheduleName}} programme créé",
|
"schedule_created_successfully": "{{scheduleName}} programme créé",
|
||||||
"availability_updated_successfully": "{{scheduleName}} programme mis à jour",
|
"availability_updated_successfully": "{{scheduleName}} programme mis à jour",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "Rediriger vers la réservation ",
|
"redirect_success_booking": "Rediriger vers la réservation ",
|
||||||
"you_are_being_redirected": "Vous êtes redirigé vers {{ url }} dans $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "Vous êtes redirigé vers {{ url }} dans $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://exemple.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://exemple.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "Pour pouvoir utiliser cette fonctionnalité, vous devez passer à un compte Pro.",
|
|
||||||
"duplicate": "Dupliquer",
|
"duplicate": "Dupliquer",
|
||||||
"offer_seats": "Offrir des places",
|
"offer_seats": "Offrir des places",
|
||||||
"offer_seats_description": "Offrez des places pour réservations (cela désactive les invités et active les réservations)",
|
"offer_seats_description": "Offrez des places pour réservations (cela désactive les invités et active les réservations)",
|
||||||
@@ -850,7 +888,7 @@
|
|||||||
"edit_booking": "Modifier la réservation",
|
"edit_booking": "Modifier la réservation",
|
||||||
"reschedule_booking": "Reporter la réservation",
|
"reschedule_booking": "Reporter la réservation",
|
||||||
"former_time": "Ancienne heure",
|
"former_time": "Ancienne heure",
|
||||||
"confirmation_page_gif": "Gif pour la page de confirmation",
|
"confirmation_page_gif": "Ajouter un GIF à la page de confirmation",
|
||||||
"search": "Rechercher",
|
"search": "Rechercher",
|
||||||
"impersonate": "Connexion autre",
|
"impersonate": "Connexion autre",
|
||||||
"user_impersonation_heading": "Connexion en tant qu'autre utilisateur",
|
"user_impersonation_heading": "Connexion en tant qu'autre utilisateur",
|
||||||
@@ -877,7 +915,7 @@
|
|||||||
"choose_ways_put_cal_site": "Choisissez une des façons suivantes de mettre Cal sur votre site.",
|
"choose_ways_put_cal_site": "Choisissez une des façons suivantes de mettre Cal sur votre site.",
|
||||||
"setting_up_zapier": "Configuration de votre intégration Zapier",
|
"setting_up_zapier": "Configuration de votre intégration Zapier",
|
||||||
"generate_api_key": "Générer une clé Api",
|
"generate_api_key": "Générer une clé Api",
|
||||||
"generate_api_key_description": "Générer une clé API à utiliser avec Cal.com à",
|
"generate_api_key_description": "Générer une clé API à utiliser avec Cal.com sur",
|
||||||
"your_unique_api_key": "Votre clé API unique",
|
"your_unique_api_key": "Votre clé API unique",
|
||||||
"copy_safe_api_key": "Copiez cette clé API et conservez-la dans un endroit sûr. Si vous perdez cette clé, vous devrez en générer une nouvelle.",
|
"copy_safe_api_key": "Copiez cette clé API et conservez-la dans un endroit sûr. Si vous perdez cette clé, vous devrez en générer une nouvelle.",
|
||||||
"zapier_setup_instructions": "<0>Connectez-vous à votre compte Zapier et créez un nouveau Zap.</0><1>Sélectionnez Cal.com comme application Trigger. Choisissez également un événement Trigger. </1><2>Choisissez votre compte, puis saisissez votre clé API unique.</2><3>Testez votre Trigger.</3><4>Vous pouvez vous lancer !</4>",
|
"zapier_setup_instructions": "<0>Connectez-vous à votre compte Zapier et créez un nouveau Zap.</0><1>Sélectionnez Cal.com comme application Trigger. Choisissez également un événement Trigger. </1><2>Choisissez votre compte, puis saisissez votre clé API unique.</2><3>Testez votre Trigger.</3><4>Vous pouvez vous lancer !</4>",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "Workflows",
|
"workflows": "Workflows",
|
||||||
"new_workflow_btn": "Nouveau workflow",
|
"new_workflow_btn": "Nouveau workflow",
|
||||||
"add_new_workflow": "Ajouter un nouveau workflow",
|
"add_new_workflow": "Ajouter un nouveau workflow",
|
||||||
|
"reschedule_event_trigger": "lorsque l'événement est reprogrammé",
|
||||||
"trigger": "Déclencheur",
|
"trigger": "Déclencheur",
|
||||||
"triggers": "Déclencheurs",
|
"triggers": "Déclencheurs",
|
||||||
"action": "Action",
|
"action": "Action",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "Puisque vous passez d'un nom d'utilisateur standard à un premium, vous allez être envoyé au paiement pour valider le changement.",
|
"change_username_standard_to_premium": "Puisque vous passez d'un nom d'utilisateur standard à un premium, vous allez être envoyé au paiement pour valider le changement.",
|
||||||
"change_username_premium_to_standard": "Puisque vous passez d'un nom d'utilisateur premium à un standard, vous allez être envoyé au paiement pour valider la rétrogradation.",
|
"change_username_premium_to_standard": "Puisque vous passez d'un nom d'utilisateur premium à un standard, vous allez être envoyé au paiement pour valider la rétrogradation.",
|
||||||
"go_to_stripe_billing": "Accéder à la facturation",
|
"go_to_stripe_billing": "Accéder à la facturation",
|
||||||
|
"stripe_description": "Nécessite un paiement pour les réservations (0,5% + 0,10 € de commission par transaction)",
|
||||||
"trial_expired": "Votre période d'essai a expiré",
|
"trial_expired": "Votre période d'essai a expiré",
|
||||||
"remove_app": "Supprimer l'application",
|
"remove_app": "Supprimer l'application",
|
||||||
"yes_remove_app": "Oui, supprimer l'application",
|
"yes_remove_app": "Oui, supprimer l'application",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "Voulez-vous vraiment supprimer cette application ?",
|
"are_you_sure_you_want_to_remove_this_app": "Voulez-vous vraiment supprimer cette application ?",
|
||||||
|
"app_removed_successfully": "Application supprimée avec succès",
|
||||||
|
"error_removing_app": "Erreur lors de la suppression de l'application",
|
||||||
"web_conference": "Conférence en ligne",
|
"web_conference": "Conférence en ligne",
|
||||||
"number_for_sms_reminders": "Numéro de téléphone (pour les rappels par SMS)",
|
"number_for_sms_reminders": "Numéro de téléphone (pour les rappels par SMS)",
|
||||||
"requires_confirmation": "Nécessite une confirmation",
|
"requires_confirmation": "Nécessite une confirmation",
|
||||||
@@ -1022,18 +1064,209 @@
|
|||||||
"navigate": "Naviguer",
|
"navigate": "Naviguer",
|
||||||
"open": "Ouvrir",
|
"open": "Ouvrir",
|
||||||
"close": "Fermer",
|
"close": "Fermer",
|
||||||
|
"team_feature_teams": "Ceci est une fonctionnalité d'équipe. Mettez à niveau vers l'équipe pour voir la disponibilité de votre équipe.",
|
||||||
|
"team_feature_workflows": "Ceci est une fonctionnalité d'équipe. Mettez à niveau vers l'équipe pour automatiser vos notifications et rappels d'événements avec les flux de travail.",
|
||||||
|
"show_eventtype_on_profile": "Afficher sur le profil",
|
||||||
"embed": "Intégré",
|
"embed": "Intégré",
|
||||||
"new_username": "Nouveau nom d'utilisateur",
|
"new_username": "Nouveau nom d'utilisateur",
|
||||||
"current_username": "Nom d'utilisateur actuel",
|
"current_username": "Nom d'utilisateur actuel",
|
||||||
"example_1": "Exemple 1",
|
"example_1": "Exemple 1",
|
||||||
"example_2": "Exemple 2",
|
"example_2": "Exemple 2",
|
||||||
|
"additional_input_label": "Libellé de saisie supplémentaire",
|
||||||
"company_size": "Taille de l'entreprise",
|
"company_size": "Taille de l'entreprise",
|
||||||
"what_help_needed": "Pour quoi avez-vous besoin d'aide ?",
|
"what_help_needed": "Pour quoi avez-vous besoin d'aide ?",
|
||||||
"variable_format": "Format des variables",
|
"variable_format": "Format des variables",
|
||||||
|
"webhook_subscriber_url_reserved": "L'url d'abonné au Webhook est déjà définie",
|
||||||
|
"custom_input_as_variable_info": "Ignorer tous les caractères spéciaux du libellé de saisie supplémentaire (utiliser uniquement des lettres et des chiffres), utiliser des majuscules pour toutes les lettres et remplacer les espaces par des tirets bas.",
|
||||||
"using_additional_inputs_as_variables": "Comment utiliser des entrées supplémentaires en tant que variables ?",
|
"using_additional_inputs_as_variables": "Comment utiliser des entrées supplémentaires en tant que variables ?",
|
||||||
"download_desktop_app": "Télécharger l'application de bureau",
|
"download_desktop_app": "Télécharger l'application de bureau",
|
||||||
"set_ping_link": "Définir le lien Ping",
|
"set_ping_link": "Définir le lien Ping",
|
||||||
|
"rate_limit_exceeded": "Limite dépassée",
|
||||||
|
"when_something_happens": "Quand quelque chose se passe",
|
||||||
|
"action_is_performed": "Une action est effectuée",
|
||||||
|
"test_action": "Tester l'action",
|
||||||
|
"notification_sent": "Notification envoyée",
|
||||||
|
"no_input": "Aucune entrée",
|
||||||
|
"test_workflow_action": "Tester l'effet du workflow",
|
||||||
|
"send_sms": "Envoyer un SMS",
|
||||||
|
"send_sms_to_number": "Êtes-vous sûr de vouloir envoyer un SMS au {{number}}?",
|
||||||
|
"missing_connected_calendar": "Aucun calendrier par défaut connecté",
|
||||||
|
"connect_your_calendar_and_link": "Vous pouvez connecter votre calendrier depuis <1>ici</1>.",
|
||||||
|
"default_calendar_selected": "Calendrier par défaut",
|
||||||
|
"hide_from_profile": "Masquer du profil",
|
||||||
|
"event_setup_tab_title": "Configuration de l'événement",
|
||||||
|
"event_limit_tab_title": "Limites",
|
||||||
|
"event_limit_tab_description": "Fréquence de réservation",
|
||||||
|
"event_advanced_tab_description": "Paramètres du calendrier & plus...",
|
||||||
|
"event_advanced_tab_title": "Avancé",
|
||||||
|
"select_which_cal": "Sélectionnez le calendrier auquel ajouter des réservations",
|
||||||
|
"custom_event_name": "Nom de l'événement personnalisé",
|
||||||
|
"custom_event_name_description": "Créer des noms d'événements personnalisés à afficher sur l'événement du calendrier",
|
||||||
|
"2fa_required": "Authentification en deux étapes requise",
|
||||||
|
"incorrect_2fa": "Code d'authentification à deux facteurs incorrect",
|
||||||
|
"which_event_type_apply": "À quel type d'événement s'appliquera-t-il ?",
|
||||||
|
"no_workflows_description": "Les workflows permettent une automatisation simple pour envoyer des notifications et des rappels vous permettant de construire des processus autour de vos événements.",
|
||||||
|
"create_workflow": "Créer un workflow",
|
||||||
|
"do_this": "Effectuer ceci",
|
||||||
|
"turn_off": "Désactiver",
|
||||||
|
"settings_updated_successfully": "Paramètres mis à jour avec succès",
|
||||||
|
"error_updating_settings": "Erreur lors de la mise à jour des paramètres",
|
||||||
|
"personal_cal_url": "Mon URL Cal personnelle",
|
||||||
|
"bio_hint": "Quelques phrases à propos de vous. Ces informations apparaîtront sur votre page d'url personnelle.",
|
||||||
|
"delete_account_modal_title": "Supprimer le compte",
|
||||||
|
"confirm_delete_account_modal": "Êtes-vous sûr de vouloir supprimer votre compte Cal.com ?",
|
||||||
|
"delete_my_account": "Supprimer mon compte",
|
||||||
|
"start_of_week": "Début de la semaine",
|
||||||
|
"select_calendars": "Sélectionnez quels calendriers vous voulez vérifier les conflits pour éviter les doubles réservations.",
|
||||||
|
"check_for_conflicts": "Vérifier les conflits",
|
||||||
|
"adding_events_to": "Ajout d'événements à",
|
||||||
|
"follow_system_preferences": "Suivre les préférences système",
|
||||||
|
"custom_brand_colors": "Couleurs de marque personnalisées",
|
||||||
|
"customize_your_brand_colors": "Personnalisez votre propre couleur de marque dans votre page de réservation.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "Supprime les marques associées à Cal, c'est-à-dire \"Powered by Cal.\"",
|
||||||
|
"profile_picture": "Photo de profil",
|
||||||
|
"upload": "Télécharger",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "Ce type d'événement nécessite un jeton d'authentification.",
|
||||||
|
"rainbow_connect_wallet_gate": "Connectez votre portefeuille si vous possédez <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "Votre portefeuille connecté ne contient pas assez de <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "Signez la demande de message sur votre portefeuille.",
|
||||||
|
"rainbow_signature_error": "Erreur lors de la demande de signature de votre portefeuille.",
|
||||||
|
"token_address": "Adresse du jeton",
|
||||||
|
"blockchain": "Blockchain",
|
||||||
|
"old_password": "Ancien mot de passe",
|
||||||
|
"secure_password": "Votre nouveau mot de passe super sécurisé",
|
||||||
|
"error_updating_password": "Erreur lors de la mise à jour du mot de passe",
|
||||||
|
"two_factor_auth": "Authentification en deux étapes",
|
||||||
|
"recurring_event_tab_description": "Configurez un calendrier récurrent",
|
||||||
|
"today": "aujourd'hui",
|
||||||
|
"appearance": "Apparence",
|
||||||
|
"appearance_subtitle": "Gérer les paramètres pour votre apparence de réservation",
|
||||||
|
"my_account": "Mon compte",
|
||||||
|
"general": "Général",
|
||||||
|
"calendars": "Calendriers",
|
||||||
|
"2fa_auth": "Authentification à deux facteurs",
|
||||||
|
"invoices": "Factures",
|
||||||
|
"embeds": "Intègre",
|
||||||
|
"impersonation": "Identification",
|
||||||
|
"users": "Utilisateurs",
|
||||||
|
"profile_description": "Gérer les paramètres de votre profil cal",
|
||||||
|
"general_description": "Gérer les paramètres pour votre langue et votre fuseau horaire",
|
||||||
|
"calendars_description": "Configurez la manière dont vos types d'événements interagissent avec vos calendriers",
|
||||||
|
"appearance_description": "Gérer les paramètres pour votre apparence de réservation",
|
||||||
|
"conferencing_description": "Gérez vos applications de vidéoconférence pour vos réunions",
|
||||||
|
"password_description": "Gérer les paramètres pour les mots de passe de votre compte",
|
||||||
|
"2fa_description": "Gérer les paramètres pour les mots de passe de votre compte",
|
||||||
|
"we_just_need_basic_info": "Nous avons juste besoin de quelques informations de base pour configurer votre profil.",
|
||||||
|
"skip": "Ignorer",
|
||||||
|
"do_this_later": "Effectuer ceci plus tard",
|
||||||
|
"set_availability_getting_started_subtitle_1": "Définir les plages de temps lorsque vous êtes disponible",
|
||||||
|
"set_availability_getting_started_subtitle_2": "Vous pouvez personnaliser tout cela plus tard dans la page de disponibilité.",
|
||||||
|
"connect_calendars_from_app_store": "Vous pouvez ajouter plus de calendriers depuis l'App Store",
|
||||||
|
"connect_conference_apps": "Connecter les applications de conférence",
|
||||||
|
"connect_calendar_apps": "Connecter les applications de calendrier",
|
||||||
|
"connect_payment_apps": "Connecter les applications de paiement",
|
||||||
|
"connect_other_apps": "Connecter d'autres applications",
|
||||||
|
"current_step_of_total": "Étape {{currentStep}} sur {{maxSteps}}",
|
||||||
|
"add_variable": "Ajouter une variable",
|
||||||
|
"custom_phone_number": "Numéro de téléphone personnalisé",
|
||||||
|
"message_template": "Modèle de message",
|
||||||
|
"email_subject": "Objet",
|
||||||
|
"add_dynamic_variables": "Ajouter des variables de texte dynamiques",
|
||||||
|
"event_name_info": "Nom du type d'événement",
|
||||||
|
"event_date_info": "Date de l'évènement",
|
||||||
|
"event_time_info": "Heure de début de l'événement",
|
||||||
|
"location_info": "Lieu de l'événement",
|
||||||
"organizer_name_info": "Votre nom",
|
"organizer_name_info": "Votre nom",
|
||||||
|
"additional_notes_info": "Notes supplémentaires de réservation",
|
||||||
|
"attendee_name_info": "Nom de la personne réservant",
|
||||||
|
"to": "À/vers",
|
||||||
|
"attendee_required_enter_number": "Le participant devra entrer un numéro de téléphone lors de la réservation",
|
||||||
|
"workflow_turned_on_successfully": "Le workflow {{workflowName}} a été {{offOn}} avec succès",
|
||||||
|
"download_responses": "Télécharger les réponses",
|
||||||
|
"create_your_first_form": "Créer votre premier formulaire",
|
||||||
|
"create_your_first_form_description": "Grâce aux formulaires d'acheminement, vous pouvez poser des questions de qualification et vous diriger vers la personne ou le type d'événement appropriés.",
|
||||||
|
"create_your_first_webhook": "Créez votre premier Webhook",
|
||||||
|
"create_your_first_webhook_description": "Avec les Webhooks, vous pouvez recevoir des données de réunion en temps réel lorsque quelque chose se passe sur Cal.com.",
|
||||||
|
"for_a_maximum_of": "Pour un maximum de",
|
||||||
|
"event_one": "événement",
|
||||||
|
"event_other": "événements",
|
||||||
|
"profile_team_description": "Gérer les paramètres de votre profil d'équipe",
|
||||||
|
"members_team_description": "Utilisateurs membres du groupe",
|
||||||
|
"team_url": "URL de l'équipe",
|
||||||
|
"delete_team": "Supprimer l'équipe",
|
||||||
|
"team_members": "Membres de l'équipe",
|
||||||
|
"more": "En savoir plus",
|
||||||
|
"more_page_footer": "Nous considérons l'application mobile comme une extension de l'application web. Si vous effectuez des actions complexes, veuillez vous référer à l'application Web.",
|
||||||
|
"workflow_example_1": "Envoyer un rappel SMS 24 heures avant le début de l'événement",
|
||||||
|
"workflow_example_2": "Envoyer un SMS personnalisé lorsque l'événement est reprogrammé au participant",
|
||||||
|
"workflow_example_3": "Envoyer un email personnalisé quand un nouvel événement est réservé à un hôte",
|
||||||
|
"workflow_example_4": "Envoyer un rappel par e-mail 1 heure avant le début des événements",
|
||||||
|
"workflow_example_5": "Envoyer un email personnalisé lorsque l'événement est reprogrammé à l'hôte",
|
||||||
|
"workflow_example_6": "Envoyer un SMS personnalisé quand un nouvel événement est réservé à un hôte",
|
||||||
|
"welcome_to_cal_header": "Bienvenue sur Cal.com !",
|
||||||
|
"edit_form_later_subtitle": "Vous pourrez modifier cela plus tard.",
|
||||||
|
"connect_calendar_later": "Je connecterai mon calendrier plus tard",
|
||||||
|
"set_my_availability_later": "Je vais définir ma disponibilité plus tard",
|
||||||
|
"problem_saving_user_profile": "Un problème est survenu lors de l'enregistrement de vos données. Veuillez réessayer ou contacter le service client.",
|
||||||
|
"purchase_missing_seats": "Acheter des places manquantes",
|
||||||
|
"slot_length": "Durée du créneau",
|
||||||
|
"booking_appearance": "Apparence de page de réservation",
|
||||||
|
"appearance_team_description": "Gérer les paramètres pour l'apparence de réservation de votre équipe",
|
||||||
|
"only_owner_change": "Seul le propriétaire de cette équipe peut apporter des modifications à la réservation de l'équipe ",
|
||||||
|
"team_disable_cal_branding_description": "Supprime les marques associées à Cal, c'est-à-dire \"Powered by Cal\"",
|
||||||
|
"invited_by_team": "{{teamName}} vous a invité à rejoindre son équipe en tant que {{role}}",
|
||||||
|
"token_invalid_expired": "Le jeton est invalide ou expiré.",
|
||||||
|
"exchange_add": "Se connecter à Microsoft Exchange",
|
||||||
|
"exchange_authentication": "Méthode d'authentification",
|
||||||
|
"exchange_authentication_standard": "Authentification de base",
|
||||||
|
"exchange_authentication_ntlm": "Authentification NTLM",
|
||||||
|
"exchange_compression": "Compression GZip",
|
||||||
|
"routing_forms_description": "Vous pouvez voir tous les formulaires et tous les parcours que vous avez créés ici.",
|
||||||
|
"add_new_form": "Ajouter un nouveau formulaire",
|
||||||
|
"form_description": "Créez votre formulaire pour acheminer un organisateur",
|
||||||
|
"copy_link_to_form": "Copier le lien vers le formulaire",
|
||||||
|
"theme": "Thème",
|
||||||
|
"theme_applies_note": "Ceci s'applique uniquement à vos pages publiques de réservation",
|
||||||
"theme_light": "Clair",
|
"theme_light": "Clair",
|
||||||
"theme_dark": "Sombre"
|
"theme_dark": "Sombre",
|
||||||
|
"theme_system": "Défaut du système",
|
||||||
|
"add_a_team": "Ajouter une équipe",
|
||||||
|
"saml_config": "Configuration SAML",
|
||||||
|
"add_webhook_description": "Recevoir les données de la réunion en temps réel lorsque quelque chose se passe sur Cal.com",
|
||||||
|
"triggers_when": "Se déclenche quand",
|
||||||
|
"test_webhook": "Veuillez faire un test de ping avant de créer.",
|
||||||
|
"enable_webhook": "Activer le Webhook",
|
||||||
|
"add_webhook": "Ajouter un Webhook",
|
||||||
|
"webhook_edited_successfully": "Webhook enregistré",
|
||||||
|
"webhooks_description": "Recevez les données de la réunion en temps réel lorsque quelque chose se passe sur Cal.com",
|
||||||
|
"api_keys_description": "Générer des clés API pour accéder à votre propre compte",
|
||||||
|
"new_api_key": "Nouvelle clé API",
|
||||||
|
"active": "Actif",
|
||||||
|
"api_key_updated": "Nom de clé API mis à jour",
|
||||||
|
"api_key_update_failed": "Erreur de mise à jour du nom de la clé API",
|
||||||
|
"embeds_title": "Intégration d'iframe HTML",
|
||||||
|
"embeds_description": "Intégrez tous vos types d'événements sur votre site web",
|
||||||
|
"create_first_api_key": "Créez votre première clé API",
|
||||||
|
"create_first_api_key_description": "Les clés API permettent à d'autres applications de communiquer avec Cal.com",
|
||||||
|
"back_to_signin": "Retour à la connexion",
|
||||||
|
"reset_link_sent": "Lien de réinitialisation envoyé",
|
||||||
|
"password_reset_email": "Un e-mail est transmis vers {{email}} avec les instructions pour réinitialiser votre mot de passe.",
|
||||||
|
"password_updated": "Mot de passe mis à jour !",
|
||||||
|
"pending_payment": "Paiement en attente",
|
||||||
|
"confirmation_page_rainbow": "Le jeton porte votre événement avec des jetons ou des NFT sur Ethereum, Polygone et plus encore.",
|
||||||
|
"not_on_cal": "Pas sur Cal.com",
|
||||||
|
"no_calendar_installed": "Aucun calendrier installé",
|
||||||
|
"no_calendar_installed_description": "Vous n'avez pas encore connecté vos calendriers",
|
||||||
|
"add_a_calendar": "Ajouter au calendrier",
|
||||||
|
"change_email_hint": "Vous devrez peut-être vous déconnecter et vous reconnecter pour que le changement prenne effet",
|
||||||
|
"confirm_password_change_email": "Veuillez confirmer votre mot de passe avant de changer votre adresse e-mail",
|
||||||
|
"seats": "places",
|
||||||
|
"every_app_published": "Chaque application publiée sur l'App Store de Cal.com est open source et soigneusement testée via les évaluations par les pairs. Néanmoins, Cal.com, Inc. n'approuve pas ou ne certifie pas ces applications à moins qu'elles ne soient publiées par Cal.com. Si vous rencontrez un contenu ou un comportement inapproprié, veuillez le signaler.",
|
||||||
|
"report_app": "Signaler une application",
|
||||||
|
"billing_manage_details_title": "Affichez et gérez vos informations de facturation",
|
||||||
|
"billing_manage_details_description": "Affichez et modifiez vos informations de facturation, et annuler votre abonnement.",
|
||||||
|
"billing_help_title": "Besoin d'autre chose ?",
|
||||||
|
"billing_help_description": "Si vous avez besoin d'aide pour la facturation, notre équipe d'assistance est là pour vous aider."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "נא להשתמש בקישור הבא כדי לאפס את הסיסמה",
|
"use_link_to_reset_password": "נא להשתמש בקישור הבא כדי לאפס את הסיסמה",
|
||||||
"hey_there": "שלום,",
|
"hey_there": "שלום,",
|
||||||
"forgot_your_password_calcom": "שכחתה את הסיסמה? - cal.com",
|
"forgot_your_password_calcom": "שכחתה את הסיסמה? - cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | סוג האירוע",
|
|
||||||
"delete_webhook_confirmation_message": "בטוח שברצונך למחוק את ה-Webhook הזה? אם אירוע יבוטל או שייקבע עבורו מועד, לא תקבל יותר נתוני פגישות מ-Cal.com בזמן אמת או בכתובת ה-URL שציינת.",
|
"delete_webhook_confirmation_message": "בטוח שברצונך למחוק את ה-Webhook הזה? אם אירוע יבוטל או שייקבע עבורו מועד, לא תקבל יותר נתוני פגישות מ-Cal.com בזמן אמת או בכתובת ה-URL שציינת.",
|
||||||
"confirm_delete_webhook": "כן, אני רוצה למחוק את ה-Webhook",
|
"confirm_delete_webhook": "כן, אני רוצה למחוק את ה-Webhook",
|
||||||
"edit_webhook": "עריכת Webhook",
|
"edit_webhook": "עריכת Webhook",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "צפייה בדף הציבורי",
|
"view_public_page": "צפייה בדף הציבורי",
|
||||||
"sign_out": "יציאה",
|
"sign_out": "יציאה",
|
||||||
"add_another": "הוסף לוח זמנים נוסף",
|
"add_another": "הוסף לוח זמנים נוסף",
|
||||||
|
"install_another": "התקנת אפליקציה נוספת",
|
||||||
"until": "עד",
|
"until": "עד",
|
||||||
"powered_by": "מופעל על ידי",
|
"powered_by": "מופעל על ידי",
|
||||||
"unavailable": "לא זמין",
|
"unavailable": "לא זמין",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "תיבת סימון",
|
"checkbox": "תיבת סימון",
|
||||||
"is_required": "נדרש",
|
"is_required": "נדרש",
|
||||||
"required": "נדרש",
|
"required": "נדרש",
|
||||||
|
"optional": "אופציונלי",
|
||||||
"input_type": "סוג הקלט",
|
"input_type": "סוג הקלט",
|
||||||
"rejected": "נדחה",
|
"rejected": "נדחה",
|
||||||
"unconfirmed": "לא אושר",
|
"unconfirmed": "לא אושר",
|
||||||
@@ -227,7 +228,9 @@
|
|||||||
"connect_your_calendar_instructions": "קשר את לוח השנה שלך לצפייה בזמנים עמוסים ובאירועים חדשים באופן אוטומטי ברגע שנקבע מועד עבורם.",
|
"connect_your_calendar_instructions": "קשר את לוח השנה שלך לצפייה בזמנים עמוסים ובאירועים חדשים באופן אוטומטי ברגע שנקבע מועד עבורם.",
|
||||||
"set_up_later": "להגדיר מאוחר יותר",
|
"set_up_later": "להגדיר מאוחר יותר",
|
||||||
"current_time": "השעה הנוכחית",
|
"current_time": "השעה הנוכחית",
|
||||||
|
"details": "פרטים",
|
||||||
"welcome": "ברוך הבא",
|
"welcome": "ברוך הבא",
|
||||||
|
"welcome_back": "ברוך שובך",
|
||||||
"welcome_to_calcom": "ברוך הבא אל Cal.com",
|
"welcome_to_calcom": "ברוך הבא אל Cal.com",
|
||||||
"welcome_instructions": "אמור לנו באיזה שם ברצונך שנקרא לך ובאיזה אזור זמן אתה נמצא. ניתן יהיה לערוך את הפרטים האלה מאוחר יותר.",
|
"welcome_instructions": "אמור לנו באיזה שם ברצונך שנקרא לך ובאיזה אזור זמן אתה נמצא. ניתן יהיה לערוך את הפרטים האלה מאוחר יותר.",
|
||||||
"connect_caldav": "חיבור לשרת CalDav",
|
"connect_caldav": "חיבור לשרת CalDav",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "מתי",
|
"when": "מתי",
|
||||||
"where": "היכן",
|
"where": "היכן",
|
||||||
"add_to_calendar": "הוספה ללוח השנה",
|
"add_to_calendar": "הוספה ללוח השנה",
|
||||||
|
"add_another_calendar": "הוספת לוח שנה אחר",
|
||||||
"other": "אחר",
|
"other": "אחר",
|
||||||
"emailed_you_and_attendees": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה הכוללת את כל הפרטים.",
|
"emailed_you_and_attendees": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה הכוללת את כל הפרטים.",
|
||||||
"emailed_you_and_attendees_recurring": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה לאירוע הראשון מבין האירועים החוזרים האלה.",
|
"emailed_you_and_attendees_recurring": "שלחנו לך ולמשתתפים האחרים הודעת דוא\"ל עם הזמנה בלוח השנה לאירוע הראשון מבין האירועים החוזרים האלה.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "נא להזין את הסיסמה החדשה שבה ברצונך להשתמש עבור החשבון.",
|
"enter_new_password": "נא להזין את הסיסמה החדשה שבה ברצונך להשתמש עבור החשבון.",
|
||||||
"reset_password": "איפוס סיסמה",
|
"reset_password": "איפוס סיסמה",
|
||||||
"change_your_password": "שינוי סיסמה",
|
"change_your_password": "שינוי סיסמה",
|
||||||
|
"show_password": "הצגת הסיסמה",
|
||||||
|
"hide_password": "הסתרת הסיסמה",
|
||||||
"try_again": "לנסות שוב",
|
"try_again": "לנסות שוב",
|
||||||
"request_is_expired": "תוקף הבקשה פג.",
|
"request_is_expired": "תוקף הבקשה פג.",
|
||||||
"reset_instructions": "הזן את כתובת הדוא\"ל המשויכת לחשבון שלך, ואנו נשלח לך קישור לאיפוס הסיסמה.",
|
"reset_instructions": "הזן את כתובת הדוא\"ל המשויכת לחשבון שלך, ואנו נשלח לך קישור לאיפוס הסיסמה.",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "ברגע שמישהו יקבע איתך פגישה חוזרת, המועד שנקבע יוצג כאן.",
|
"recurring_bookings": "ברגע שמישהו יקבע איתך פגישה חוזרת, המועד שנקבע יוצג כאן.",
|
||||||
"past_bookings": "ההזמנות הקודמות שלך יוצגו כאן.",
|
"past_bookings": "ההזמנות הקודמות שלך יוצגו כאן.",
|
||||||
"cancelled_bookings": "ההזמנות המבוטלות שלך יוצגו כאן.",
|
"cancelled_bookings": "ההזמנות המבוטלות שלך יוצגו כאן.",
|
||||||
|
"unconfirmed_bookings": "ההזמנות שלך שלא אושרו יוצגו כאן.",
|
||||||
"on": "בתאריך",
|
"on": "בתאריך",
|
||||||
"and": "וגם",
|
"and": "וגם",
|
||||||
"calendar_shows_busy_between": "בלוח השנה מוצג כי אתה עסוק בין",
|
"calendar_shows_busy_between": "בלוח השנה מוצג כי אתה עסוק בין",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "ההזמנה בוטלה",
|
"booking_cancelled": "ההזמנה בוטלה",
|
||||||
"booking_rescheduled": "מועד ההזמנה השתנה",
|
"booking_rescheduled": "מועד ההזמנה השתנה",
|
||||||
"booking_created": "ההזמנה נוצרה",
|
"booking_created": "ההזמנה נוצרה",
|
||||||
|
"meeting_ended": "הפגישה הסתיימה",
|
||||||
"form_submitted": "הטופס נשלח",
|
"form_submitted": "הטופס נשלח",
|
||||||
"event_triggers": "גורמים מפעילים של אירועים",
|
"event_triggers": "גורמים מפעילים של אירועים",
|
||||||
"subscriber_url": "כתובת URL של המנוי/ה",
|
"subscriber_url": "כתובת URL של המנוי/ה",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "עכשיו ניצור את המשתמש הראשון המוגדר כמנהל מערכת.",
|
"lets_create_first_administrator_user": "עכשיו ניצור את המשתמש הראשון המוגדר כמנהל מערכת.",
|
||||||
"new_member": "חבר/ה חדש/ה",
|
"new_member": "חבר/ה חדש/ה",
|
||||||
"invite": "להזמין",
|
"invite": "להזמין",
|
||||||
|
"add_team_members": "הוספת חברי צוות",
|
||||||
|
"add_team_members_description": "להזמין עוד אנשים להצטרף לצוות",
|
||||||
|
"add_team_member": "הוספת חבר צוות",
|
||||||
"invite_new_member": "להזמין חבר/ה חדש/ה",
|
"invite_new_member": "להזמין חבר/ה חדש/ה",
|
||||||
"invite_new_team_member": "להזמין מישהו לצוות שלך.",
|
"invite_new_team_member": "להזמין מישהו לצוות שלך.",
|
||||||
"change_member_role": "לשנות את תפקיד החבר/ה בצוות",
|
"change_member_role": "לשנות את תפקיד החבר/ה בצוות",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "צור את הצוות הראשון שלך והזמן משתמשים אחרים לעבוד יחד איתך.",
|
"create_first_team_and_invite_others": "צור את הצוות הראשון שלך והזמן משתמשים אחרים לעבוד יחד איתך.",
|
||||||
"create_team_to_get_started": "צור צוות כדי להתחיל",
|
"create_team_to_get_started": "צור צוות כדי להתחיל",
|
||||||
"teams": "צוותים",
|
"teams": "צוותים",
|
||||||
|
"team": "צוות",
|
||||||
"team_billing": "חיוב צוותים",
|
"team_billing": "חיוב צוותים",
|
||||||
"upgrade_to_flexible_pro_title": "שינינו את החיוב בעבור צוותים",
|
"upgrade_to_flexible_pro_title": "שינינו את החיוב בעבור צוותים",
|
||||||
"upgrade_to_flexible_pro_message": "יש בצוות שלך חברים שאין להם מקום. שדרג לחבילת Pro לדאוג למקומות החסרים.",
|
"upgrade_to_flexible_pro_message": "יש בצוות שלך חברים שאין להם מקום. שדרג לחבילת Pro לדאוג למקומות החסרים.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "חיוב",
|
"billing": "חיוב",
|
||||||
"manage_your_billing_info": "נהל את פרטי החיוב ובטל את המינוי.",
|
"manage_your_billing_info": "נהל את פרטי החיוב ובטל את המינוי.",
|
||||||
"availability": "זמינות",
|
"availability": "זמינות",
|
||||||
|
"edit_availability": "עריכת נתוני זמינות",
|
||||||
"configure_availability": "הגדר מועדים שבהם תהיה זמין להזמנות.",
|
"configure_availability": "הגדר מועדים שבהם תהיה זמין להזמנות.",
|
||||||
|
"copy_times_to": "העתקת שעות אל",
|
||||||
"change_weekly_schedule": "שינוי לוח הזמנים השבועי שלך",
|
"change_weekly_schedule": "שינוי לוח הזמנים השבועי שלך",
|
||||||
"logo": "לוגו",
|
"logo": "לוגו",
|
||||||
"error": "שגיאה",
|
"error": "שגיאה",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "השם שיופיע בלוחות השנה",
|
"event_name_tooltip": "השם שיופיע בלוחות השנה",
|
||||||
"meeting_with_user": "פגישה עם {ATTENDEE}",
|
"meeting_with_user": "פגישה עם {ATTENDEE}",
|
||||||
"additional_inputs": "אפשרויות קלט נוספות",
|
"additional_inputs": "אפשרויות קלט נוספות",
|
||||||
|
"additional_input_description": "לדרוש מכלי התזמון להוסיף פרטים לפני אישור ההזמנה",
|
||||||
"label": "תווית",
|
"label": "תווית",
|
||||||
"placeholder": "מציין מיקום",
|
"placeholder": "מציין מיקום",
|
||||||
"type": "סוג",
|
"type": "סוג",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "השבתת אורחים",
|
"disable_guests": "השבתת אורחים",
|
||||||
"disable_guests_description": "השבת את האפשרות להוסיף אורחים נוספים בעת ביצוע הזמנה.",
|
"disable_guests_description": "השבת את האפשרות להוסיף אורחים נוספים בעת ביצוע הזמנה.",
|
||||||
"private_link": "יצירת קישור פרטי",
|
"private_link": "יצירת קישור פרטי",
|
||||||
|
"private_link_label": "קישור פרטי",
|
||||||
|
"private_link_hint": "הקישור הפרטי שלך ייווצר מחדש לאחר כל שימוש",
|
||||||
"copy_private_link": "העתקת קישור פרטי",
|
"copy_private_link": "העתקת קישור פרטי",
|
||||||
"private_link_description": "ניתן ליצור כתובת URL פרטית על מנת לשתף את האירוע מבלי לחשוף את שם המשתמש/ת שלך ב-Cal",
|
"private_link_description": "ניתן ליצור כתובת URL פרטית על מנת לשתף את האירוע מבלי לחשוף את שם המשתמש/ת שלך ב-Cal",
|
||||||
"invitees_can_schedule": "המוזמנים יכולים לקבוע מועד",
|
"invitees_can_schedule": "המוזמנים יכולים לקבוע מועד",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "בטוח שברצונך למחוק את חשבון Cal.com שלך? כל מי ששיתפת איתו את הקישור לחשבון לא יוכל יותר להזמין באמצעותו, וכל ההעדפות ששמרת יאבדו.",
|
"delete_account_confirmation_message": "בטוח שברצונך למחוק את חשבון Cal.com שלך? כל מי ששיתפת איתו את הקישור לחשבון לא יוכל יותר להזמין באמצעותו, וכל ההעדפות ששמרת יאבדו.",
|
||||||
"integrations": "שילובים",
|
"integrations": "שילובים",
|
||||||
"apps": "אפליקציות",
|
"apps": "אפליקציות",
|
||||||
|
"category_apps": "אפליקציות בקטגוריה {{category}}",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "מקשרים בין אנשים, טכנולוגיה ומקום העבודה.",
|
"app_store_description": "מקשרים בין אנשים, טכנולוגיה ומקום העבודה.",
|
||||||
"settings": "הגדרות",
|
"settings": "הגדרות",
|
||||||
"event_type_moved_successfully": "סוג האירוע הועבר בהצלחה",
|
"event_type_moved_successfully": "סוג האירוע הועבר בהצלחה",
|
||||||
|
"next_step_text": "השלב הבא",
|
||||||
"next_step": "לדלג על שלב זה",
|
"next_step": "לדלג על שלב זה",
|
||||||
"prev_step": "לשלב הקודם",
|
"prev_step": "לשלב הקודם",
|
||||||
|
"install": "התקנה",
|
||||||
"installed": "מותקן",
|
"installed": "מותקן",
|
||||||
"active_install_one": "התקנה פעילה {{count}}",
|
"active_install_one": "התקנה פעילה {{count}}",
|
||||||
"active_install_other": "{{count}} התקנות פעילות",
|
"active_install_other": "{{count}} התקנות פעילות",
|
||||||
"globally_install": "התקנה גלובלית",
|
"globally_install": "התקנה גלובלית",
|
||||||
|
"app_successfully_installed": "האפליקציה הותקנה בהצלחה",
|
||||||
|
"app_could_not_be_installed": "לא ניתן היה להתקין את האפליקציה",
|
||||||
"disconnect": "התנתקות",
|
"disconnect": "התנתקות",
|
||||||
"embed_your_calendar": "הטמע את לוח השנה שלך בתוך דף האינטרנט",
|
"embed_your_calendar": "הטמע את לוח השנה שלך בתוך דף האינטרנט",
|
||||||
"connect_your_favourite_apps": "חבר את האפליקציות האהובות עליך.",
|
"connect_your_favourite_apps": "חבר את האפליקציות האהובות עליך.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "חיבור לוח שנה נוסף",
|
"connect_additional_calendar": "חיבור לוח שנה נוסף",
|
||||||
"conferencing": "שיחות ועידה",
|
"conferencing": "שיחות ועידה",
|
||||||
"calendar": "לוח שנה",
|
"calendar": "לוח שנה",
|
||||||
|
"payments": "תשלומים",
|
||||||
"not_installed": "לא מותקן",
|
"not_installed": "לא מותקן",
|
||||||
"error_password_mismatch": "הסיסמאות אינן זהות.",
|
"error_password_mismatch": "הסיסמאות אינן זהות.",
|
||||||
"error_required_field": "שדה זה הוא שדה חובה.",
|
"error_required_field": "שדה זה הוא שדה חובה.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "ייבוא מ",
|
"import_from": "ייבוא מ",
|
||||||
"access_token": "טוקן גישה",
|
"access_token": "טוקן גישה",
|
||||||
"visit_roadmap": "מפת דרכים",
|
"visit_roadmap": "מפת דרכים",
|
||||||
|
"featured_categories": "קטגוריות מוצגות",
|
||||||
"popular_categories": "קטגוריות פופולריות",
|
"popular_categories": "קטגוריות פופולריות",
|
||||||
|
"number_apps_one": "אפליקציה {{count}}",
|
||||||
|
"number_apps_other": "{{count}} אפליקציות",
|
||||||
"trending_apps": "אפליקציות פופולריות",
|
"trending_apps": "אפליקציות פופולריות",
|
||||||
|
"explore_apps": "אפליקציות בקטגוריה {{category}}",
|
||||||
"installed_apps": "אפליקציות מותקנות",
|
"installed_apps": "אפליקציות מותקנות",
|
||||||
|
"no_category_apps": "אין אפליקציות בקטגוריה {{category}}",
|
||||||
|
"no_category_apps_description_calendar": "הוסף/י אפליקציית לוח שנה כדי לבדוק אם יש התנגשויות על מנת למנוע כפל הזמנות",
|
||||||
|
"no_category_apps_description_conferencing": "נסה/י להוסיף אפליקציית שיחות ועידה כדי לשלב שיחות וידאו עם הלקוחות",
|
||||||
|
"no_category_apps_description_payment": "הוסף/י אפליקציית תשלומים על מנת להפוך את ביצוע העסקאות בינך לבין הלקוחות לפשוט יותר",
|
||||||
|
"no_category_apps_description_other": "הוסף/י כל סוג אחר של אפליקציה לביצוע פעולות שונות",
|
||||||
|
"installed_app_calendar_description": "הגדר/י את לוח(ות) השנה לבדוק אם יש התנגשויות על מנת למנוע כפל הזמנות.",
|
||||||
|
"installed_app_conferencing_description": "הוסף/י את האפליקציות האהובות עליך לשיחות ועידה לשימוש בפגישות שלך",
|
||||||
|
"installed_app_payment_description": "הגדר/י את השירותים לעיבוד תשלומים שבהם יש להשתמש לחיוב הלקוחות.",
|
||||||
|
"installed_app_other_description": "כל האפליקציות המותקנות שלך מקטגוריות אחרות.",
|
||||||
"empty_installed_apps_headline": "אין אפליקציות מותקנות",
|
"empty_installed_apps_headline": "אין אפליקציות מותקנות",
|
||||||
"empty_installed_apps_description": "אפליקציות מאפשרות לך לשפר משמעותית את תהליכי העבודה שלך ואת תהליך קביעת המועדים.",
|
"empty_installed_apps_description": "אפליקציות מאפשרות לך לשפר משמעותית את תהליכי העבודה שלך ואת תהליך קביעת המועדים.",
|
||||||
"empty_installed_apps_button": "נא לעיין ב-App Store",
|
"empty_installed_apps_button": "נא לעיין ב-App Store",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "הסר",
|
"remove": "הסר",
|
||||||
"add": "הוסף",
|
"add": "הוסף",
|
||||||
"installed_one": "מותקן",
|
"installed_one": "מותקן",
|
||||||
|
"installed_other": "{{count}} הותקנו",
|
||||||
"verify_wallet": "אימות הארנק",
|
"verify_wallet": "אימות הארנק",
|
||||||
"connect_metamask": "קישור Metamask",
|
"connect_metamask": "קישור Metamask",
|
||||||
"create_events_on": "יצירת אירועים ב:",
|
"create_events_on": "יצירת אירועים ב:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "הגדר לברירת המחדל",
|
"set_to_default": "הגדר לברירת המחדל",
|
||||||
"new_schedule_btn": "תזמון חדש",
|
"new_schedule_btn": "תזמון חדש",
|
||||||
"add_new_schedule": "הוסף מועד חדש",
|
"add_new_schedule": "הוסף מועד חדש",
|
||||||
|
"add_new_calendar": "הוספת לוח שנה חדש",
|
||||||
|
"set_calendar": "הגדר/י למתי יש להוסיף אירועים חדשים כשאת/ה כבר עסוק/ה.",
|
||||||
"delete_schedule": "מחק תזמון",
|
"delete_schedule": "מחק תזמון",
|
||||||
"schedule_created_successfully": "יצירת התזמון {{scheduleName}} בוצעה בהצלחה",
|
"schedule_created_successfully": "יצירת התזמון {{scheduleName}} בוצעה בהצלחה",
|
||||||
"availability_updated_successfully": "עדכון התזמון {{scheduleName}} בוצע בהצלחה",
|
"availability_updated_successfully": "עדכון התזמון {{scheduleName}} בוצע בהצלחה",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "הפניה מחדש בעת הזמנה ",
|
"redirect_success_booking": "הפניה מחדש בעת הזמנה ",
|
||||||
"you_are_being_redirected": "אנחנו ננתב אותך אל {{ url }} בעוד $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "אנחנו ננתב אותך אל {{ url }} בעוד $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "כדי להשתמש בתכונה זו, עליך לשדרג לחשבון Pro.",
|
|
||||||
"duplicate": "כפילות",
|
"duplicate": "כפילות",
|
||||||
"offer_seats": "הצעת מקומות",
|
"offer_seats": "הצעת מקומות",
|
||||||
"offer_seats_description": "הצעת מקומות להזמנות (אפשרות זו משביתה אישורי הזמנות ואורחים)",
|
"offer_seats_description": "הצעת מקומות להזמנות (אפשרות זו משביתה אישורי הזמנות ואורחים)",
|
||||||
@@ -809,7 +847,7 @@
|
|||||||
"booking_full": "אין יותר מקומות זמינים",
|
"booking_full": "אין יותר מקומות זמינים",
|
||||||
"api_keys": "מפתחות ממשק תכנות יישומים (API)",
|
"api_keys": "מפתחות ממשק תכנות יישומים (API)",
|
||||||
"api_key": "מפתח ממשק תכנות יישומים (API)",
|
"api_key": "מפתח ממשק תכנות יישומים (API)",
|
||||||
"test_api_key": "בדיקת מפתח ממשק תכנות יישומים (API)",
|
"test_api_key": "לבדוק מפתח ממשק תכנות יישומים (API)",
|
||||||
"test_passed": "הבדיקה עברה בהצלחה!",
|
"test_passed": "הבדיקה עברה בהצלחה!",
|
||||||
"test_failed": "הבדיקה נכשלה",
|
"test_failed": "הבדיקה נכשלה",
|
||||||
"provide_api_key": "נא לציין מפתח ממשק תכנות יישומים (API)",
|
"provide_api_key": "נא לציין מפתח ממשק תכנות יישומים (API)",
|
||||||
@@ -850,7 +888,7 @@
|
|||||||
"edit_booking": "עריכת ההזמנה",
|
"edit_booking": "עריכת ההזמנה",
|
||||||
"reschedule_booking": "שנה/י את מועד ההזמנה",
|
"reschedule_booking": "שנה/י את מועד ההזמנה",
|
||||||
"former_time": "המועד הקודם",
|
"former_time": "המועד הקודם",
|
||||||
"confirmation_page_gif": "נא להוסיף קובץ GIF לדף האישור",
|
"confirmation_page_gif": "להוסיף קובץ GIF לדף האישור",
|
||||||
"search": "חיפוש",
|
"search": "חיפוש",
|
||||||
"impersonate": "התחזות",
|
"impersonate": "התחזות",
|
||||||
"user_impersonation_heading": "התחזות למשתמשים",
|
"user_impersonation_heading": "התחזות למשתמשים",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "תהליכי עבודה",
|
"workflows": "תהליכי עבודה",
|
||||||
"new_workflow_btn": "תהליך עבודה חדש",
|
"new_workflow_btn": "תהליך עבודה חדש",
|
||||||
"add_new_workflow": "הוספת תהליך עבודה חדש",
|
"add_new_workflow": "הוספת תהליך עבודה חדש",
|
||||||
|
"reschedule_event_trigger": "כאשר נקבע מועד חדש לאירוע",
|
||||||
"trigger": "גורם מפעיל",
|
"trigger": "גורם מפעיל",
|
||||||
"triggers": "גורמים מפעילים",
|
"triggers": "גורמים מפעילים",
|
||||||
"action": "פעולה",
|
"action": "פעולה",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "מאחר שאתה משנה את שם המשתמש מסטנדרטי לפרימיום, תועבר אל הקופה לצורך שדרוג.",
|
"change_username_standard_to_premium": "מאחר שאתה משנה את שם המשתמש מסטנדרטי לפרימיום, תועבר אל הקופה לצורך שדרוג.",
|
||||||
"change_username_premium_to_standard": "מאחר שאתה משנה את שם המשתמש מפרימיום לסטנדרטי, תועבר אל הקופה לצורך שנמוך.",
|
"change_username_premium_to_standard": "מאחר שאתה משנה את שם המשתמש מפרימיום לסטנדרטי, תועבר אל הקופה לצורך שנמוך.",
|
||||||
"go_to_stripe_billing": "למעבר אל דף החיוב",
|
"go_to_stripe_billing": "למעבר אל דף החיוב",
|
||||||
|
"stripe_description": "דרישת תשלום עבור הזמנות (0.5% + €0.10 עמלה לכל עסקה)",
|
||||||
"trial_expired": "התוקף של גרסת הניסיון שלך פג",
|
"trial_expired": "התוקף של גרסת הניסיון שלך פג",
|
||||||
"remove_app": "הסרת האפליקציה",
|
"remove_app": "הסרת האפליקציה",
|
||||||
"yes_remove_app": "כן, להסיר את האפליקציה",
|
"yes_remove_app": "כן, להסיר את האפליקציה",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "בטוח שברצונך להסיר את האפליקציה הזו?",
|
"are_you_sure_you_want_to_remove_this_app": "בטוח שברצונך להסיר את האפליקציה הזו?",
|
||||||
|
"app_removed_successfully": "הסרת האפליקציה בוצעה בהצלחה",
|
||||||
|
"error_removing_app": "שגיאה בהסרת האפליקציה",
|
||||||
"web_conference": "שיחת ועידה מקוונת",
|
"web_conference": "שיחת ועידה מקוונת",
|
||||||
"number_for_sms_reminders": "מספר טלפון (לתזכורות ב-SMS)",
|
"number_for_sms_reminders": "מספר טלפון (לתזכורות ב-SMS)",
|
||||||
"requires_confirmation": "נדרש אישור",
|
"requires_confirmation": "נדרש אישור",
|
||||||
@@ -1022,18 +1064,209 @@
|
|||||||
"navigate": "ניווט",
|
"navigate": "ניווט",
|
||||||
"open": "פתיחה",
|
"open": "פתיחה",
|
||||||
"close": "סגירה",
|
"close": "סגירה",
|
||||||
|
"team_feature_teams": "זוהי תכונה של גרסת Team. כדאי לשדרג ל-Team כדי לראות את זמינות חברי הצוות.",
|
||||||
|
"team_feature_workflows": "זוהי תכונה של גרסת Team. כדאי לשדרג ל-Team כדי להפוך את התזכורות והעדכונים לגבי אירועים לאוטומטיים באמצעות תהליכי עבודה.",
|
||||||
|
"show_eventtype_on_profile": "הצג בפרופיל",
|
||||||
"embed": "הטמעה",
|
"embed": "הטמעה",
|
||||||
"new_username": "שם משתמש חדש",
|
"new_username": "שם משתמש חדש",
|
||||||
"current_username": "שם משתמש נוכחי",
|
"current_username": "שם משתמש נוכחי",
|
||||||
"example_1": "דוגמה 1",
|
"example_1": "דוגמה 1",
|
||||||
"example_2": "דוגמה 2",
|
"example_2": "דוגמה 2",
|
||||||
|
"additional_input_label": "תווית קלט נוספת",
|
||||||
"company_size": "גודל החברה",
|
"company_size": "גודל החברה",
|
||||||
"what_help_needed": "במה דרושה לך עזרה?",
|
"what_help_needed": "במה דרושה לך עזרה?",
|
||||||
"variable_format": "הפורמט של המשתנה",
|
"variable_format": "הפורמט של המשתנה",
|
||||||
|
"webhook_subscriber_url_reserved": "כתובת ה-URL של מנוי/מנויית Webhook כבר מוגדרת",
|
||||||
|
"custom_input_as_variable_info": "התעלמות מכל התווים המיוחדים של תווית הקלט הנוספת (שימוש באותיות ובספרות בלבד), שימוש באותיות רישיות עבור כל האותיות והחלפת רווחים במקפים תחתונים.",
|
||||||
"using_additional_inputs_as_variables": "איך ניתן להשתמש בסוגי קלט נוספים כמשתנים?",
|
"using_additional_inputs_as_variables": "איך ניתן להשתמש בסוגי קלט נוספים כמשתנים?",
|
||||||
"download_desktop_app": "הורדת האפליקציה למחשבים שולחניים",
|
"download_desktop_app": "הורדת האפליקציה למחשבים שולחניים",
|
||||||
"set_ping_link": "הגדרת קישור Ping",
|
"set_ping_link": "הגדרת קישור Ping",
|
||||||
|
"rate_limit_exceeded": "חריגה מההגבלה",
|
||||||
|
"when_something_happens": "כאשר משהו קורה",
|
||||||
|
"action_is_performed": "פעולה מבוצעת",
|
||||||
|
"test_action": "בדיקת פעולה",
|
||||||
|
"notification_sent": "נשלח עדכון",
|
||||||
|
"no_input": "אין קלט",
|
||||||
|
"test_workflow_action": "בדיקת פעולת תהליך עבודה",
|
||||||
|
"send_sms": "שליחת SMS",
|
||||||
|
"send_sms_to_number": "בטוח שברצונך לשלוח SMS למספר {{number}}?",
|
||||||
|
"missing_connected_calendar": "אף לוח שנה המוגדר כברירת מחדל לא מחובר",
|
||||||
|
"connect_your_calendar_and_link": "ניתן לחבר את לוח השנה שלך מ<1>כאן</1>.",
|
||||||
|
"default_calendar_selected": "לוח השנה המוגדר כברירת מחדל",
|
||||||
|
"hide_from_profile": "להסתיר מהפרופיל",
|
||||||
|
"event_setup_tab_title": "הגדרת האירוע",
|
||||||
|
"event_limit_tab_title": "מגבלות",
|
||||||
|
"event_limit_tab_description": "באיזו תדירות ניתן להזמין אותך",
|
||||||
|
"event_advanced_tab_description": "הגדרות לוח שנה ועוד...",
|
||||||
|
"event_advanced_tab_title": "מתקדם",
|
||||||
|
"select_which_cal": "בחר/י את לוח השנה שאליו יש להוסיף הזמנות",
|
||||||
|
"custom_event_name": "שם אירוע מותאם אישית",
|
||||||
|
"custom_event_name_description": "ניתן ליצור שמות אירועים בהתאמה אישית שיוצגו באירוע בלוח השנה",
|
||||||
|
"2fa_required": "נדרש אימות בשני גורמים",
|
||||||
|
"incorrect_2fa": "קוד שגוי של אימות בשני גורמים",
|
||||||
|
"which_event_type_apply": "על איזה סוג אירוע זה יחול?",
|
||||||
|
"no_workflows_description": "תהליכי עבודה מאפשרים שימוש באוטומציה פשוטה לשליחת עדכונים ותזכורות, כך שאת/ה יכול/ה לתכנן תהליכים שקשורים לאירועים שלך.",
|
||||||
|
"create_workflow": "יצירת תהליך עבודה",
|
||||||
|
"do_this": "יש לבצע את הפעולה הזו",
|
||||||
|
"turn_off": "השבתה",
|
||||||
|
"settings_updated_successfully": "עדכון ההגדרות בוצע בהצלחה",
|
||||||
|
"error_updating_settings": "שגיאה במהלך עדכון ההגדרות",
|
||||||
|
"personal_cal_url": "כתובת ה-URL של ה-Cal האישי שלי",
|
||||||
|
"bio_hint": "מספר משפטים אודותיך. המידע הזה יופיע בדף ה-URL האישי שלך.",
|
||||||
|
"delete_account_modal_title": "מחיקת חשבון",
|
||||||
|
"confirm_delete_account_modal": "בטוח שברצונך למחוק את חשבון Cal.com שלך?",
|
||||||
|
"delete_my_account": "מחיקת החשבון שלי",
|
||||||
|
"start_of_week": "תחילת השבוע",
|
||||||
|
"select_calendars": "בחר/י את לוחות השנה שבהם ברצונך לבדוק אם יש התנגשויות כדי למנוע כפל הזמנות.",
|
||||||
|
"check_for_conflicts": "בדיקת התנגשויות",
|
||||||
|
"adding_events_to": "הוספת אירועים ל",
|
||||||
|
"follow_system_preferences": "פעל לפי העדפות המערכת",
|
||||||
|
"custom_brand_colors": "צבעי מותג בהתאמה אישית",
|
||||||
|
"customize_your_brand_colors": "בצע/י התאמה אישית של דף ההזמנות שלך עם צבעי מותג משלך.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "הסרת מיתוגים הקשורים ל-Cal, כלומר 'מופעל על ידי Cal'.",
|
||||||
|
"profile_picture": "תמונת פרופיל",
|
||||||
|
"upload": "העלאה",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "סוג אירוע זה מוגן באמצעות טוקן.",
|
||||||
|
"rainbow_connect_wallet_gate": "קשר/י את הארנק שלך אם בבעלותך <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "אין בארנק שלך מספיק <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "חתום/י על בקשת ההודעה בארנק.",
|
||||||
|
"rainbow_signature_error": "שגיאה בעת בקשת חתימה מהארנק.",
|
||||||
|
"token_address": "כתובת הטוקן",
|
||||||
|
"blockchain": "בלוקצ'יין",
|
||||||
|
"old_password": "הסיסמה הקודמת",
|
||||||
|
"secure_password": "הסיסמה החדשה והסופר מאובטחת שלך",
|
||||||
|
"error_updating_password": "שגיאה בעת עדכון הסיסמה",
|
||||||
|
"two_factor_auth": "אימות בשני גורמים",
|
||||||
|
"recurring_event_tab_description": "הגדרת לוח זמנים חוזר",
|
||||||
|
"today": "היום",
|
||||||
|
"appearance": "מראה",
|
||||||
|
"appearance_subtitle": "ניהול ההגדרות של מראה ההזמנות שלך",
|
||||||
|
"my_account": "החשבון שלי",
|
||||||
|
"general": "כללי",
|
||||||
|
"calendars": "לוחות שנה",
|
||||||
|
"2fa_auth": "אימות בשני גורמים",
|
||||||
|
"invoices": "חשבוניות",
|
||||||
|
"embeds": "הטמעות",
|
||||||
|
"impersonation": "התחזות",
|
||||||
|
"users": "משתמשים",
|
||||||
|
"profile_description": "ניהול הגדרות עבור פרופיל Cal שלך",
|
||||||
|
"general_description": "ניהול הגדרות שפה ואזור זמן",
|
||||||
|
"calendars_description": "הגדרת האינטראקציה בין סוגי האירועים שלך לבין לוחות השנה שלך",
|
||||||
|
"appearance_description": "ניהול ההגדרות של מראה ההזמנות שלך",
|
||||||
|
"conferencing_description": "ניהול האפליקציות שלך לשיחות ועידה לשימוש בפגישות שלך",
|
||||||
|
"password_description": "ניהול הגדרות עבור סיסמאות החשבון שלך",
|
||||||
|
"2fa_description": "ניהול הגדרות עבור סיסמאות החשבון שלך",
|
||||||
|
"we_just_need_basic_info": "אנחנו זקוקים רק לכמה פרטים בסיסיים כדי להגדיר את הפרופיל שלך.",
|
||||||
|
"skip": "דלג",
|
||||||
|
"do_this_later": "לעשות זאת מאוחר יותר",
|
||||||
|
"set_availability_getting_started_subtitle_1": "הגדרת טווחי זמן שבהם את/ה זמין/ה",
|
||||||
|
"set_availability_getting_started_subtitle_2": "תוכל/י לבצע התאמה אישית של כל ההגדרות האלה מאוחר יותר בדף פרטי הזמינות.",
|
||||||
|
"connect_calendars_from_app_store": "ניתן להוסיף עוד לוחות שנה מה-App Store",
|
||||||
|
"connect_conference_apps": "חיבור אפליקציות של שיחות ועידה",
|
||||||
|
"connect_calendar_apps": "חיבור אפליקציות של לוחות שנה",
|
||||||
|
"connect_payment_apps": "חיבור אפליקציות של תשלומים",
|
||||||
|
"connect_other_apps": "חיבור אפליקציות אחרות",
|
||||||
|
"current_step_of_total": "שלב {{currentStep}} מתוך {{maxSteps}}",
|
||||||
|
"add_variable": "הוספת משתנה",
|
||||||
|
"custom_phone_number": "מספר טלפון בהתאמה אישית",
|
||||||
|
"message_template": "תבנית הודעות",
|
||||||
|
"email_subject": "נושא הדוא״ל",
|
||||||
|
"add_dynamic_variables": "הוספת משתני טקסט דינמיים",
|
||||||
|
"event_name_info": "שם סוג האירוע",
|
||||||
|
"event_date_info": "תאריך האירוע",
|
||||||
|
"event_time_info": "שעת ההתחלה של האירוע",
|
||||||
|
"location_info": "מיקום האירוע",
|
||||||
"organizer_name_info": "שמך",
|
"organizer_name_info": "שמך",
|
||||||
|
"additional_notes_info": "הערות נוספות בהזמנה",
|
||||||
|
"attendee_name_info": "שם האדם שביצע את ההזמנה",
|
||||||
|
"to": "אל",
|
||||||
|
"attendee_required_enter_number": "דבר זה יחייב את המשתתף/ת להזין מספר טלפון בעת ההזמנה",
|
||||||
|
"workflow_turned_on_successfully": "תהליך העבודה {{workflowName}} הועבר למצב {{offOn}} בהצלחה",
|
||||||
|
"download_responses": "הורדת התגובות",
|
||||||
|
"create_your_first_form": "יצירת הטופס הראשון שלך",
|
||||||
|
"create_your_first_form_description": "באמצעות טפסי ניתוב ניתן לשאול שאלות סיווג ולנתב אל האדם או אל סוג האירוע המתאימים.",
|
||||||
|
"create_your_first_webhook": "יצירת ה-Webhook הראשון שלך",
|
||||||
|
"create_your_first_webhook_description": "עם רכיבי Webhook ניתן לקבל נתוני פגישה בזמן אמת כשמשהו קורה ב-Cal.com.",
|
||||||
|
"for_a_maximum_of": "למקסימום של",
|
||||||
|
"event_one": "אירוע",
|
||||||
|
"event_other": "אירועים",
|
||||||
|
"profile_team_description": "ניהול הגדרות עבור פרופיל הצוות",
|
||||||
|
"members_team_description": "משתמשים שמשתייכים לקבוצה",
|
||||||
|
"team_url": "כתובת ה-URL של הצוות",
|
||||||
|
"delete_team": "מחיקת צוות",
|
||||||
|
"team_members": "חברי הצוות",
|
||||||
|
"more": "עוד",
|
||||||
|
"more_page_footer": "אנחנו רואים באפליקציה לנייד הרחבה של האפליקציה האינטרנטית. אם עליך לבצע פעולות מורכבות, כדאי לחזור אל האפליקציה האינטרנטית.",
|
||||||
|
"workflow_example_1": "שליחת תזכורת ב-SMS למשתתף/ת 24 שעות לפני תחילת האירוע",
|
||||||
|
"workflow_example_2": "שליחת SMS מותאם אישית למשתתף/ת כאשר המועד של אירוע משתנה",
|
||||||
|
"workflow_example_3": "שליחת דוא\"ל מותאם אישית למארח/ת כאשר אירוע חדש מוזמן",
|
||||||
|
"workflow_example_4": "שליחת תזכורת בדוא\"ל למשתתף/ת שעה לפני תחילת אירועים",
|
||||||
|
"workflow_example_5": "שליחת דוא\"ל מותאם אישית למארח/ת כאשר המועד של אירוע משתנה",
|
||||||
|
"workflow_example_6": "שליחת SMS מותאם אישית למארח/ת כאשר אירוע חדש מוזמן",
|
||||||
|
"welcome_to_cal_header": "ברוך בואך אל Cal.com!",
|
||||||
|
"edit_form_later_subtitle": "ניתן יהיה לערוך את זה מאוחר יותר.",
|
||||||
|
"connect_calendar_later": "אקשר את לוח השנה שלי מאוחר יותר",
|
||||||
|
"set_my_availability_later": "אגדיר את הזמינות שלי בהמשך",
|
||||||
|
"problem_saving_user_profile": "היתה בעיה בשמירת הנתונים שלך. נסה/י שוב או פנה/י לתמיכת לקוחות.",
|
||||||
|
"purchase_missing_seats": "חסרים מקומות ברכישה",
|
||||||
|
"slot_length": "אורך חלון הזמן",
|
||||||
|
"booking_appearance": "מראה ההזמנה",
|
||||||
|
"appearance_team_description": "ניהול ההגדרות של מראה הזמנות הצוות שלך",
|
||||||
|
"only_owner_change": "רק הבעלים של הצוות יכולים לבצע שינויים בהזמנה של הצוות ",
|
||||||
|
"team_disable_cal_branding_description": "הסרת מיתוגים הקשורים ל-Cal, כלומר 'מופעל על ידי Cal'",
|
||||||
|
"invited_by_team": "הוזמנת על ידי {{teamName}} להצטרף לצוות בתפקיד {{role}}",
|
||||||
|
"token_invalid_expired": "הטוקן לא חוקי או שתוקפו פג.",
|
||||||
|
"exchange_add": "התחבר/י אל Microsoft Exchange",
|
||||||
|
"exchange_authentication": "שיטת אימות",
|
||||||
|
"exchange_authentication_standard": "אימות בסיסי",
|
||||||
|
"exchange_authentication_ntlm": "אימות NTLM",
|
||||||
|
"exchange_compression": "דחיסת GZip",
|
||||||
|
"routing_forms_description": "כאן ניתן לראות את כל הטפסים והנתיבים שיצרת.",
|
||||||
|
"add_new_form": "הוספת טופס חדש",
|
||||||
|
"form_description": "צור/י טופס משלך כדי לנתב אל מזמין/ה",
|
||||||
|
"copy_link_to_form": "העתק את הקישור לטופס",
|
||||||
|
"theme": "ערכת נושא",
|
||||||
|
"theme_applies_note": "חל רק על הדפים של הזמנות ציבוריות",
|
||||||
"theme_light": "בהיר",
|
"theme_light": "בהיר",
|
||||||
"theme_dark": "כהה"
|
"theme_dark": "כהה",
|
||||||
|
"theme_system": "ברירת המחדל של המערכת",
|
||||||
|
"add_a_team": "הוספת צוות",
|
||||||
|
"saml_config": "תצורת SAML",
|
||||||
|
"add_webhook_description": "קבלת נתוני פגישה בזמן אמת כשמשהו קורה ב-Cal.com",
|
||||||
|
"triggers_when": "מופעל כאשר",
|
||||||
|
"test_webhook": "יש לבצע בדיקת Ping לפני היצירה.",
|
||||||
|
"enable_webhook": "הפעלת Webhook",
|
||||||
|
"add_webhook": "הוספת Webhook",
|
||||||
|
"webhook_edited_successfully": "ה-Webhook נשמר",
|
||||||
|
"webhooks_description": "קבלת נתוני פגישה בזמן אמת כשמשהו קורה ב-Cal.com",
|
||||||
|
"api_keys_description": "צור/י מפתחות API לקבלת גישה לחשבון שלך",
|
||||||
|
"new_api_key": "מפתח API חדש",
|
||||||
|
"active": "פעיל",
|
||||||
|
"api_key_updated": "שם מפתח ה-API עודכן",
|
||||||
|
"api_key_update_failed": "שגיאה בעת עדכון השם של מפתח ה-API",
|
||||||
|
"embeds_title": "הטמעת iframe של HTML",
|
||||||
|
"embeds_description": "הטמעת כל סוגי האירועים באתר",
|
||||||
|
"create_first_api_key": "יצירת מפתח ה-API הראשון שלך",
|
||||||
|
"create_first_api_key_description": "מפתחות API מאפשרים לאפליקציות אחרות לתקשר עם Cal.com",
|
||||||
|
"back_to_signin": "בחזרה לדף הכניסה",
|
||||||
|
"reset_link_sent": "נשלח קישור לאיפוס",
|
||||||
|
"password_reset_email": "שלחנו לך הודעת דוא\"ל לכתובת {{email}} עם הוראות לאיפוס הסיסמה.",
|
||||||
|
"password_updated": "הסיסמה עודכנה!",
|
||||||
|
"pending_payment": "בהמתנה לתשלום",
|
||||||
|
"confirmation_page_rainbow": "הגן/י על האירוע שלך באמצעות טוקנים או אסימוני NFT ב-Ethereum, ב-Polygon ועוד.",
|
||||||
|
"not_on_cal": "לא ב-Cal.com",
|
||||||
|
"no_calendar_installed": "לא מותקן אף לוח שנה",
|
||||||
|
"no_calendar_installed_description": "לא קישרת אף אחד מלוחות השנה שלך",
|
||||||
|
"add_a_calendar": "הוספת לוח שנה",
|
||||||
|
"change_email_hint": "ייתכן שיהיה צורך לצאת ולהיכנס שוב כדי לראות שהשינויים נכנסו לתוקף",
|
||||||
|
"confirm_password_change_email": "יש לאשר את הסיסמה לפני שינוי כתובת הדוא\"ל",
|
||||||
|
"seats": "מקומות",
|
||||||
|
"every_app_published": "כל אפליקציה שמתפרסמת ב-App Store של Cal.com היא בעלת קוד מקור פתוח. כל אפליקציה כזו גם נבדקה בקפידה על ידי עמיתים. למרות זאת, Cal.com, Inc. אינה מעודדת שימוש באף אפליקציה כזו ואינה מעניקה אישור לאף אפליקציה כזו, אלא אם מדובר באפליקציות שפורסמו על ידי Cal.com. אם נתקלת בהתנהגות או בתכנים בלתי הולמים, עליך לדווח על האפליקציה.",
|
||||||
|
"report_app": "דיווח על האפליקציה",
|
||||||
|
"billing_manage_details_title": "הצגה וניהול של פרטי החיוב",
|
||||||
|
"billing_manage_details_description": "כאן ניתן להציג ולנהל את פרטי החיוב, וכן לבטל את המינוי.",
|
||||||
|
"billing_help_title": "צריך משהו נוסף?",
|
||||||
|
"billing_help_description": "אם דרוש לך סיוע נוסף בענייני חיוב, צוות התמיכה שלנו כאן כדי לעזור."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "Usa il link qui sotto per reimpostare la tua password",
|
"use_link_to_reset_password": "Usa il link qui sotto per reimpostare la tua password",
|
||||||
"hey_there": "Ciao,",
|
"hey_there": "Ciao,",
|
||||||
"forgot_your_password_calcom": "Hai dimenticato la password? - Cal.com",
|
"forgot_your_password_calcom": "Hai dimenticato la password? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | Tipo di evento",
|
|
||||||
"delete_webhook_confirmation_message": "Sei sicuro di voler eliminare questo webhook? Non riceverai più Cal.com dati di riunione in un URL specificato, in tempo reale, quando un evento è programmato o annullato.",
|
"delete_webhook_confirmation_message": "Sei sicuro di voler eliminare questo webhook? Non riceverai più Cal.com dati di riunione in un URL specificato, in tempo reale, quando un evento è programmato o annullato.",
|
||||||
"confirm_delete_webhook": "Sì, elimina webhook",
|
"confirm_delete_webhook": "Sì, elimina webhook",
|
||||||
"edit_webhook": "Modifica Webhook",
|
"edit_webhook": "Modifica Webhook",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "Visualizza la pagina pubblica",
|
"view_public_page": "Visualizza la pagina pubblica",
|
||||||
"sign_out": "Esci",
|
"sign_out": "Esci",
|
||||||
"add_another": "Aggiungi un altro",
|
"add_another": "Aggiungi un altro",
|
||||||
|
"install_another": "Installa un altro",
|
||||||
"until": "fino a",
|
"until": "fino a",
|
||||||
"powered_by": "offerto da",
|
"powered_by": "offerto da",
|
||||||
"unavailable": "Non Disponibile",
|
"unavailable": "Non Disponibile",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "Casella di controllo",
|
"checkbox": "Casella di controllo",
|
||||||
"is_required": "È obbligatorio",
|
"is_required": "È obbligatorio",
|
||||||
"required": "Obbligatorio",
|
"required": "Obbligatorio",
|
||||||
|
"optional": "Facoltativo",
|
||||||
"input_type": "Tipo di input",
|
"input_type": "Tipo di input",
|
||||||
"rejected": "Rifiutato",
|
"rejected": "Rifiutato",
|
||||||
"unconfirmed": "Non Confermato",
|
"unconfirmed": "Non Confermato",
|
||||||
@@ -227,7 +228,9 @@
|
|||||||
"connect_your_calendar_instructions": "Collega il tuo calendario per controllare automaticamente gli orari occupati e i nuovi eventi appena vengono pianificati.",
|
"connect_your_calendar_instructions": "Collega il tuo calendario per controllare automaticamente gli orari occupati e i nuovi eventi appena vengono pianificati.",
|
||||||
"set_up_later": "Configura più tardi",
|
"set_up_later": "Configura più tardi",
|
||||||
"current_time": "Orario corrente",
|
"current_time": "Orario corrente",
|
||||||
|
"details": "Dettagli",
|
||||||
"welcome": "Benvenuto",
|
"welcome": "Benvenuto",
|
||||||
|
"welcome_back": "Bentornato",
|
||||||
"welcome_to_calcom": "Benvenuto in Cal.com",
|
"welcome_to_calcom": "Benvenuto in Cal.com",
|
||||||
"welcome_instructions": "Dimmi come chiamarti e facci sapere in che timezone sei. Potrai cambiarlo dopo.",
|
"welcome_instructions": "Dimmi come chiamarti e facci sapere in che timezone sei. Potrai cambiarlo dopo.",
|
||||||
"connect_caldav": "Connetti al server CalDav",
|
"connect_caldav": "Connetti al server CalDav",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "Quando",
|
"when": "Quando",
|
||||||
"where": "Dove",
|
"where": "Dove",
|
||||||
"add_to_calendar": "Aggiungi al calendario",
|
"add_to_calendar": "Aggiungi al calendario",
|
||||||
|
"add_another_calendar": "Aggiungi un altro calendario",
|
||||||
"other": "Altro",
|
"other": "Altro",
|
||||||
"emailed_you_and_attendees": "Abbiamo inviato via email a te e agli altri partecipanti un invito al calendario con tutti i dettagli.",
|
"emailed_you_and_attendees": "Abbiamo inviato via email a te e agli altri partecipanti un invito al calendario con tutti i dettagli.",
|
||||||
"emailed_you_and_attendees_recurring": "Abbiamo inviato via email a te e agli altri partecipanti un invito al primo di questi eventi ricorrenti.",
|
"emailed_you_and_attendees_recurring": "Abbiamo inviato via email a te e agli altri partecipanti un invito al primo di questi eventi ricorrenti.",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "Inserisci la nuova password che desideri per il tuo account.",
|
"enter_new_password": "Inserisci la nuova password che desideri per il tuo account.",
|
||||||
"reset_password": "Reimposta Password",
|
"reset_password": "Reimposta Password",
|
||||||
"change_your_password": "Cambia la tua password",
|
"change_your_password": "Cambia la tua password",
|
||||||
|
"show_password": "Mostra password",
|
||||||
|
"hide_password": "Nascondi password",
|
||||||
"try_again": "Prova Di Nuovo",
|
"try_again": "Prova Di Nuovo",
|
||||||
"request_is_expired": "Quella richiesta è scaduta.",
|
"request_is_expired": "Quella richiesta è scaduta.",
|
||||||
"reset_instructions": "Inserisci l'indirizzo email associato al tuo account e ti invieremo un link per reimpostare la password.",
|
"reset_instructions": "Inserisci l'indirizzo email associato al tuo account e ti invieremo un link per reimpostare la password.",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "Quando qualcuno prenoterà una riunione ricorrente con te, la riunione apparirà qui.",
|
"recurring_bookings": "Quando qualcuno prenoterà una riunione ricorrente con te, la riunione apparirà qui.",
|
||||||
"past_bookings": "Le tue prenotazioni passate appariranno qui.",
|
"past_bookings": "Le tue prenotazioni passate appariranno qui.",
|
||||||
"cancelled_bookings": "Le tue prenotazioni passate appariranno qui.",
|
"cancelled_bookings": "Le tue prenotazioni passate appariranno qui.",
|
||||||
|
"unconfirmed_bookings": "Le tue prenotazioni non confermate appariranno qui.",
|
||||||
"on": "su",
|
"on": "su",
|
||||||
"and": "e",
|
"and": "e",
|
||||||
"calendar_shows_busy_between": "Il tuo calendario ti mostra come occupato tra",
|
"calendar_shows_busy_between": "Il tuo calendario ti mostra come occupato tra",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "Prenotazione Annullata",
|
"booking_cancelled": "Prenotazione Annullata",
|
||||||
"booking_rescheduled": "Prenotazione Riprogrammata",
|
"booking_rescheduled": "Prenotazione Riprogrammata",
|
||||||
"booking_created": "Prenotazione Creata",
|
"booking_created": "Prenotazione Creata",
|
||||||
|
"meeting_ended": "Riunione terminata",
|
||||||
"form_submitted": "Modulo inviato",
|
"form_submitted": "Modulo inviato",
|
||||||
"event_triggers": "Attivatori Evento",
|
"event_triggers": "Attivatori Evento",
|
||||||
"subscriber_url": "Url del Subscriber",
|
"subscriber_url": "Url del Subscriber",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "Creiamo il primo utente amministratore.",
|
"lets_create_first_administrator_user": "Creiamo il primo utente amministratore.",
|
||||||
"new_member": "Nuovo Membro",
|
"new_member": "Nuovo Membro",
|
||||||
"invite": "Invita",
|
"invite": "Invita",
|
||||||
|
"add_team_members": "Aggiungi membri del team",
|
||||||
|
"add_team_members_description": "Invita altri utenti a unirsi al tuo team",
|
||||||
|
"add_team_member": "Aggiungi un membro del team",
|
||||||
"invite_new_member": "Invita un nuovo membro",
|
"invite_new_member": "Invita un nuovo membro",
|
||||||
"invite_new_team_member": "Invita qualcuno nel tuo team.",
|
"invite_new_team_member": "Invita qualcuno nel tuo team.",
|
||||||
"change_member_role": "Cambia il ruolo del membro del team",
|
"change_member_role": "Cambia il ruolo del membro del team",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "Crea il tuo primo team e invita altri utenti a lavorare insieme a te.",
|
"create_first_team_and_invite_others": "Crea il tuo primo team e invita altri utenti a lavorare insieme a te.",
|
||||||
"create_team_to_get_started": "Crea una squadra per iniziare",
|
"create_team_to_get_started": "Crea una squadra per iniziare",
|
||||||
"teams": "Team",
|
"teams": "Team",
|
||||||
|
"team": "Team",
|
||||||
"team_billing": "Fatturazione team",
|
"team_billing": "Fatturazione team",
|
||||||
"upgrade_to_flexible_pro_title": "Abbiamo cambiato la fatturazione per i team",
|
"upgrade_to_flexible_pro_title": "Abbiamo cambiato la fatturazione per i team",
|
||||||
"upgrade_to_flexible_pro_message": "Alcuni membri del tuo team non hanno un posto. Aggiorna il tuo piano Pro per coprire i posti mancanti.",
|
"upgrade_to_flexible_pro_message": "Alcuni membri del tuo team non hanno un posto. Aggiorna il tuo piano Pro per coprire i posti mancanti.",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "Fatturazione",
|
"billing": "Fatturazione",
|
||||||
"manage_your_billing_info": "Gestisci le tue informazioni di fatturazione e annulla il tuo abbonamento.",
|
"manage_your_billing_info": "Gestisci le tue informazioni di fatturazione e annulla il tuo abbonamento.",
|
||||||
"availability": "Disponibilità",
|
"availability": "Disponibilità",
|
||||||
|
"edit_availability": "Modifica disponibilità",
|
||||||
"configure_availability": "Cambia quando sei disponibile per le prenotazioni.",
|
"configure_availability": "Cambia quando sei disponibile per le prenotazioni.",
|
||||||
|
"copy_times_to": "Copia orari in",
|
||||||
"change_weekly_schedule": "Cambia il tuo programma settimanale",
|
"change_weekly_schedule": "Cambia il tuo programma settimanale",
|
||||||
"logo": "Logo",
|
"logo": "Logo",
|
||||||
"error": "Errore",
|
"error": "Errore",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "Il nome che apparirà nei calendari",
|
"event_name_tooltip": "Il nome che apparirà nei calendari",
|
||||||
"meeting_with_user": "Riunione con {ATTENDEE}",
|
"meeting_with_user": "Riunione con {ATTENDEE}",
|
||||||
"additional_inputs": "Input Aggiuntivi",
|
"additional_inputs": "Input Aggiuntivi",
|
||||||
|
"additional_input_description": "Chiedi al creatore del programma di inserire dei campi di input aggiuntivi prima che la prenotazione sia confermata",
|
||||||
"label": "Etichetta",
|
"label": "Etichetta",
|
||||||
"placeholder": "Segnaposto",
|
"placeholder": "Segnaposto",
|
||||||
"type": "Tipo",
|
"type": "Tipo",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "Disabilita Ospiti",
|
"disable_guests": "Disabilita Ospiti",
|
||||||
"disable_guests_description": "Disabilita l'aggiunta di ulteriori ospiti durante la prenotazione.",
|
"disable_guests_description": "Disabilita l'aggiunta di ulteriori ospiti durante la prenotazione.",
|
||||||
"private_link": "Genera URL privato",
|
"private_link": "Genera URL privato",
|
||||||
|
"private_link_label": "Link privato",
|
||||||
|
"private_link_hint": "Il tuo link privato verrà rigenerato dopo ogni utilizzo",
|
||||||
"copy_private_link": "Copia link privato",
|
"copy_private_link": "Copia link privato",
|
||||||
"private_link_description": "Genera un URL privato da condividere senza mostrare il tuo nome utente Cal",
|
"private_link_description": "Genera un URL privato da condividere senza mostrare il tuo nome utente Cal",
|
||||||
"invitees_can_schedule": "Gli inviti possono programmare",
|
"invitees_can_schedule": "Gli inviti possono programmare",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "Sei sicuro di voler eliminare il tuo account Cal.com? Chiunque abbia il link del tuo account non potrà più utilizzarlo per prenotare e le preferenze che hai salvato andranno perse.",
|
"delete_account_confirmation_message": "Sei sicuro di voler eliminare il tuo account Cal.com? Chiunque abbia il link del tuo account non potrà più utilizzarlo per prenotare e le preferenze che hai salvato andranno perse.",
|
||||||
"integrations": "Integrazioni",
|
"integrations": "Integrazioni",
|
||||||
"apps": "App",
|
"apps": "App",
|
||||||
|
"category_apps": "App {{category}}",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "Collegare persone, tecnologia e luogo di lavoro.",
|
"app_store_description": "Collegare persone, tecnologia e luogo di lavoro.",
|
||||||
"settings": "Impostazioni",
|
"settings": "Impostazioni",
|
||||||
"event_type_moved_successfully": "Il tipo di evento è stato spostato con successo",
|
"event_type_moved_successfully": "Il tipo di evento è stato spostato con successo",
|
||||||
|
"next_step_text": "Prossimo passo",
|
||||||
"next_step": "Salta passo",
|
"next_step": "Salta passo",
|
||||||
"prev_step": "Passo precedente",
|
"prev_step": "Passo precedente",
|
||||||
|
"install": "Installa",
|
||||||
"installed": "Installato",
|
"installed": "Installato",
|
||||||
"active_install_one": "{{count}} installazione attiva",
|
"active_install_one": "{{count}} installazione attiva",
|
||||||
"active_install_other": "{{count}} installazioni attive",
|
"active_install_other": "{{count}} installazioni attive",
|
||||||
"globally_install": "Installato a livello globale",
|
"globally_install": "Installato a livello globale",
|
||||||
|
"app_successfully_installed": "App installata correttamente",
|
||||||
|
"app_could_not_be_installed": "Impossibile installare l'app",
|
||||||
"disconnect": "Disconnetti",
|
"disconnect": "Disconnetti",
|
||||||
"embed_your_calendar": "Incorpora il tuo calendario nella tua pagina web",
|
"embed_your_calendar": "Incorpora il tuo calendario nella tua pagina web",
|
||||||
"connect_your_favourite_apps": "Collega le tue app preferite.",
|
"connect_your_favourite_apps": "Collega le tue app preferite.",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "Collega calendario aggiuntivo",
|
"connect_additional_calendar": "Collega calendario aggiuntivo",
|
||||||
"conferencing": "Conferenze",
|
"conferencing": "Conferenze",
|
||||||
"calendar": "Calendario",
|
"calendar": "Calendario",
|
||||||
|
"payments": "Pagamenti",
|
||||||
"not_installed": "Non installato",
|
"not_installed": "Non installato",
|
||||||
"error_password_mismatch": "Le password non corrispondono.",
|
"error_password_mismatch": "Le password non corrispondono.",
|
||||||
"error_required_field": "Questo campo è richiesto.",
|
"error_required_field": "Questo campo è richiesto.",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "Importa da",
|
"import_from": "Importa da",
|
||||||
"access_token": "Token di accesso",
|
"access_token": "Token di accesso",
|
||||||
"visit_roadmap": "Roadmap",
|
"visit_roadmap": "Roadmap",
|
||||||
|
"featured_categories": "Categorie in evidenza",
|
||||||
"popular_categories": "Categorie popolari",
|
"popular_categories": "Categorie popolari",
|
||||||
|
"number_apps_one": "{{count}} App",
|
||||||
|
"number_apps_other": "{{count}} app",
|
||||||
"trending_apps": "App di tendenza",
|
"trending_apps": "App di tendenza",
|
||||||
|
"explore_apps": "App {{category}}",
|
||||||
"installed_apps": "App installate",
|
"installed_apps": "App installate",
|
||||||
|
"no_category_apps": "Nessuna app {{category}}",
|
||||||
|
"no_category_apps_description_calendar": "Aggiungi un'app di calendario per controllare i conflitti ed evitare doppie prenotazioni",
|
||||||
|
"no_category_apps_description_conferencing": "Prova ad aggiungere un'app di conferenza per integrare le videochiamate con i clienti",
|
||||||
|
"no_category_apps_description_payment": "Aggiungi un'app di pagamento per facilitare le transazioni con i clienti",
|
||||||
|
"no_category_apps_description_other": "Aggiungi qualsiasi altra app per fare altre attività",
|
||||||
|
"installed_app_calendar_description": "Imposta uno o più calendari per controllare i conflitti ed evitare doppie prenotazioni.",
|
||||||
|
"installed_app_conferencing_description": "Aggiungi le tue app di videoconferenza preferite per le tue riunioni",
|
||||||
|
"installed_app_payment_description": "Configura quale servizio di elaborazione dei pagamenti usare per addebitare i clienti.",
|
||||||
|
"installed_app_other_description": "Tutte le app installate appartenenti alle altre categorie.",
|
||||||
"empty_installed_apps_headline": "Nessuna app installata",
|
"empty_installed_apps_headline": "Nessuna app installata",
|
||||||
"empty_installed_apps_description": "Le app consentono di ottimizzare il flusso di lavoro e di migliorare significativamente la pianificazione.",
|
"empty_installed_apps_description": "Le app consentono di ottimizzare il flusso di lavoro e di migliorare significativamente la pianificazione.",
|
||||||
"empty_installed_apps_button": "Esplora l'App Store",
|
"empty_installed_apps_button": "Esplora l'App Store",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "Rimuovi",
|
"remove": "Rimuovi",
|
||||||
"add": "Aggiungi",
|
"add": "Aggiungi",
|
||||||
"installed_one": "Installato",
|
"installed_one": "Installato",
|
||||||
|
"installed_other": "{{count}} installate",
|
||||||
"verify_wallet": "Verifica Wallet",
|
"verify_wallet": "Verifica Wallet",
|
||||||
"connect_metamask": "Connetti Metamask",
|
"connect_metamask": "Connetti Metamask",
|
||||||
"create_events_on": "Crea eventi su:",
|
"create_events_on": "Crea eventi su:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "Impostazione predefinita",
|
"set_to_default": "Impostazione predefinita",
|
||||||
"new_schedule_btn": "Nuovo programma",
|
"new_schedule_btn": "Nuovo programma",
|
||||||
"add_new_schedule": "Aggiungi un nuovo programma",
|
"add_new_schedule": "Aggiungi un nuovo programma",
|
||||||
|
"add_new_calendar": "Aggiungi un nuovo calendario",
|
||||||
|
"set_calendar": "Imposta dove aggiungere nuovi eventi quando vi è una prenotazione.",
|
||||||
"delete_schedule": "Elimina programma",
|
"delete_schedule": "Elimina programma",
|
||||||
"schedule_created_successfully": "Programma {{scheduleName}} creato",
|
"schedule_created_successfully": "Programma {{scheduleName}} creato",
|
||||||
"availability_updated_successfully": "Disponibilità aggiornata con successo",
|
"availability_updated_successfully": "Disponibilità aggiornata con successo",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "Reindirizza su prenotazione ",
|
"redirect_success_booking": "Reindirizza su prenotazione ",
|
||||||
"you_are_being_redirected": "Verrai reindirizzato a {{ url }} tra $t(second, {\"count\": {{seconds}} }).",
|
"you_are_being_redirected": "Verrai reindirizzato a {{ url }} tra $t(second, {\"count\": {{seconds}} }).",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "Per poter utilizzare questa funzionalità, è necessario passare a un account Pro.",
|
|
||||||
"duplicate": "Duplica",
|
"duplicate": "Duplica",
|
||||||
"offer_seats": "Imposta posti",
|
"offer_seats": "Imposta posti",
|
||||||
"offer_seats_description": "Imposta i posti da prenotare (ciò disabiliterà le prenotazioni ospite e le prenotazioni opt-in)",
|
"offer_seats_description": "Imposta i posti da prenotare (ciò disabiliterà le prenotazioni ospite e le prenotazioni opt-in)",
|
||||||
@@ -811,7 +849,7 @@
|
|||||||
"api_key": "Chiave API",
|
"api_key": "Chiave API",
|
||||||
"test_api_key": "Prova chiave API",
|
"test_api_key": "Prova chiave API",
|
||||||
"test_passed": "Test superato!",
|
"test_passed": "Test superato!",
|
||||||
"test_failed": "Test non superato",
|
"test_failed": "Prova non superata",
|
||||||
"provide_api_key": "Fornisci chiave API",
|
"provide_api_key": "Fornisci chiave API",
|
||||||
"api_key_modal_subtitle": "Le chiavi API consentono di effettuare chiamate API per il proprio account.",
|
"api_key_modal_subtitle": "Le chiavi API consentono di effettuare chiamate API per il proprio account.",
|
||||||
"api_keys_subtitle": "Genera chiavi API da usare per accedere al tuo account.",
|
"api_keys_subtitle": "Genera chiavi API da usare per accedere al tuo account.",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "Flussi di lavoro",
|
"workflows": "Flussi di lavoro",
|
||||||
"new_workflow_btn": "Nuovo flusso di lavoro",
|
"new_workflow_btn": "Nuovo flusso di lavoro",
|
||||||
"add_new_workflow": "Aggiungi un nuovo flusso di lavoro",
|
"add_new_workflow": "Aggiungi un nuovo flusso di lavoro",
|
||||||
|
"reschedule_event_trigger": "quando un evento viene riprogrammato",
|
||||||
"trigger": "Attivatore",
|
"trigger": "Attivatore",
|
||||||
"triggers": "Attivatori",
|
"triggers": "Attivatori",
|
||||||
"action": "Azione",
|
"action": "Azione",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "Poiché stai passando da un nome utente standard a un nome utente premium, sarai portato alla pagina di pagamento per effettuare l'upgrade.",
|
"change_username_standard_to_premium": "Poiché stai passando da un nome utente standard a un nome utente premium, sarai portato alla pagina di pagamento per effettuare l'upgrade.",
|
||||||
"change_username_premium_to_standard": "Poiché stai passando da un nome utente premium a un nome utente standard, sarai portato alla pagina di pagamento per effettuare il downgrade.",
|
"change_username_premium_to_standard": "Poiché stai passando da un nome utente premium a un nome utente standard, sarai portato alla pagina di pagamento per effettuare il downgrade.",
|
||||||
"go_to_stripe_billing": "Vai alla fatturazione",
|
"go_to_stripe_billing": "Vai alla fatturazione",
|
||||||
|
"stripe_description": "Richiedi pagamento per le prenotazioni (0,5% + 0,10 € di commissione per transazione)",
|
||||||
"trial_expired": "Il periodo di prova è scaduto",
|
"trial_expired": "Il periodo di prova è scaduto",
|
||||||
"remove_app": "Rimuovi app",
|
"remove_app": "Rimuovi app",
|
||||||
"yes_remove_app": "Sì, rimuovi l'app",
|
"yes_remove_app": "Sì, rimuovi l'app",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "Rimuovere questa app?",
|
"are_you_sure_you_want_to_remove_this_app": "Rimuovere questa app?",
|
||||||
|
"app_removed_successfully": "App rimossa correttamente",
|
||||||
|
"error_removing_app": "Errore durante la rimozione dell'app",
|
||||||
"web_conference": "Conferenza Web",
|
"web_conference": "Conferenza Web",
|
||||||
"number_for_sms_reminders": "Numero di telefono (per promemoria via SMS)",
|
"number_for_sms_reminders": "Numero di telefono (per promemoria via SMS)",
|
||||||
"requires_confirmation": "Richiede conferma",
|
"requires_confirmation": "Richiede conferma",
|
||||||
@@ -1022,20 +1064,209 @@
|
|||||||
"navigate": "Esplora",
|
"navigate": "Esplora",
|
||||||
"open": "Apri",
|
"open": "Apri",
|
||||||
"close": "Chiudi",
|
"close": "Chiudi",
|
||||||
|
"team_feature_teams": "Questa è una funzionalità del piano Team. Effettua l'upgrade al piano Team per vedere la disponibilità del tuo team.",
|
||||||
|
"team_feature_workflows": "Questa è una funzionalità del piano Team. Effettua l'upgrade al piano Team per automatizzare le notifiche e i promemoria degli eventi per i flussi di lavoro.",
|
||||||
|
"show_eventtype_on_profile": "Mostra nel profilo",
|
||||||
"embed": "Incorpora",
|
"embed": "Incorpora",
|
||||||
"new_username": "Nuovo nome utente",
|
"new_username": "Nuovo nome utente",
|
||||||
"current_username": "Nome utente corrente",
|
"current_username": "Nome utente corrente",
|
||||||
"example_1": "Esempio 1",
|
"example_1": "Esempio 1",
|
||||||
"example_2": "Esempio 2",
|
"example_2": "Esempio 2",
|
||||||
|
"additional_input_label": "Etichetta del campo di input aggiuntivo",
|
||||||
"company_size": "Dimensione dell'azienda",
|
"company_size": "Dimensione dell'azienda",
|
||||||
"what_help_needed": "Per cosa ti serve assistenza?",
|
"what_help_needed": "Per cosa ti serve assistenza?",
|
||||||
"variable_format": "Formato variabile",
|
"variable_format": "Formato variabile",
|
||||||
|
"webhook_subscriber_url_reserved": "URL dell'abbonato Webhook già definito",
|
||||||
"custom_input_as_variable_info": "Ignora tutti i caratteri speciali dell'etichetta del campo di input aggiuntivo (usa solo lettere e numeri), usa solo lettere maiuscole e sostituisci gli spazi con il trattino basso.",
|
"custom_input_as_variable_info": "Ignora tutti i caratteri speciali dell'etichetta del campo di input aggiuntivo (usa solo lettere e numeri), usa solo lettere maiuscole e sostituisci gli spazi con il trattino basso.",
|
||||||
"using_additional_inputs_as_variables": "Come usare i campi di input aggiuntivi come variabili?",
|
"using_additional_inputs_as_variables": "Come usare i campi di input aggiuntivi come variabili?",
|
||||||
"download_desktop_app": "Scarica app desktop",
|
"download_desktop_app": "Scarica app desktop",
|
||||||
"set_ping_link": "Imposta link di Ping",
|
"set_ping_link": "Imposta link di Ping",
|
||||||
|
"rate_limit_exceeded": "Limite superato",
|
||||||
|
"when_something_happens": "Quando succede qualcosa",
|
||||||
|
"action_is_performed": "Viene eseguita un'azione",
|
||||||
|
"test_action": "Verifica azione",
|
||||||
|
"notification_sent": "Notifica inviata",
|
||||||
|
"no_input": "Nessun input",
|
||||||
|
"test_workflow_action": "Verifica azione del flusso di lavoro",
|
||||||
|
"send_sms": "Invia SMS",
|
||||||
|
"send_sms_to_number": "Inviare un SMS a {{number}}?",
|
||||||
"missing_connected_calendar": "Nessun calendario predefinito collegato",
|
"missing_connected_calendar": "Nessun calendario predefinito collegato",
|
||||||
|
"connect_your_calendar_and_link": "Puoi collegare il tuo calendario <1>qui</1>.",
|
||||||
|
"default_calendar_selected": "Calendario predefinito",
|
||||||
|
"hide_from_profile": "Nascondi nel profilo",
|
||||||
|
"event_setup_tab_title": "Impostazione evento",
|
||||||
|
"event_limit_tab_title": "Limiti",
|
||||||
|
"event_limit_tab_description": "Con quale frequenza è possibile fare una prenotazione",
|
||||||
|
"event_advanced_tab_description": "Impostazioni calendario e altro...",
|
||||||
|
"event_advanced_tab_title": "Avanzate",
|
||||||
|
"select_which_cal": "Seleziona il calendario al quale aggiungere prenotazioni",
|
||||||
|
"custom_event_name": "Nome evento personalizzato",
|
||||||
|
"custom_event_name_description": "Crea nomi di eventi personalizzati da visualizzare nell'evento del calendario",
|
||||||
|
"2fa_required": "Autenticazione a due fattori necessaria",
|
||||||
|
"incorrect_2fa": "Codice di autenticazione a due fattori errato",
|
||||||
|
"which_event_type_apply": "A quale tipo di evento si applicherà?",
|
||||||
|
"no_workflows_description": "I flussi di lavoro attivano una semplice automazione per inviare notifiche e promemoria che ti consentono di creare processi per i tuoi eventi.",
|
||||||
|
"create_workflow": "Crea un flusso di lavoro",
|
||||||
|
"do_this": "Esegui questa operazione",
|
||||||
|
"turn_off": "Disattiva",
|
||||||
|
"settings_updated_successfully": "Impostazioni aggiornate correttamente",
|
||||||
|
"error_updating_settings": "Errore durante l'aggiornamento delle impostazioni",
|
||||||
|
"personal_cal_url": "Il mio URL personale di Cal",
|
||||||
|
"bio_hint": "Scrivi qualcosa di te. Queste informazioni appariranno nella tua pagina personale.",
|
||||||
|
"delete_account_modal_title": "Elimina account",
|
||||||
|
"confirm_delete_account_modal": "Eliminare il tuo account Cal.com?",
|
||||||
|
"delete_my_account": "Elimina il mio account",
|
||||||
|
"start_of_week": "Inizio della settimana",
|
||||||
|
"select_calendars": "Seleziona su quali calendari desideri controllare i conflitti per evitare doppie prenotazioni.",
|
||||||
|
"check_for_conflicts": "Controlla conflitti",
|
||||||
|
"adding_events_to": "Aggiungendo eventi a",
|
||||||
|
"follow_system_preferences": "Segui le preferenze di sistema",
|
||||||
|
"custom_brand_colors": "Colori del marchio personalizzati",
|
||||||
|
"customize_your_brand_colors": "Personalizza la tua pagina di prenotazione con i colori del tuo marchio.",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "Rimuove tutte le scritte con il marchio Cal, ad es., 'Powered by Cal.'",
|
||||||
|
"profile_picture": "Immagine del profilo",
|
||||||
|
"upload": "Carica",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "Questo tipo di evento è protetto da token.",
|
||||||
|
"rainbow_connect_wallet_gate": "Collega il tuo portafoglio se possiedi <1>{{name}}</1> (<3>{{symbol}}</3>).",
|
||||||
|
"rainbow_insufficient_balance": "Il portafoglio collegato non contiene abbastanza <1>{{symbol}}</1>.",
|
||||||
|
"rainbow_sign_message_request": "Firma la richiesta di messaggio sul tuo portafoglio.",
|
||||||
|
"rainbow_signature_error": "Errore durante la richiesta di firma al tuo portafoglio.",
|
||||||
|
"token_address": "Indirizzo token",
|
||||||
|
"blockchain": "Blockchain",
|
||||||
|
"old_password": "Vecchia password",
|
||||||
|
"secure_password": "La tua nuova password super sicura",
|
||||||
|
"error_updating_password": "Errore durante l'aggiornamento della password",
|
||||||
|
"two_factor_auth": "Autenticazione a due fattori",
|
||||||
|
"recurring_event_tab_description": "Imposta una pianificazione ricorrente",
|
||||||
|
"today": "oggi",
|
||||||
|
"appearance": "Aspetto",
|
||||||
|
"appearance_subtitle": "Gestisci le impostazioni di aspetto delle tue prenotazioni",
|
||||||
|
"my_account": "Il mio account",
|
||||||
|
"general": "Generale",
|
||||||
|
"calendars": "Calendari",
|
||||||
|
"2fa_auth": "Autenticazione a due fattori",
|
||||||
|
"invoices": "Fatture",
|
||||||
|
"embeds": "Incorpora",
|
||||||
|
"impersonation": "Impersonificazione",
|
||||||
|
"users": "Utenti",
|
||||||
|
"profile_description": "Gestisci le impostazioni del tuo profilo cal",
|
||||||
|
"general_description": "Gestisci le impostazioni di lingua e fuso orario",
|
||||||
|
"calendars_description": "Configura come i tipi di eventi devono interagire con i tuoi calendari",
|
||||||
|
"appearance_description": "Gestisci le impostazioni di aspetto delle tue prenotazioni",
|
||||||
|
"conferencing_description": "Gestisci le app di videoconferenza per le tue riunioni",
|
||||||
|
"password_description": "Gestisci le impostazioni relative alle password del tuo account",
|
||||||
|
"2fa_description": "Gestisci le impostazioni relative alle password del tuo account",
|
||||||
|
"we_just_need_basic_info": "Abbiamo bisogno di alcune informazioni di base per completare la configurazione del tuo profilo.",
|
||||||
|
"skip": "Salta",
|
||||||
|
"do_this_later": "Più tardi",
|
||||||
|
"set_availability_getting_started_subtitle_1": "Definisci gli intervalli di tempo quando sei disponibile",
|
||||||
|
"set_availability_getting_started_subtitle_2": "È possibile personalizzare queste impostazioni in un secondo tempo nella pagina della disponibilità.",
|
||||||
|
"connect_calendars_from_app_store": "È possibile aggiungere altri calendari dall'App store",
|
||||||
|
"connect_conference_apps": "Connetti app di conferenza",
|
||||||
|
"connect_calendar_apps": "Connetti app di calendario",
|
||||||
|
"connect_payment_apps": "Connetti app di pagamento",
|
||||||
|
"connect_other_apps": "Connetti altre app",
|
||||||
|
"current_step_of_total": "Passo {{currentStep}} di {{maxSteps}}",
|
||||||
|
"add_variable": "Aggiungi variabile",
|
||||||
|
"custom_phone_number": "Numero di telefono personalizzato",
|
||||||
|
"message_template": "Modello di messaggio",
|
||||||
|
"email_subject": "Oggetto e-mail",
|
||||||
|
"add_dynamic_variables": "Aggiungi variabili di testo dinamico",
|
||||||
|
"event_name_info": "Nome del tipo di evento",
|
||||||
|
"event_date_info": "Data dell'evento",
|
||||||
|
"event_time_info": "Ora di inizio dell'evento",
|
||||||
|
"location_info": "Luogo dell'evento",
|
||||||
"organizer_name_info": "Il tuo nome",
|
"organizer_name_info": "Il tuo nome",
|
||||||
|
"additional_notes_info": "Note aggiuntive sulla prenotazione",
|
||||||
|
"attendee_name_info": "Nome della persona che prenota",
|
||||||
|
"to": "A",
|
||||||
|
"attendee_required_enter_number": "Al partecipante verrà richiesto di inserire un numero di telefono al momento della prenotazione",
|
||||||
|
"workflow_turned_on_successfully": "Flusso di lavoro {{workflowName}} impostato come {{offOn}} correttamente",
|
||||||
|
"download_responses": "Scarica risposte",
|
||||||
|
"create_your_first_form": "Crea il tuo primo modulo",
|
||||||
|
"create_your_first_form_description": "I Moduli di instradamento consentono di porre domande qualificanti agli utenti per indirizzarli a persone o eventi pertinenti.",
|
||||||
|
"create_your_first_webhook": "Crea il tuo primo Webhook",
|
||||||
|
"create_your_first_webhook_description": "I Webhook consentono di ricevere in tempo reale le informazioni sulle riunioni quando si verifica un evento su Cal.com.",
|
||||||
|
"for_a_maximum_of": "Per un massimo di",
|
||||||
|
"event_one": "evento",
|
||||||
|
"event_other": "eventi",
|
||||||
|
"profile_team_description": "Gestisci le impostazioni del profilo del tuo team",
|
||||||
|
"members_team_description": "Utenti nel gruppo",
|
||||||
|
"team_url": "URL del team",
|
||||||
|
"delete_team": "Elimina team",
|
||||||
|
"team_members": "Membri del team",
|
||||||
|
"more": "Altro",
|
||||||
|
"more_page_footer": "Consideriamo l'applicazione mobile un'estensione dell'applicazione web. Se si stanno eseguendo delle azioni complesse, si prega di fare riferimento all'applicazione web.",
|
||||||
|
"workflow_example_1": "Invia al partecipante un promemoria via SMS 24 ore prima dell'inizio dell'evento",
|
||||||
|
"workflow_example_2": "Invia al partecipante un SMS personalizzato se l'evento viene riprogrammato",
|
||||||
|
"workflow_example_3": "Invia all'organizzatore un'e-mail personalizzata quando viene prenotato un nuovo evento",
|
||||||
|
"workflow_example_4": "Invia al partecipante un promemoria via e-mail un'ora prima dell'inizio dell'evento",
|
||||||
|
"workflow_example_5": "Invia all'organizzatore un'e-mail personalizzata se l'evento viene riprogrammato",
|
||||||
|
"workflow_example_6": "Invia all'organizzatore un SMS personalizzato quando viene prenotato un nuovo evento",
|
||||||
|
"welcome_to_cal_header": "Benvenuto in Cal.com!",
|
||||||
|
"edit_form_later_subtitle": "Sarà possibile apportare modifiche in un secondo tempo.",
|
||||||
|
"connect_calendar_later": "Connetterò il mio calendario più tardi",
|
||||||
|
"set_my_availability_later": "Configurerò la mia disponibilità più tardi",
|
||||||
|
"problem_saving_user_profile": "Si è verificato un problema durante il salvataggio dei dati. Riprovare o contattare l'assistenza clienti.",
|
||||||
|
"purchase_missing_seats": "Acquista posti mancanti",
|
||||||
|
"slot_length": "Durata della fascia oraria",
|
||||||
|
"booking_appearance": "Aspetto prenotazione",
|
||||||
|
"appearance_team_description": "Gestisci le impostazioni di aspetto delle prenotazioni del tuo team",
|
||||||
|
"only_owner_change": "Solo il proprietario del team può apportare modifiche alla prenotazione del team ",
|
||||||
|
"team_disable_cal_branding_description": "Rimuove tutte le scritte con il marchio Cal, ad es., 'Powered by Cal'",
|
||||||
|
"invited_by_team": "{{teamName}} ti ha invitato a unirti al team come {{role}}",
|
||||||
|
"token_invalid_expired": "Il token non è valido o scaduto.",
|
||||||
|
"exchange_add": "Connetti a Microsoft Exchange",
|
||||||
|
"exchange_authentication": "Metodo di autenticazione",
|
||||||
|
"exchange_authentication_standard": "Autenticazione di base",
|
||||||
|
"exchange_authentication_ntlm": "Autenticazione NTLM",
|
||||||
|
"exchange_compression": "Compressione GZip",
|
||||||
|
"routing_forms_description": "È possibile vedere qui tutti i moduli e tutti i percorsi che hai creato.",
|
||||||
|
"add_new_form": "Aggiungi nuovo modulo",
|
||||||
|
"form_description": "Crea un modulo per instradare le persone che prenotano",
|
||||||
|
"copy_link_to_form": "Copia il link al modulo",
|
||||||
|
"theme": "Tema",
|
||||||
|
"theme_applies_note": "Si applica solo alle pagine di prenotazione pubbliche",
|
||||||
"theme_light": "Chiaro",
|
"theme_light": "Chiaro",
|
||||||
"theme_dark": "Scuro"
|
"theme_dark": "Scuro",
|
||||||
|
"theme_system": "Predefinito di sistema",
|
||||||
|
"add_a_team": "Aggiungi un team",
|
||||||
|
"saml_config": "Configurazione SAML",
|
||||||
|
"add_webhook_description": "Ricevi in tempo reale le informazioni sulle riunioni quando si verifica un evento su Cal.com",
|
||||||
|
"triggers_when": "Viene attivato quando",
|
||||||
|
"test_webhook": "Eseguire un test del ping prima di creare.",
|
||||||
|
"enable_webhook": "Abilita Webhook",
|
||||||
|
"add_webhook": "Aggiungi Webhook",
|
||||||
|
"webhook_edited_successfully": "Webhook salvato",
|
||||||
|
"webhooks_description": "Ricevi in tempo reale le informazioni sulle riunioni quando si verifica un evento su Cal.com",
|
||||||
|
"api_keys_description": "Genera chiavi API per accedere al tuo account",
|
||||||
|
"new_api_key": "Nuova chiave API",
|
||||||
|
"active": "Attivo",
|
||||||
|
"api_key_updated": "Nome chiave API aggiornato",
|
||||||
|
"api_key_update_failed": "Errore durante l'aggiornamento del nome della chiave API",
|
||||||
|
"embeds_title": "iframe HTML incorporato",
|
||||||
|
"embeds_description": "Incorpora tutti i tipi di eventi nel tuo sito web",
|
||||||
|
"create_first_api_key": "Crea la tua prima chiave API",
|
||||||
|
"create_first_api_key_description": "Le chiavi API consentono alle altre applicazioni di comunicare con Cal.com",
|
||||||
|
"back_to_signin": "Torna alla pagina di accesso",
|
||||||
|
"reset_link_sent": "Link per la reimpostazione inviato",
|
||||||
|
"password_reset_email": "Un'e-mail con le istruzioni per reimpostare la password è stata inviata all'indirizzo {{email}}.",
|
||||||
|
"password_updated": "Password aggiornata!",
|
||||||
|
"pending_payment": "Pagamento in sospeso",
|
||||||
|
"confirmation_page_rainbow": "Proteggi i tuoi eventi con token o NFT su Ethereum, Polygon e altri.",
|
||||||
|
"not_on_cal": "Non presente su Cal.com",
|
||||||
|
"no_calendar_installed": "Nessun calendario installato",
|
||||||
|
"no_calendar_installed_description": "Non hai ancora collegato alcun calendario",
|
||||||
|
"add_a_calendar": "Aggiungi un calendario",
|
||||||
|
"change_email_hint": "Per rendere effettive le modifiche, potrebbe essere necessario disconnettersi e accedere nuovamente",
|
||||||
|
"confirm_password_change_email": "Conferma la password prima di cambiare l'indirizzo e-mail",
|
||||||
|
"seats": "posti",
|
||||||
|
"every_app_published": "Tutte le applicazioni pubblicate nell'App store di Cal.com sono open source e sono state testate in modo approfondito attraverso una valutazione tra pari. Tuttavia, Cal.com, Inc. non promuove né certifica tali applicazioni, a meno che non siano pubblicate da Cal.com. Se notate contenuti o comportamenti inappropriati, vi preghiamo di segnalarceli.",
|
||||||
|
"report_app": "Segnala app",
|
||||||
|
"billing_manage_details_title": "Visualizza e gestisci i tuoi dettagli di fatturazione",
|
||||||
|
"billing_manage_details_description": "Visualizza e modifica i tuoi dati di fatturazione, puoi anche modificare la tua subcription.",
|
||||||
|
"billing_help_title": "Hai bisogno di altro?",
|
||||||
|
"billing_help_description": "Se hai bisogno di ulteriore aiuto per la fatturazione, il nostro team di supporto è qui per aiutarti."
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@
|
|||||||
"use_link_to_reset_password": "以下のリンクを使用してパスワードをリセットしてください",
|
"use_link_to_reset_password": "以下のリンクを使用してパスワードをリセットしてください",
|
||||||
"hey_there": "こんにちは!",
|
"hey_there": "こんにちは!",
|
||||||
"forgot_your_password_calcom": "パスワードをお忘れですか? - Cal.com",
|
"forgot_your_password_calcom": "パスワードをお忘れですか? - Cal.com",
|
||||||
"event_type_title": "{{eventTypeTitle}} | イベントタイプ",
|
|
||||||
"delete_webhook_confirmation_message": "このウェブフックを削除してもよろしいですか? イベントがスケジュールまたはキャンセルされたときに、指定された URL でのミーティングデータをリアルタイムには受け取れなくなります。",
|
"delete_webhook_confirmation_message": "このウェブフックを削除してもよろしいですか? イベントがスケジュールまたはキャンセルされたときに、指定された URL でのミーティングデータをリアルタイムには受け取れなくなります。",
|
||||||
"confirm_delete_webhook": "はい、ウェブフックを削除します",
|
"confirm_delete_webhook": "はい、ウェブフックを削除します",
|
||||||
"edit_webhook": "ウェブフックを編集",
|
"edit_webhook": "ウェブフックを編集",
|
||||||
@@ -143,6 +142,7 @@
|
|||||||
"view_public_page": "公開ページを表示する",
|
"view_public_page": "公開ページを表示する",
|
||||||
"sign_out": "ログアウト",
|
"sign_out": "ログアウト",
|
||||||
"add_another": "さらに追加",
|
"add_another": "さらに追加",
|
||||||
|
"install_another": "別のものをインストール",
|
||||||
"until": "まで",
|
"until": "まで",
|
||||||
"powered_by": "powered by",
|
"powered_by": "powered by",
|
||||||
"unavailable": "利用不可",
|
"unavailable": "利用不可",
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
"checkbox": "チェックボックス",
|
"checkbox": "チェックボックス",
|
||||||
"is_required": "必須項目",
|
"is_required": "必須項目",
|
||||||
"required": "必須",
|
"required": "必須",
|
||||||
|
"optional": "任意",
|
||||||
"input_type": "入力形式",
|
"input_type": "入力形式",
|
||||||
"rejected": "拒否されました",
|
"rejected": "拒否されました",
|
||||||
"unconfirmed": "未確認",
|
"unconfirmed": "未確認",
|
||||||
@@ -227,10 +228,12 @@
|
|||||||
"connect_your_calendar_instructions": "カレンダーに接続すると、予定済の忙しい時間と新しいイベントを自動的に確認できます。",
|
"connect_your_calendar_instructions": "カレンダーに接続すると、予定済の忙しい時間と新しいイベントを自動的に確認できます。",
|
||||||
"set_up_later": "あとで設定",
|
"set_up_later": "あとで設定",
|
||||||
"current_time": "現在の時刻",
|
"current_time": "現在の時刻",
|
||||||
|
"details": "詳細",
|
||||||
"welcome": "ようこそ",
|
"welcome": "ようこそ",
|
||||||
|
"welcome_back": "おかえりなさい",
|
||||||
"welcome_to_calcom": "Cal.com へようこそ",
|
"welcome_to_calcom": "Cal.com へようこそ",
|
||||||
"welcome_instructions": "Cal.com でご使用になるお名前とタイムゾーンを教えてください。これらは後から編集できます。",
|
"welcome_instructions": "Cal.com でご使用になるお名前とタイムゾーンを教えてください。これらは後から編集できます。",
|
||||||
"connect_caldav": "CalDav Serverに接続",
|
"connect_caldav": "CalDav (Beta)に接続",
|
||||||
"credentials_stored_and_encrypted": "認証情報は保存され暗号化されます。",
|
"credentials_stored_and_encrypted": "認証情報は保存され暗号化されます。",
|
||||||
"connect": "接続",
|
"connect": "接続",
|
||||||
"try_for_free": "無料で試す",
|
"try_for_free": "無料で試す",
|
||||||
@@ -240,6 +243,7 @@
|
|||||||
"when": "いつ",
|
"when": "いつ",
|
||||||
"where": "どこで",
|
"where": "どこで",
|
||||||
"add_to_calendar": "カレンダーに追加",
|
"add_to_calendar": "カレンダーに追加",
|
||||||
|
"add_another_calendar": "別のカレンダーを追加",
|
||||||
"other": "その他",
|
"other": "その他",
|
||||||
"emailed_you_and_attendees": "あなたと他の出席者にすべての詳細を記載したカレンダーの招待状を電子メールで送信しました。",
|
"emailed_you_and_attendees": "あなたと他の出席者にすべての詳細を記載したカレンダーの招待状を電子メールで送信しました。",
|
||||||
"emailed_you_and_attendees_recurring": "あなたと他の出席者にこの繰り返しイベント初回のカレンダーの招待状を電子メールで送信しました。",
|
"emailed_you_and_attendees_recurring": "あなたと他の出席者にこの繰り返しイベント初回のカレンダーの招待状を電子メールで送信しました。",
|
||||||
@@ -261,6 +265,8 @@
|
|||||||
"enter_new_password": "アカウントに使う新しいパスワードを入力してください",
|
"enter_new_password": "アカウントに使う新しいパスワードを入力してください",
|
||||||
"reset_password": "パスワードのリセット",
|
"reset_password": "パスワードのリセット",
|
||||||
"change_your_password": "パスワードの変更",
|
"change_your_password": "パスワードの変更",
|
||||||
|
"show_password": "パスワードを表示",
|
||||||
|
"hide_password": "パスワードを隠す",
|
||||||
"try_again": "もう一度試す",
|
"try_again": "もう一度試す",
|
||||||
"request_is_expired": "そのリクエストは期限が切れています。",
|
"request_is_expired": "そのリクエストは期限が切れています。",
|
||||||
"reset_instructions": "あなたのアカウントに関連付けられているメールアドレスを入力すると、パスワードをリセットするためのリンクが送信されます。",
|
"reset_instructions": "あなたのアカウントに関連付けられているメールアドレスを入力すると、パスワードをリセットするためのリンクが送信されます。",
|
||||||
@@ -306,6 +312,7 @@
|
|||||||
"recurring_bookings": "別のユーザーがあなたとの繰り返しイベントを予約すると、ここに表示されます。",
|
"recurring_bookings": "別のユーザーがあなたとの繰り返しイベントを予約すると、ここに表示されます。",
|
||||||
"past_bookings": "過去の予約はここに表示されます。",
|
"past_bookings": "過去の予約はここに表示されます。",
|
||||||
"cancelled_bookings": "キャンセルされた予約はここに表示されます。",
|
"cancelled_bookings": "キャンセルされた予約はここに表示されます。",
|
||||||
|
"unconfirmed_bookings": "未確認の予約はここに表示されます。",
|
||||||
"on": "上",
|
"on": "上",
|
||||||
"and": "と",
|
"and": "と",
|
||||||
"calendar_shows_busy_between": "カレンダーは、次の間で忙しいことを示します:",
|
"calendar_shows_busy_between": "カレンダーは、次の間で忙しいことを示します:",
|
||||||
@@ -346,6 +353,7 @@
|
|||||||
"booking_cancelled": "予約がキャンセルされました",
|
"booking_cancelled": "予約がキャンセルされました",
|
||||||
"booking_rescheduled": "予約の再スケジュール済",
|
"booking_rescheduled": "予約の再スケジュール済",
|
||||||
"booking_created": "予約を作成しました",
|
"booking_created": "予約を作成しました",
|
||||||
|
"meeting_ended": "ミーティングが終了しました",
|
||||||
"form_submitted": "フォームが送信されました",
|
"form_submitted": "フォームが送信されました",
|
||||||
"event_triggers": "イベントトリガー",
|
"event_triggers": "イベントトリガー",
|
||||||
"subscriber_url": "購読者の URL",
|
"subscriber_url": "購読者の URL",
|
||||||
@@ -488,6 +496,9 @@
|
|||||||
"lets_create_first_administrator_user": "最初の管理者ユーザーを作成しましょう。",
|
"lets_create_first_administrator_user": "最初の管理者ユーザーを作成しましょう。",
|
||||||
"new_member": "新しいメンバー",
|
"new_member": "新しいメンバー",
|
||||||
"invite": "招待する",
|
"invite": "招待する",
|
||||||
|
"add_team_members": "チームメンバーを追加",
|
||||||
|
"add_team_members_description": "他の人をチームに参加するよう招待する",
|
||||||
|
"add_team_member": "チームメンバーを追加",
|
||||||
"invite_new_member": "新しいメンバーを招待する",
|
"invite_new_member": "新しいメンバーを招待する",
|
||||||
"invite_new_team_member": "チームに誰かを招待する。",
|
"invite_new_team_member": "チームに誰かを招待する。",
|
||||||
"change_member_role": "チームメンバーの役割を変更する",
|
"change_member_role": "チームメンバーの役割を変更する",
|
||||||
@@ -600,6 +611,7 @@
|
|||||||
"create_first_team_and_invite_others": "あなたの最初のチームを作成し、あなたと一緒に仕事をするために他のユーザーを招待してください。",
|
"create_first_team_and_invite_others": "あなたの最初のチームを作成し、あなたと一緒に仕事をするために他のユーザーを招待してください。",
|
||||||
"create_team_to_get_started": "始めるためにチームを作成",
|
"create_team_to_get_started": "始めるためにチームを作成",
|
||||||
"teams": "チーム",
|
"teams": "チーム",
|
||||||
|
"team": "チーム",
|
||||||
"team_billing": "チームの請求",
|
"team_billing": "チームの請求",
|
||||||
"upgrade_to_flexible_pro_title": "チームへの請求内容を変更しました",
|
"upgrade_to_flexible_pro_title": "チームへの請求内容を変更しました",
|
||||||
"upgrade_to_flexible_pro_message": "あなたのチームには座席がないメンバーがいます。Pro プランへとアップグレードし、不足している座席を確保してください。",
|
"upgrade_to_flexible_pro_message": "あなたのチームには座席がないメンバーがいます。Pro プランへとアップグレードし、不足している座席を確保してください。",
|
||||||
@@ -620,7 +632,9 @@
|
|||||||
"billing": "請求",
|
"billing": "請求",
|
||||||
"manage_your_billing_info": "請求情報の管理とサブスクリプションのキャンセル。",
|
"manage_your_billing_info": "請求情報の管理とサブスクリプションのキャンセル。",
|
||||||
"availability": "利用可能期間",
|
"availability": "利用可能期間",
|
||||||
|
"edit_availability": "予定を編集",
|
||||||
"configure_availability": "予約が可能な時間を設定する。",
|
"configure_availability": "予約が可能な時間を設定する。",
|
||||||
|
"copy_times_to": "次に時間をコピー",
|
||||||
"change_weekly_schedule": "ウィークリースケジュールを変更する",
|
"change_weekly_schedule": "ウィークリースケジュールを変更する",
|
||||||
"logo": "ロゴ",
|
"logo": "ロゴ",
|
||||||
"error": "エラー",
|
"error": "エラー",
|
||||||
@@ -635,6 +649,7 @@
|
|||||||
"event_name_tooltip": "カレンダーに表示される名前",
|
"event_name_tooltip": "カレンダーに表示される名前",
|
||||||
"meeting_with_user": "{ATTENDEE} とのミーティング",
|
"meeting_with_user": "{ATTENDEE} とのミーティング",
|
||||||
"additional_inputs": "追加入力",
|
"additional_inputs": "追加入力",
|
||||||
|
"additional_input_description": "予約確認前にスケジュール設定者の追加入力が必要です",
|
||||||
"label": "ラベル",
|
"label": "ラベル",
|
||||||
"placeholder": "プレースホルダー",
|
"placeholder": "プレースホルダー",
|
||||||
"type": "タイプ",
|
"type": "タイプ",
|
||||||
@@ -649,6 +664,8 @@
|
|||||||
"disable_guests": "ゲストを無効化",
|
"disable_guests": "ゲストを無効化",
|
||||||
"disable_guests_description": "予約中のゲストの追加を無効にします。",
|
"disable_guests_description": "予約中のゲストの追加を無効にします。",
|
||||||
"private_link": "プライベートリンクを生成",
|
"private_link": "プライベートリンクを生成",
|
||||||
|
"private_link_label": "プライベートリンク",
|
||||||
|
"private_link_hint": "プライベートリンクは使用するたびに再生成されます",
|
||||||
"copy_private_link": "プライベートリンクをコピー",
|
"copy_private_link": "プライベートリンクをコピー",
|
||||||
"private_link_description": "Cal ユーザー名を公開せずに共有するプライベートURLを生成",
|
"private_link_description": "Cal ユーザー名を公開せずに共有するプライベートURLを生成",
|
||||||
"invitees_can_schedule": "招待されるメンバーはスケジュールできる",
|
"invitees_can_schedule": "招待されるメンバーはスケジュールできる",
|
||||||
@@ -679,7 +696,7 @@
|
|||||||
"add_new_event_type": "新しいイベントタイプを追加する",
|
"add_new_event_type": "新しいイベントタイプを追加する",
|
||||||
"new_event_type_to_book_description": "ユーザーが時間を予約する際に使う新しいイベントタイプを作成する。",
|
"new_event_type_to_book_description": "ユーザーが時間を予約する際に使う新しいイベントタイプを作成する。",
|
||||||
"length": "長さ",
|
"length": "長さ",
|
||||||
"minimum_booking_notice": "最低限の通知",
|
"minimum_booking_notice": "最低頻度の通知",
|
||||||
"slot_interval": "時間帯の間隔",
|
"slot_interval": "時間帯の間隔",
|
||||||
"slot_interval_default": "イベントの長さを使用する (デフォルト)",
|
"slot_interval_default": "イベントの長さを使用する (デフォルト)",
|
||||||
"delete_event_type_description": "このイベントタイプを削除してもよろしいですか? あなたがこのリンクを共有した人は、それを使って予約することができなくなります。",
|
"delete_event_type_description": "このイベントタイプを削除してもよろしいですか? あなたがこのリンクを共有した人は、それを使って予約することができなくなります。",
|
||||||
@@ -690,16 +707,21 @@
|
|||||||
"delete_account_confirmation_message": "あなたの Cal.com アカウントを本当に削除してもよろしいですか?あなたのアカウントリンクを共有しているユーザーは、そのアカウントを使用して予約を行うことができなくなり、保存していた設定も失われます。",
|
"delete_account_confirmation_message": "あなたの Cal.com アカウントを本当に削除してもよろしいですか?あなたのアカウントリンクを共有しているユーザーは、そのアカウントを使用して予約を行うことができなくなり、保存していた設定も失われます。",
|
||||||
"integrations": "連携",
|
"integrations": "連携",
|
||||||
"apps": "アプリ",
|
"apps": "アプリ",
|
||||||
|
"category_apps": "{{category}} アプリ",
|
||||||
"app_store": "App Store",
|
"app_store": "App Store",
|
||||||
"app_store_description": "人とテクノロジーと職場をつなぐ。",
|
"app_store_description": "人とテクノロジーと職場をつなぐ。",
|
||||||
"settings": "設定",
|
"settings": "設定",
|
||||||
"event_type_moved_successfully": "イベントの種類が正常に移動されました",
|
"event_type_moved_successfully": "イベントの種類が正常に移動されました",
|
||||||
|
"next_step_text": "次のステップ",
|
||||||
"next_step": "手順をスキップ",
|
"next_step": "手順をスキップ",
|
||||||
"prev_step": "前の手順",
|
"prev_step": "前の手順",
|
||||||
|
"install": "インストール",
|
||||||
"installed": "インストール済み",
|
"installed": "インストール済み",
|
||||||
"active_install_one": "{{count}} 件のアクティブなインストール",
|
"active_install_one": "{{count}} 件のアクティブなインストール",
|
||||||
"active_install_other": "{{count}} 件のアクティブなインストール",
|
"active_install_other": "{{count}} 件のアクティブなインストール",
|
||||||
"globally_install": "全世界でインストール",
|
"globally_install": "全世界でインストール",
|
||||||
|
"app_successfully_installed": "アプリが正常にインストールされました",
|
||||||
|
"app_could_not_be_installed": "アプリをインストールできませんでした",
|
||||||
"disconnect": "接続を解除",
|
"disconnect": "接続を解除",
|
||||||
"embed_your_calendar": "カレンダーをウェブページに埋め込む",
|
"embed_your_calendar": "カレンダーをウェブページに埋め込む",
|
||||||
"connect_your_favourite_apps": "お気に入りのアプリを接続する",
|
"connect_your_favourite_apps": "お気に入りのアプリを接続する",
|
||||||
@@ -710,6 +732,7 @@
|
|||||||
"connect_additional_calendar": "別のカレンダーを接続する",
|
"connect_additional_calendar": "別のカレンダーを接続する",
|
||||||
"conferencing": "ミーティング中",
|
"conferencing": "ミーティング中",
|
||||||
"calendar": "カレンダー",
|
"calendar": "カレンダー",
|
||||||
|
"payments": "お支払い",
|
||||||
"not_installed": "インストールされていません",
|
"not_installed": "インストールされていません",
|
||||||
"error_password_mismatch": "パスワードが一致しません。",
|
"error_password_mismatch": "パスワードが一致しません。",
|
||||||
"error_required_field": "このフィールドは必須です。",
|
"error_required_field": "このフィールドは必須です。",
|
||||||
@@ -743,9 +766,22 @@
|
|||||||
"import_from": "インポート元",
|
"import_from": "インポート元",
|
||||||
"access_token": "アクセストークン",
|
"access_token": "アクセストークン",
|
||||||
"visit_roadmap": "ロードマップ",
|
"visit_roadmap": "ロードマップ",
|
||||||
|
"featured_categories": "注目のカテゴリー",
|
||||||
"popular_categories": "人気のカテゴリー",
|
"popular_categories": "人気のカテゴリー",
|
||||||
|
"number_apps_one": "{{count}} 個のアプリ",
|
||||||
|
"number_apps_other": "{{count}} 個のアプリ",
|
||||||
"trending_apps": "人気のアプリ",
|
"trending_apps": "人気のアプリ",
|
||||||
|
"explore_apps": "{{category}} アプリ",
|
||||||
"installed_apps": "インストールされているアプリ",
|
"installed_apps": "インストールされているアプリ",
|
||||||
|
"no_category_apps": "{{category}} アプリはありません",
|
||||||
|
"no_category_apps_description_calendar": "ダブルブッキングを防ぐために、スケジュールの重なりをチェックするカレンダーアプリを追加します",
|
||||||
|
"no_category_apps_description_conferencing": "会議アプリを追加して、顧客とのビデオ通話を統合してみます",
|
||||||
|
"no_category_apps_description_payment": "決済アプリを追加して、顧客との取引を容易にします",
|
||||||
|
"no_category_apps_description_other": "他の種類のアプリを追加して、いろいろなことができるようにします",
|
||||||
|
"installed_app_calendar_description": "ダブルブッキングを防ぐために、スケジュールの重なりをチェックするようカレンダーを設定します",
|
||||||
|
"installed_app_conferencing_description": "会議用にお気に入りのビデオ会議アプリを追加します",
|
||||||
|
"installed_app_payment_description": "顧客に請求をする際に使用する決済処理サービスを設定します。",
|
||||||
|
"installed_app_other_description": "他のカテゴリーからインストールしたすべてのアプリ。",
|
||||||
"empty_installed_apps_headline": "アプリがインストールされていません",
|
"empty_installed_apps_headline": "アプリがインストールされていません",
|
||||||
"empty_installed_apps_description": "アプリを使えば、ワークフローの質を高め、スケジュールライフを大幅に改善することができます。",
|
"empty_installed_apps_description": "アプリを使えば、ワークフローの質を高め、スケジュールライフを大幅に改善することができます。",
|
||||||
"empty_installed_apps_button": "App Storeで探す",
|
"empty_installed_apps_button": "App Storeで探す",
|
||||||
@@ -766,6 +802,7 @@
|
|||||||
"remove": "削除する",
|
"remove": "削除する",
|
||||||
"add": "追加する",
|
"add": "追加する",
|
||||||
"installed_one": "インストール済み",
|
"installed_one": "インストール済み",
|
||||||
|
"installed_other": "{{count}} 回インストールされました",
|
||||||
"verify_wallet": "ウォレットを確認する",
|
"verify_wallet": "ウォレットを確認する",
|
||||||
"connect_metamask": "メタマスクを接続する",
|
"connect_metamask": "メタマスクを接続する",
|
||||||
"create_events_on": "以下にイベントを作成する:",
|
"create_events_on": "以下にイベントを作成する:",
|
||||||
@@ -783,6 +820,8 @@
|
|||||||
"set_to_default": "デフォルトに設定",
|
"set_to_default": "デフォルトに設定",
|
||||||
"new_schedule_btn": "新しいスケジュール",
|
"new_schedule_btn": "新しいスケジュール",
|
||||||
"add_new_schedule": "新しいスケジュールを追加",
|
"add_new_schedule": "新しいスケジュールを追加",
|
||||||
|
"add_new_calendar": "新しいカレンダーを追加",
|
||||||
|
"set_calendar": "予約時に新しいイベントを追加する場所を設定します。",
|
||||||
"delete_schedule": "スケジュールを削除",
|
"delete_schedule": "スケジュールを削除",
|
||||||
"schedule_created_successfully": "{{scheduleName}} のスケジュールが正常に作成されました",
|
"schedule_created_successfully": "{{scheduleName}} のスケジュールが正常に作成されました",
|
||||||
"availability_updated_successfully": "利用可否の更新に成功しました",
|
"availability_updated_successfully": "利用可否の更新に成功しました",
|
||||||
@@ -798,7 +837,6 @@
|
|||||||
"redirect_success_booking": "予約時にリダイレクト",
|
"redirect_success_booking": "予約時にリダイレクト",
|
||||||
"you_are_being_redirected": "$t(second, {\"count\": {{seconds}} }) で {{ url }} にリダイレクトします",
|
"you_are_being_redirected": "$t(second, {\"count\": {{seconds}} }) で {{ url }} にリダイレクトします",
|
||||||
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
"external_redirect_url": "https://example.com/redirect-to-my-success-page",
|
||||||
"redirect_url_upgrade_description": "この機能を利用するには、Pro アカウントへのアップグレードが必要です。",
|
|
||||||
"duplicate": "複製",
|
"duplicate": "複製",
|
||||||
"offer_seats": "座席を提供",
|
"offer_seats": "座席を提供",
|
||||||
"offer_seats_description": "予約に座席を提供 (これはゲストとオプトイン予約を無効化します)",
|
"offer_seats_description": "予約に座席を提供 (これはゲストとオプトイン予約を無効化します)",
|
||||||
@@ -877,7 +915,7 @@
|
|||||||
"choose_ways_put_cal_site": "サイトに Cal を設置する方法を、次の中から 1 つ選んでください。",
|
"choose_ways_put_cal_site": "サイトに Cal を設置する方法を、次の中から 1 つ選んでください。",
|
||||||
"setting_up_zapier": "Zapier 連携の設定",
|
"setting_up_zapier": "Zapier 連携の設定",
|
||||||
"generate_api_key": "API キーを生成",
|
"generate_api_key": "API キーを生成",
|
||||||
"generate_api_key_description": "以下から Cal.com で使用する API キーを生成する",
|
"generate_api_key_description": "以下より Cal.com で使用する API キーを生成する: ",
|
||||||
"your_unique_api_key": "あなた専用の API キー",
|
"your_unique_api_key": "あなた専用の API キー",
|
||||||
"copy_safe_api_key": "この API キーをコピーして安全な場所に保存してください。このキーを紛失した場合は、新しいキーを生成する必要があります。",
|
"copy_safe_api_key": "この API キーをコピーして安全な場所に保存してください。このキーを紛失した場合は、新しいキーを生成する必要があります。",
|
||||||
"zapier_setup_instructions": "<0>Zapier アカウントにログインし、新しい Zap を作成します。</0><1>Cal.com を Trigger アプリとして選択します。Trigger イベントも選択します。</1><2>アカウントを選択し、あなた専用の API キーを入力します。</2><3>トリガーをテストします。</3><4>設定完了!</4>",
|
"zapier_setup_instructions": "<0>Zapier アカウントにログインし、新しい Zap を作成します。</0><1>Cal.com を Trigger アプリとして選択します。Trigger イベントも選択します。</1><2>アカウントを選択し、あなた専用の API キーを入力します。</2><3>トリガーをテストします。</3><4>設定完了!</4>",
|
||||||
@@ -936,6 +974,7 @@
|
|||||||
"workflows": "ワークフロー",
|
"workflows": "ワークフロー",
|
||||||
"new_workflow_btn": "新しいワークフロー",
|
"new_workflow_btn": "新しいワークフロー",
|
||||||
"add_new_workflow": "新しいワークフローを追加",
|
"add_new_workflow": "新しいワークフローを追加",
|
||||||
|
"reschedule_event_trigger": "イベントスケジュールの変更時に",
|
||||||
"trigger": "トリガー",
|
"trigger": "トリガー",
|
||||||
"triggers": "トリガー",
|
"triggers": "トリガー",
|
||||||
"action": "アクション",
|
"action": "アクション",
|
||||||
@@ -963,10 +1002,13 @@
|
|||||||
"change_username_standard_to_premium": "スタンダードからプレミアムユーザー名に変更すると、アップグレードのための精算画面に移動します。",
|
"change_username_standard_to_premium": "スタンダードからプレミアムユーザー名に変更すると、アップグレードのための精算画面に移動します。",
|
||||||
"change_username_premium_to_standard": "プレミアムからスタンダードユーザー名に変更すると、ダウングレードのための精算画面に移動します。",
|
"change_username_premium_to_standard": "プレミアムからスタンダードユーザー名に変更すると、ダウングレードのための精算画面に移動します。",
|
||||||
"go_to_stripe_billing": "請求画面に移動",
|
"go_to_stripe_billing": "請求画面に移動",
|
||||||
|
"stripe_description": "予約の支払いが必要です(1回の取引につき0.5% + 0.10ユーロの手数料)",
|
||||||
"trial_expired": "トライアル期間は終了しました",
|
"trial_expired": "トライアル期間は終了しました",
|
||||||
"remove_app": "アプリを削除",
|
"remove_app": "アプリを削除",
|
||||||
"yes_remove_app": "はい。アプリを削除します",
|
"yes_remove_app": "はい。アプリを削除します",
|
||||||
"are_you_sure_you_want_to_remove_this_app": "このアプリを削除してもよろしいですか?",
|
"are_you_sure_you_want_to_remove_this_app": "このアプリを削除してもよろしいですか?",
|
||||||
|
"app_removed_successfully": "アプリは正常に削除されました",
|
||||||
|
"error_removing_app": "アプリの削除中にエラーが発生しました",
|
||||||
"web_conference": "ウェブ会議",
|
"web_conference": "ウェブ会議",
|
||||||
"number_for_sms_reminders": "電話番号(SMS リマインダー用)",
|
"number_for_sms_reminders": "電話番号(SMS リマインダー用)",
|
||||||
"requires_confirmation": "確認が必要です",
|
"requires_confirmation": "確認が必要です",
|
||||||
@@ -1022,20 +1064,209 @@
|
|||||||
"navigate": "ナビゲート",
|
"navigate": "ナビゲート",
|
||||||
"open": "開く",
|
"open": "開く",
|
||||||
"close": "閉じる",
|
"close": "閉じる",
|
||||||
|
"team_feature_teams": "これはチーム機能です。チームにアップグレードすると、チームの参加可能状況を確認することができます。",
|
||||||
|
"team_feature_workflows": "これはチーム機能です。チームにアップグレードすると、ワークフローを使って、イベントの通知やリマインダーを自動化できます。",
|
||||||
|
"show_eventtype_on_profile": "プロフィールに表示",
|
||||||
"embed": "埋め込む",
|
"embed": "埋め込む",
|
||||||
"new_username": "新しいユーザー名",
|
"new_username": "新しいユーザー名",
|
||||||
"current_username": "現在のユーザー名",
|
"current_username": "現在のユーザー名",
|
||||||
"example_1": "例 1",
|
"example_1": "例 1",
|
||||||
"example_2": "例 2",
|
"example_2": "例 2",
|
||||||
|
"additional_input_label": "追加の入力ラベル",
|
||||||
"company_size": "会社の規模",
|
"company_size": "会社の規模",
|
||||||
"what_help_needed": "何かお困りですか?",
|
"what_help_needed": "何かお困りですか?",
|
||||||
"variable_format": "変数の形式",
|
"variable_format": "変数の形式",
|
||||||
|
"webhook_subscriber_url_reserved": "ウェブフック購読者 URL は既に定義されています",
|
||||||
"custom_input_as_variable_info": "追加の入力ラベルに含まれている特殊文字はすべて無視し (アルファベットと数字のみを使用)、アルファベットをすべて大文字に、そして空白をアンダースコアへと変換します。",
|
"custom_input_as_variable_info": "追加の入力ラベルに含まれている特殊文字はすべて無視し (アルファベットと数字のみを使用)、アルファベットをすべて大文字に、そして空白をアンダースコアへと変換します。",
|
||||||
"using_additional_inputs_as_variables": "追加の入力内容を変数として使用するにはどうすればよいですか?",
|
"using_additional_inputs_as_variables": "追加の入力内容を変数として使用するにはどうすればよいですか?",
|
||||||
"download_desktop_app": "デスクトップアプリをダウンロード",
|
"download_desktop_app": "デスクトップアプリをダウンロード",
|
||||||
"set_ping_link": "Ping リンクを設定",
|
"set_ping_link": "Ping リンクを設定",
|
||||||
|
"rate_limit_exceeded": "試行回数の上限を超えました",
|
||||||
|
"when_something_happens": "何かが起こった場合",
|
||||||
|
"action_is_performed": "アクションが実行されます",
|
||||||
|
"test_action": "テストアクション",
|
||||||
|
"notification_sent": "通知を送信しました",
|
||||||
|
"no_input": "入力なし",
|
||||||
|
"test_workflow_action": "ワークフローアクションをテスト",
|
||||||
|
"send_sms": "SMS を送信",
|
||||||
|
"send_sms_to_number": "{{number}} にSMSを送信してもよろしいですか?",
|
||||||
"missing_connected_calendar": "デフォルトのカレンダーが接続されていません",
|
"missing_connected_calendar": "デフォルトのカレンダーが接続されていません",
|
||||||
|
"connect_your_calendar_and_link": "<1>こちら</1>からカレンダーを接続できます。",
|
||||||
|
"default_calendar_selected": "デフォルトのカレンダー",
|
||||||
|
"hide_from_profile": "プロファイルから隠す",
|
||||||
|
"event_setup_tab_title": "イベント設定",
|
||||||
|
"event_limit_tab_title": "上限",
|
||||||
|
"event_limit_tab_description": "予約できる頻度",
|
||||||
|
"event_advanced_tab_description": "カレンダー設定など...",
|
||||||
|
"event_advanced_tab_title": "詳細設定",
|
||||||
|
"select_which_cal": "予約を追加するカレンダーを選択してください",
|
||||||
|
"custom_event_name": "カスタムイベント名",
|
||||||
|
"custom_event_name_description": "カレンダーのイベントに表示するカスタマイズされたイベント名を作成します",
|
||||||
|
"2fa_required": "二要素認証が必要です",
|
||||||
|
"incorrect_2fa": "不正な二要素認証コード",
|
||||||
|
"which_event_type_apply": "これはどのイベントタイプに適用されますか?",
|
||||||
|
"no_workflows_description": "ワークフローを使用すると通知やリマインダーの送信を簡単に自動化することができ、イベントに関するプロセスを構築することができます。",
|
||||||
|
"create_workflow": "ワークフローを作成",
|
||||||
|
"do_this": "これを実行する",
|
||||||
|
"turn_off": "オフにする",
|
||||||
|
"settings_updated_successfully": "設定が正常に更新されました",
|
||||||
|
"error_updating_settings": "設定の更新中にエラーが発生しました",
|
||||||
|
"personal_cal_url": "私の個人 Cal URL",
|
||||||
|
"bio_hint": "あなたに関する簡潔な説明。これはあなたの個人 URL ページに表示されます。",
|
||||||
|
"delete_account_modal_title": "アカウントを削除する",
|
||||||
|
"confirm_delete_account_modal": "Cal.com アカウントを削除してもよろしいですか?",
|
||||||
|
"delete_my_account": "アカウントを削除する",
|
||||||
|
"start_of_week": "週の始まり",
|
||||||
|
"select_calendars": "ダブルブッキングを防ぐために、スケジュールの重なりをチェックするカレンダーを選択してください。",
|
||||||
|
"check_for_conflicts": "スケジュールの重なりをチェック",
|
||||||
|
"adding_events_to": "イベントの追加先",
|
||||||
|
"follow_system_preferences": "システム環境設定に従う",
|
||||||
|
"custom_brand_colors": "カスタムブランドカラー",
|
||||||
|
"customize_your_brand_colors": "予約ページをあなた独自のブランドカラーでカスタマイズします。",
|
||||||
|
"pro": "Pro",
|
||||||
|
"removes_cal_branding": "Cal 関連のブランディング、すなわち「Powered by Cal」を削除します。",
|
||||||
|
"profile_picture": "プロフィール写真",
|
||||||
|
"upload": "アップロード",
|
||||||
|
"web3": "Web3",
|
||||||
|
"rainbow_token_gated": "このイベントタイプはトークンゲート(トークンを持っている人だけに制限)されています。",
|
||||||
|
"rainbow_connect_wallet_gate": "<1>{{name}}</1>(<3>{{symbol}}</3>)を所有している場合、ウォレットを接続します。",
|
||||||
|
"rainbow_insufficient_balance": "接続されているウォレットには十分な<1>{{symbol}}</1>が含まれていません。",
|
||||||
|
"rainbow_sign_message_request": "ウォレットのメッセージリクエストに署名してください。",
|
||||||
|
"rainbow_signature_error": "ウォレットからの署名リクエスト中にエラーが発生しました。",
|
||||||
|
"token_address": "トークンアドレス",
|
||||||
|
"blockchain": "ブロックチェーン",
|
||||||
|
"old_password": "古いパスワード",
|
||||||
|
"secure_password": "セキュリティ保護された新しいパスワード",
|
||||||
|
"error_updating_password": "パスワードの更新中にエラーが発生しました",
|
||||||
|
"two_factor_auth": "二要素認証",
|
||||||
|
"recurring_event_tab_description": "繰り返しスケジュールを設定",
|
||||||
|
"today": "今日",
|
||||||
|
"appearance": "画面表示",
|
||||||
|
"appearance_subtitle": "予約画面の表示設定を管理します",
|
||||||
|
"my_account": "アカウント",
|
||||||
|
"general": "一般",
|
||||||
|
"calendars": "カレンダー",
|
||||||
|
"2fa_auth": "二要素認証",
|
||||||
|
"invoices": "インボイス",
|
||||||
|
"embeds": "埋め込み",
|
||||||
|
"impersonation": "なりすまし",
|
||||||
|
"users": "ユーザー",
|
||||||
|
"profile_description": "Cal プロフィールの設定を管理します",
|
||||||
|
"general_description": "言語とタイムゾーンの設定を管理します",
|
||||||
|
"calendars_description": "イベントタイプとカレンダーの連携の仕方を設定します",
|
||||||
|
"appearance_description": "予約画面の表示設定を管理します",
|
||||||
|
"conferencing_description": "会議用のビデオ会議アプリを管理します",
|
||||||
|
"password_description": "アカウントパスワードの設定を管理します",
|
||||||
|
"2fa_description": "アカウントパスワードの設定を管理します",
|
||||||
|
"we_just_need_basic_info": "プロフィールを設定するための基本的な情報が必要です。",
|
||||||
|
"skip": "スキップ",
|
||||||
|
"do_this_later": "後で行う",
|
||||||
|
"set_availability_getting_started_subtitle_1": "参加予約可能な時間の範囲を定義します",
|
||||||
|
"set_availability_getting_started_subtitle_2": "これらはすべて後で、参加予約可能状況のページでカスタマイズできます。",
|
||||||
|
"connect_calendars_from_app_store": "アプリストアからさらにカレンダーを追加することができます",
|
||||||
|
"connect_conference_apps": "会議アプリを接続",
|
||||||
|
"connect_calendar_apps": "カレンダーアプリを接続",
|
||||||
|
"connect_payment_apps": "決済アプリを接続",
|
||||||
|
"connect_other_apps": "その他のアプリを接続",
|
||||||
|
"current_step_of_total": "ステップ {{currentStep}} / {{maxSteps}}",
|
||||||
|
"add_variable": "変数を追加",
|
||||||
|
"custom_phone_number": "任意の電話番号",
|
||||||
|
"message_template": "メッセージテンプレート",
|
||||||
|
"email_subject": "メールの件名",
|
||||||
|
"add_dynamic_variables": "ダイナミックテキスト変数を追加",
|
||||||
|
"event_name_info": "イベントタイプ名",
|
||||||
|
"event_date_info": "イベントの日付",
|
||||||
|
"event_time_info": "イベント開始時刻",
|
||||||
|
"location_info": "イベントの場所",
|
||||||
"organizer_name_info": "あなたの名前",
|
"organizer_name_info": "あなたの名前",
|
||||||
|
"additional_notes_info": "予約の追加メモ",
|
||||||
|
"attendee_name_info": "予約者名",
|
||||||
|
"to": "送信先",
|
||||||
|
"attendee_required_enter_number": "この場合、予約時に参加者の電話番号の入力が必要になります",
|
||||||
|
"workflow_turned_on_successfully": "{{workflowName}} ワークフローが正常に {{offOn}} になりました",
|
||||||
|
"download_responses": "回答をダウンロード",
|
||||||
|
"create_your_first_form": "最初のフォームを作成",
|
||||||
|
"create_your_first_form_description": "ルーティングフォームを使用すると、選抜のための質問をし、適切な人やイベントタイプにルーティングすることができます。",
|
||||||
|
"create_your_first_webhook": "最初のウェブフックを作成",
|
||||||
|
"create_your_first_webhook_description": "ウェブフックを使用すると、Cal.com で何かが起こったときにリアルタイムでミーティングデータを受信できます。",
|
||||||
|
"for_a_maximum_of": "最大で",
|
||||||
|
"event_one": "イベント",
|
||||||
|
"event_other": "イベント",
|
||||||
|
"profile_team_description": "チームプロフィールの設定を管理します",
|
||||||
|
"members_team_description": "グループにいるユーザー",
|
||||||
|
"team_url": "チーム URL",
|
||||||
|
"delete_team": "チームを削除",
|
||||||
|
"team_members": "チームメンバー",
|
||||||
|
"more": "詳細",
|
||||||
|
"more_page_footer": "私たちはモバイルアプリケーションを Web アプリケーションの拡張機能として捉えています。複雑な操作を行う場合は、 Web アプリケーションを参照してください。",
|
||||||
|
"workflow_example_1": "イベント開始24時間前に、出席者に SMS リマインダーを送信する",
|
||||||
|
"workflow_example_2": "イベントスケジュールの変更時に、出席者にカスタム SMS を送信する",
|
||||||
|
"workflow_example_3": "新しいイベントの予約時に、ホストにカスタムメールを送信する",
|
||||||
|
"workflow_example_4": "イベント開始1時間前に、出席者にメールリマインダーを送信する",
|
||||||
|
"workflow_example_5": "イベントスケジュールの変更時に、ホストにカスタムメールを送信する",
|
||||||
|
"workflow_example_6": "新しいイベントの予約時に、ホストにカスタム SMS を送信する",
|
||||||
|
"welcome_to_cal_header": "Cal.com へようこそ!",
|
||||||
|
"edit_form_later_subtitle": "これは後で編集することができます。",
|
||||||
|
"connect_calendar_later": "後でカレンダーを接続する",
|
||||||
|
"set_my_availability_later": "参加予約可能状況は後で設定する",
|
||||||
|
"problem_saving_user_profile": "データの保存中に問題が発生しました。もう一度試すか、カスタマーサポートにご連絡ください。",
|
||||||
|
"purchase_missing_seats": "不足分の座席を購入",
|
||||||
|
"slot_length": "時間帯の長さ",
|
||||||
|
"booking_appearance": "予約画面の表示",
|
||||||
|
"appearance_team_description": "チームの予約画面の表示設定を管理します",
|
||||||
|
"only_owner_change": "このチームの所有者のみがチームの予約を変更できます ",
|
||||||
|
"team_disable_cal_branding_description": "Cal 関連のブランディング、すなわち「Powered by Cal」を削除します",
|
||||||
|
"invited_by_team": "{{teamName}} から {{role}} としてチームに参加するよう招待されました",
|
||||||
|
"token_invalid_expired": "トークンが無効または期限切れです。",
|
||||||
|
"exchange_add": "Microsoft Exchange に接続",
|
||||||
|
"exchange_authentication": "認証方法",
|
||||||
|
"exchange_authentication_standard": "基本認証",
|
||||||
|
"exchange_authentication_ntlm": "NTLM 認証",
|
||||||
|
"exchange_compression": "GZip 圧縮",
|
||||||
|
"routing_forms_description": "作成したすべてのフォームとルートをここで確認できます。",
|
||||||
|
"add_new_form": "新しいフォームを追加",
|
||||||
|
"form_description": "予約者をルーティングするフォームを作成します",
|
||||||
|
"copy_link_to_form": "フォームのリンクをコピー",
|
||||||
|
"theme": "テーマ",
|
||||||
|
"theme_applies_note": "公開予約ページにのみ適用されます",
|
||||||
"theme_light": "明るさ",
|
"theme_light": "明るさ",
|
||||||
"theme_dark": "暗め"
|
"theme_dark": "暗め",
|
||||||
|
"theme_system": "システムのデフォルト",
|
||||||
|
"add_a_team": "チームを追加",
|
||||||
|
"saml_config": "SAML 設定",
|
||||||
|
"add_webhook_description": "Cal.com で何かが起こったときにリアルタイムでミーティングデータを受信します",
|
||||||
|
"triggers_when": "次の場合にトリガー",
|
||||||
|
"test_webhook": "作成前に Ping テストを実行してください。",
|
||||||
|
"enable_webhook": "ウェブフックを有効にする",
|
||||||
|
"add_webhook": "ウェブフックを追加",
|
||||||
|
"webhook_edited_successfully": "ウェブフックを保存しました",
|
||||||
|
"webhooks_description": "Cal.com で何かが起こったときにリアルタイムでミーティングデータを受信します",
|
||||||
|
"api_keys_description": "自分のアカウントにアクセスするための API キーを生成します",
|
||||||
|
"new_api_key": "新しい API キー",
|
||||||
|
"active": "有効",
|
||||||
|
"api_key_updated": "API キーの名前が更新されました",
|
||||||
|
"api_key_update_failed": "API キーの名前を更新中にエラーが発生しました",
|
||||||
|
"embeds_title": "HTML iframe の埋め込み",
|
||||||
|
"embeds_description": "すべてのイベントタイプをウェブサイトに埋め込みます",
|
||||||
|
"create_first_api_key": "最初の API キーを作成",
|
||||||
|
"create_first_api_key_description": "API キーを使用することにより、他のアプリが Cal.com と情報をやりとりできるようになります",
|
||||||
|
"back_to_signin": "ログインに戻る",
|
||||||
|
"reset_link_sent": "リセットリンクが送信されました",
|
||||||
|
"password_reset_email": "パスワードのリセット方法を記載したメールを {{email}} 宛に送信しました。",
|
||||||
|
"password_updated": "パスワードが更新されました!",
|
||||||
|
"pending_payment": "支払い待ち",
|
||||||
|
"confirmation_page_rainbow": "イーサリアムや Polygon(ポリゴン) などのトークンや NFT を使ってイベントをトークンゲートします。",
|
||||||
|
"not_on_cal": "Cal.com ではしない",
|
||||||
|
"no_calendar_installed": "カレンダーがインストールされていません",
|
||||||
|
"no_calendar_installed_description": "まだカレンダーを接続していません",
|
||||||
|
"add_a_calendar": "カレンダーを追加",
|
||||||
|
"change_email_hint": "変更内容を有効にするには、一度ログアウトしてから再度ログインを行う必要がある場合があります",
|
||||||
|
"confirm_password_change_email": "メールアドレスを変更する前にパスワードを確認してください",
|
||||||
|
"seats": "座席",
|
||||||
|
"every_app_published": "Cal.com アプリストアで公開されているアプリはいずれもオープンソースであり、ピアレビューを通じて徹底的にテストされています。しかしながら Cal.com, Inc は、Cal.com によって公開されたものでない限り、これらのアプリを推奨または認証していません。不適切なコンテンツや動作に遭遇した場合は、ご報告ください。",
|
||||||
|
"report_app": "アプリを報告",
|
||||||
|
"billing_manage_details_title": "請求情報の詳細を表示・管理する",
|
||||||
|
"billing_manage_details_description": "請求情報の詳細を表示・編集、およびサブスクリプションをキャンセルする。",
|
||||||
|
"billing_help_title": "他に必要なものはありませんか?",
|
||||||
|
"billing_help_description": "請求に関するサポートが必要な場合は、サポートチームがお手伝いします。"
|
||||||
}
|
}
|
||||||
Loaded 100 of 315 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user