<commit_before>import { MouseEvent, useState } from 'react';

import { c, msgid } from 'ttag';

import {
    AlertModal,
    Button,
    Checkbox,
    DropdownMenuLink,
    FeatureCode,
    Icon,
    SettingsLink,
    SidebarListItem,
    SidebarListItemContent,
    SidebarListItemDiv,
    SimpleDropdown,
    Tooltip,
    classnames,
    useApi,
    useFeature,
    useLoading,
    useModalState,
    useNotifications,
    useSettingsLink,
    useUser,
} from '@proton/components';
import DropdownMenu from '@proton/components/components/dropdown/DropdownMenu';
import DropdownMenuButton from '@proton/components/components/dropdown/DropdownMenuButton';
import { CalendarModal } from '@proton/components/containers/calendar/calendarModal/CalendarModal';
import { ImportModal } from '@proton/components/containers/calendar/importModal';
import ShareCalendarModal from '@proton/components/containers/calendar/shareModal/ShareCalendarModal';
import ShareLinkModal from '@proton/components/containers/calendar/shareURL/ShareLinkModal';
import ShareLinkSuccessModal from '@proton/components/containers/calendar/shareURL/ShareLinkSuccessModal';
import { useModalsMap } from '@proton/components/hooks/useModalsMap';
import { getAllMembers, getCalendarInvitations, getPublicLinks } from '@proton/shared/lib/api/calendars';
import { getIsCalendarDisabled, getIsOwnedCalendar, getIsPersonalCalendar } from '@proton/shared/lib/calendar/calendar';
import {
    CALENDAR_SETTINGS_SUBSECTION_ID,
    COLORS,
    MAX_CALENDAR_MEMBERS,
    MAX_LINKS_PER_CALENDAR,
} from '@proton/shared/lib/calendar/constants';
import { MEMBER_PERMISSIONS } from '@proton/shared/lib/calendar/permissions';
import {
    getCalendarHasSubscriptionParameters,
    getCalendarIsNotSyncedInfo,
} from '@proton/shared/lib/calendar/subscribe/helpers';
import { APPS } from '@proton/shared/lib/constants';
import { textToClipboard } from '@proton/shared/lib/helpers/browser';
import { Address, Nullable } from '@proton/shared/lib/interfaces';
import { ModalWithProps } from '@proton/shared/lib/interfaces/Modal';
import {
    ACCESS_LEVEL,
    CalendarMember,
    CalendarMemberInvitation,
    CalendarUrlsResponse,
    GetAllInvitationsApiResponse,
    GetAllMembersApiResponse,
    MEMBER_INVITATION_STATUS,
    SubscribedCalendar,
    VisualCalendar,
} from '@proton/shared/lib/interfaces/calendar';
import noop from '@proton/utils/noop';

import CalendarSidebarShareCalendarModal from './CalendarSidebarShareCalendarModal';

type ModalsMap = {
    shareLinkSuccessModal: ModalWithProps<{
        onSubmit: (e: MouseEvent<HTMLButtonElement>) => void;
        accessLevel: ACCESS_LEVEL;
        link: string;
    }>;
    shareLinkModal: ModalWithProps<{
        calendarID: string;
        calendarName: string;
        onSubmit: ({ link, accessLevel }: { link: string; accessLevel: ACCESS_LEVEL }) => Promise<void>;
    }>;
    limitModal: ModalWithProps<{
        title: string;
        body: string;
        onClick: () => void;
        buttonText: string;
    }>;
};

export interface CalendarSidebarListItemsProps {
    calendars?: VisualCalendar[] | SubscribedCalendar[];
    loading?: boolean;
    onChangeVisibility: (id: string, checked: boolean) => void;
    actionsDisabled?: boolean;
    addresses: Address[];
}

const CalendarSidebarListItems = ({
    calendars = [],
    loading = false,
    onChangeVisibility = noop,
    actionsDisabled = false,
    addresses,
}: CalendarSidebarListItemsProps) => {
    const [user] = useUser();
    const api = useApi();
    const { createNotification } = useNotifications();
    const goToSettings = useSettingsLink();

    const isCalendarSharingEnabled = !!useFeature(FeatureCode.CalendarSharingEnabled).feature?.Value;

    const [loadingFetchMemberAndInvitations, withLoadingFetchMemberAndInvitations] = useLoading();
    const [loadingLinks, withLoadingLinks] = useLoading();

    const [importModalCalendar, setImportModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [calendarModalCalendar, setCalendarModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [isSharePrivatelyModalOpen, setIsSharePrivatelyModalOpen] = useState(false);

    const [shareModalCalendar, setShareModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [{ open: isShareModalOpen, ...shareModalProps }, setIsShareModalOpen] = useModalState();
    const [invitations, setInvitations] = useState<CalendarMemberInvitation[]>([]);
    const [members, setMembers] = useState<CalendarMember[]>([]);

    const [{ onExit: onExitCalendarModal, ...calendarModalProps }, setIsCalendarModalOpen] = useModalState();

    const [
        { open: isImportModalOpen, onClose: onCloseImportModal, onExit: onExitImportModal, ...importModalProps },
        setIsImportModalOpen,
    ] = useModalState();

    const { modalsMap, closeModal, updateModal } = useModalsMap<ModalsMap>({
        shareLinkSuccessModal: { isOpen: false },
        shareLinkModal: { isOpen: false },
        limitModal: { isOpen: false },
    });

    if (calendars.length === 0) {
        return null;
    }

    const isPersonalCalendar = getIsPersonalCalendar(calendars[0]);

    const result = calendars.map((calendar, i) => {
        const { ID, Name, Display, Color } = calendar;
        const isCalendarDisabled = getIsCalendarDisabled(calendar);

        const left = (
            <Checkbox
                className="mr0-75 flex-item-noshrink"
                color={COLORS.WHITE}
                backgroundColor={Display ? Color : 'transparent'}
                borderColor={Color}
                checked={!!Display}
                disabled={loading}
                aria-describedby={`calendar-${i}`}
                onChange={({ target: { checked } }) => onChangeVisibility(ID, checked)}
            />
        );

        const isNotSyncedInfo = getCalendarHasSubscriptionParameters(calendar)
            ? getCalendarIsNotSyncedInfo(calendar)
            : undefined;

        return (
            <SidebarListItem key={ID}>
                <SidebarListItemDiv className="calendar-sidebar-list-item opacity-on-hover-container pt0-5 pb0-5 pr0-5">
                    <SidebarListItemContent
                        data-test-id="calendar-sidebar:user-calendars"
                        left={left}
                        className={classnames(['flex', (isCalendarDisabled || isNotSyncedInfo) && 'color-weak'])}
                    >
                        <div className="flex flex-nowrap flex-justify-space-between flex-align-items-center w100">
                            <div className="flex flex-nowrap mr0-5">
                                <div className="text-ellipsis" title={Name}>
                                    {Name}
                                </div>
                                {!isCalendarDisabled && isNotSyncedInfo && (
                                    <div className="flex-item-noshrink">
                                        &nbsp;
                                        <Tooltip title={isNotSyncedInfo.text}>
                                            <span>({isNotSyncedInfo.label})</span>
                                        </Tooltip>
                                    </div>
                                )}
                                {isCalendarDisabled && (
                                    <div className="flex-item-noshrink">
                                        &nbsp;({c('Disabled calendar name suffix').t`Disabled`})
                                    </div>
                                )}
                            </div>

                            <Tooltip title={c('Sidebar calendar edit tooltip').t`Manage calendar`}>
                                <SimpleDropdown
                                    as={Button}
                                    icon
                                    hasCaret={false}
                                    shape="ghost"
                                    size="small"
                                    className="calendar-sidebar-list-item-action opacity-on-hover flex-item-noshrink no-mobile"
                                    loading={actionsDisabled}
                                    content={<Icon name="three-dots-horizontal" />}
                                >
                                    <DropdownMenu>
                                        {getIsOwnedCalendar(calendar) && (
                                            <>
                                                <DropdownMenuButton
                                                    className="text-left"
                                                    onClick={() => {
                                                        setCalendarModalCalendar(calendar);
                                                        setIsCalendarModalOpen(true);
                                                    }}
                                                ><commit_msg>Add icon for shared calendars in calendar sidebar<commit_after>import { MouseEvent, useState } from 'react';

import { c, msgid } from 'ttag';

import {
    AlertModal,
    Button,
    Checkbox,
    DropdownMenuLink,
    FeatureCode,
    Icon,
    SettingsLink,
    SidebarListItem,
    SidebarListItemContent,
    SidebarListItemDiv,
    SimpleDropdown,
    Tooltip,
    classnames,
    useApi,
    useFeature,
    useLoading,
    useModalState,
    useNotifications,
    useSettingsLink,
    useUser,
} from '@proton/components';
import DropdownMenu from '@proton/components/components/dropdown/DropdownMenu';
import DropdownMenuButton from '@proton/components/components/dropdown/DropdownMenuButton';
import { CalendarModal } from '@proton/components/containers/calendar/calendarModal/CalendarModal';
import { ImportModal } from '@proton/components/containers/calendar/importModal';
import ShareCalendarModal from '@proton/components/containers/calendar/shareModal/ShareCalendarModal';
import ShareLinkModal from '@proton/components/containers/calendar/shareURL/ShareLinkModal';
import ShareLinkSuccessModal from '@proton/components/containers/calendar/shareURL/ShareLinkSuccessModal';
import { useModalsMap } from '@proton/components/hooks/useModalsMap';
import { getAllMembers, getCalendarInvitations, getPublicLinks } from '@proton/shared/lib/api/calendars';
import { getIsCalendarDisabled, getIsOwnedCalendar, getIsPersonalCalendar } from '@proton/shared/lib/calendar/calendar';
import {
    CALENDAR_SETTINGS_SUBSECTION_ID,
    COLORS,
    MAX_CALENDAR_MEMBERS,
    MAX_LINKS_PER_CALENDAR,
} from '@proton/shared/lib/calendar/constants';
import { MEMBER_PERMISSIONS } from '@proton/shared/lib/calendar/permissions';
import {
    getCalendarHasSubscriptionParameters,
    getCalendarIsNotSyncedInfo,
} from '@proton/shared/lib/calendar/subscribe/helpers';
import { APPS } from '@proton/shared/lib/constants';
import { textToClipboard } from '@proton/shared/lib/helpers/browser';
import { Address, Nullable } from '@proton/shared/lib/interfaces';
import { ModalWithProps } from '@proton/shared/lib/interfaces/Modal';
import {
    ACCESS_LEVEL,
    CalendarMember,
    CalendarMemberInvitation,
    CalendarUrlsResponse,
    GetAllInvitationsApiResponse,
    GetAllMembersApiResponse,
    MEMBER_INVITATION_STATUS,
    SubscribedCalendar,
    VisualCalendar,
} from '@proton/shared/lib/interfaces/calendar';
import noop from '@proton/utils/noop';

import CalendarSidebarShareCalendarModal from './CalendarSidebarShareCalendarModal';

type ModalsMap = {
    shareLinkSuccessModal: ModalWithProps<{
        onSubmit: (e: MouseEvent<HTMLButtonElement>) => void;
        accessLevel: ACCESS_LEVEL;
        link: string;
    }>;
    shareLinkModal: ModalWithProps<{
        calendarID: string;
        calendarName: string;
        onSubmit: ({ link, accessLevel }: { link: string; accessLevel: ACCESS_LEVEL }) => Promise<void>;
    }>;
    limitModal: ModalWithProps<{
        title: string;
        body: string;
        onClick: () => void;
        buttonText: string;
    }>;
};

export interface CalendarSidebarListItemsProps {
    calendars?: VisualCalendar[] | SubscribedCalendar[];
    loading?: boolean;
    onChangeVisibility: (id: string, checked: boolean) => void;
    actionsDisabled?: boolean;
    addresses: Address[];
}

const CalendarSidebarListItems = ({
    calendars = [],
    loading = false,
    onChangeVisibility = noop,
    actionsDisabled = false,
    addresses,
}: CalendarSidebarListItemsProps) => {
    const [user] = useUser();
    const api = useApi();
    const { createNotification } = useNotifications();
    const goToSettings = useSettingsLink();

    const isCalendarSharingEnabled = !!useFeature(FeatureCode.CalendarSharingEnabled).feature?.Value;

    const [loadingFetchMemberAndInvitations, withLoadingFetchMemberAndInvitations] = useLoading();
    const [loadingLinks, withLoadingLinks] = useLoading();

    const [importModalCalendar, setImportModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [calendarModalCalendar, setCalendarModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [isSharePrivatelyModalOpen, setIsSharePrivatelyModalOpen] = useState(false);

    const [shareModalCalendar, setShareModalCalendar] = useState<Nullable<VisualCalendar>>(null);
    const [{ open: isShareModalOpen, ...shareModalProps }, setIsShareModalOpen] = useModalState();
    const [invitations, setInvitations] = useState<CalendarMemberInvitation[]>([]);
    const [members, setMembers] = useState<CalendarMember[]>([]);

    const [{ onExit: onExitCalendarModal, ...calendarModalProps }, setIsCalendarModalOpen] = useModalState();

    const [
        { open: isImportModalOpen, onClose: onCloseImportModal, onExit: onExitImportModal, ...importModalProps },
        setIsImportModalOpen,
    ] = useModalState();

    const { modalsMap, closeModal, updateModal } = useModalsMap<ModalsMap>({
        shareLinkSuccessModal: { isOpen: false },
        shareLinkModal: { isOpen: false },
        limitModal: { isOpen: false },
    });

    if (calendars.length === 0) {
        return null;
    }

    const isPersonalCalendar = getIsPersonalCalendar(calendars[0]);

    const result = calendars.map((calendar, i) => {
        const { ID, Name, Display, Color } = calendar;
        const isCalendarDisabled = getIsCalendarDisabled(calendar);
        const isOwnedCalendar = getIsOwnedCalendar(calendar);

        const left = (
            <Checkbox
                className="mr0-75 flex-item-noshrink"
                color={COLORS.WHITE}
                backgroundColor={Display ? Color : 'transparent'}
                borderColor={Color}
                checked={!!Display}
                disabled={loading}
                aria-describedby={`calendar-${i}`}
                onChange={({ target: { checked } }) => onChangeVisibility(ID, checked)}
            />
        );

        const isNotSyncedInfo = getCalendarHasSubscriptionParameters(calendar)
            ? getCalendarIsNotSyncedInfo(calendar)
            : undefined;

        return (
            <SidebarListItem key={ID}>
                <SidebarListItemDiv className="calendar-sidebar-list-item opacity-on-hover-container pt0-5 pb0-5 pr0-5">
                    <SidebarListItemContent
                        data-test-id="calendar-sidebar:user-calendars"
                        left={left}
                        className={classnames(['flex', (isCalendarDisabled || isNotSyncedInfo) && 'color-weak'])}
                    >
                        <div className="flex flex-nowrap flex-justify-space-between flex-align-items-center w100">
                            <div className="flex flex-nowrap mr0-5">
                                <div className="text-ellipsis" title={Name}>
                                    {Name}
                                </div>
                                {!isCalendarDisabled && isNotSyncedInfo && (
                                    <div className="flex-item-noshrink">
                                        &nbsp;
                                        <Tooltip title={isNotSyncedInfo.text}>
                                            <span>({isNotSyncedInfo.label})</span>
                                        </Tooltip>
                                    </div>
                                )}
                                {isCalendarDisabled && (
                                    <div className="flex-item-noshrink">
                                        &nbsp;({c('Disabled calendar name suffix').t`Disabled`})
                                    </div>
                                )}
                                {!isOwnedCalendar && (
                                    <Tooltip title={c('Calendar sidebar; Calendar info').t`Shared with me`}>
                                        <div className="flex-item-noshrink ml0-25">
                                            <Icon name="users" />
                                        </div>
                                    </Tooltip>
                                )}
                            </div>

                            <Tooltip title={c('Sidebar calendar edit tooltip').t`Manage calendar`}>
                                <SimpleDropdown
                                    as={Button}
                                    icon
                                    hasCaret={false}
                                    shape="ghost"
                                    size="small"
                                    className="calendar-sidebar-list-item-action opacity-on-hover flex-item-noshrink no-mobile"
                                    loading={actionsDisabled}
                                    content={<Icon name="three-dots-horizontal" />}
                                >
                                    <DropdownMenu>
                                        {getIsOwnedCalendar(calendar) && (
                                            <>
                                                <DropdownMenuButton
                                                    className="text-left"
                                                    onClick={() => {
                                                        setCalendarModalCalendar(calendar);
                                                        setIsCalendarModalOpen(true);
                                                    }}
                                                >
{'fraction_non_alphanumeric': 0.0982899066731402, 'fraction_numerical': 0.0018881156605707503, 'mean_word_length': 1.92489744398864, 'pattern_counts': {'":': 0, '<': 82, '<?xml version=': 0, '>': 98, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 85, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7394602', 'n_tokens_mistral': 4575, 'n_tokens_neox': 4461, 'n_words': 821}