Check server response of

Server response
NS records
Whois domain
Response headers
Request headers
Raw HTML code
302 Found - dlyc.com
HTTP Status: 302
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
Date: Sat, 10 May 2025 17:00:35 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 39
X-Powered-By: Express
Location: https://dlyc.com/
Vary: Accept
Via: 1.1 google

HTTP Code 302 Found (Moved Temporarily)

302 status code indicates that the requested resource is temporarily available at a different URL.

When is Code 302 used?

  • When temporarily changing a page URL
  • When testing new content
  • During temporary maintenance

What does Code 302 mean for the user?

The user is automatically redirected to the new URL, but search engines continue to index the old address.

200 OK - https://dlyc.com/
HTTP Status: 200
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
Date: Sat, 10 May 2025 17:00:35 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 580459
Vary: Accept-Encoding
X-Powered-By: Express
ETag: W/"8db6b-KTIU+1yRA/LRLJftKs/h4sf4Y1E"
Via: 1.1 google

HTTP Code 200 OK

200 status code is a standard successful HTTP server response. It means that the client’s request (e.g., from a browser) was successfully processed, and the server is delivering the requested data.

When is Code 200 used?

  • When loading a web page
  • When successfully receiving an API response
  • When processing a form or another HTTP request

What does Code 200 mean for the user?

The user receives content without errors, and the page or application functions properly. If Code 200 is accompanied by data, the browser or program processes and displays it to the user.

GET / HTTP/1.1
Host: dlyc.com
Accept: */*
User-Agent: Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected])
<!DOCTYPE html>
<html lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <script src="https://js.stripe.com/v3/"></script>
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <script src="/public/assets/js/jquery-ui.min.js"></script>
    <link href="/public/assets/css/jquery-ui.min.css" rel="stylesheet">
    <script type="text/javascript" src="/parse-sdk-js"></script>
    <!-- start vue -->
    
        <!-- prod minified vue js -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.21/vue.global.prod.min.js"></script>
    
    <script src="/public/assets/js/catch-all-minified/vue.min.js"></script>
    <!-- end vue -->
    <!-- library for image orientation -->
    <script src="/public/assets/js/load-image-all.min.js"></script>
    <!-- moment.js -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment-with-locales.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.45/moment-timezone-with-data.min.js"></script>
    <!-- library for charts -->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
    <link rel="stylesheet" href="/public/assets/css/material-icons.css">
    <!-- <link rel="stylesheet" href="https://kit.fontawesome.com/a59cae6e7b.css" crossorigin="anonymous"> -->
    <link rel="stylesheet" href="/public/assets/css/font-awesome.css" crossorigin="anonymous">
    <!-- more js -->
    <script src="/public/assets/js/cookies.js"></script>
    

    
        <!-- web builder -->
        <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500&family=Cormorant+Garamond&family=Lato&family=Lora:wght@400;500&family=Montserrat:wght@400;500;600&family=Boogaloo&family=PT+Sans:wght@400;700&family=Mukta:wght@400;700;800&family=Karla&family=Raleway:wght@400;500;700;800&family=Bree+Serif&family=Vollkorn&family=Nunito+Sans&family=Mrs+Saint+Delafield&family=Halant:wght@400;500;600;700&family=Carlito:ital,wght@0,400;0,700;1,400;1,700&family=Open+Sans:ital,wght@0,300;0,800&family=Cinzel:wght@400;900&display=swap" rel="stylesheet">
        <!-- Juice browserified for inline css -->
        <script src="/public/assets/browserified/juice-browserified.js"></script>
        <!-- start calendar stuff (tui-calendar) -->
        <link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/tui-calendar/v1.15.0/tui-calendar.css" />
        <link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/tui.date-picker/latest/tui-date-picker.css" />
        <link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/tui.time-picker/latest/tui-time-picker.css" />
        <!-- <link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/tui.date-picker/v1.15.0/tui-date-picker.css" /> -->
        <!-- <link rel="stylesheet" type="text/css" href="https://uicdn.toast.com/tui.time-picker/v1.15.0/tui-time-picker.css" /> -->
        <script src="https://uicdn.toast.com/tui.code-snippet/v1.5.2/tui-code-snippet.min.js"></script>
        <!-- <script src="https://uicdn.toast.com/tui.time-picker/v1.15.0/tui-time-picker.min.js"></script> -->
        <!-- <script src="https://uicdn.toast.com/tui.date-picker/v1.15.0/tui-date-picker.min.js"></script> -->
        <script src="https://uicdn.toast.com/tui-calendar/v1.15.0/tui-calendar.js"></script>
        <!-- end calendar stuff -->
        <script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
        <script src="/public/assets/js/browserify_src/bundle_browserify.js"></script>
        <script src="/public/assets/js/catch-all-minified/common-web-builder.min.js"></script>
        <!-- Cropper.js -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.min.js"></script>
        <!-- unlayer (newer email builder, to replace tinymce) -->
        <script src="https://editor.unlayer.com/embed.js"></script>
        
    

    

    <link rel="stylesheet" href="/public/assets/css/ios.css">

    <!-- weglot translations -->
    
         
    

    

    

    
    
    <!-- userway.org accessibility snippet -->
    
         
    

    

    
        <script src="/public/assets/js/catch-all-minified/hosted-sites.min.js"></script>
        <link href="/public/assets/css/hosted.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/dayjs@1/dayjs.min.js"></script>
        <!-- custom styles -->
        <style>

        

	

	

	
	

	/* set base fonts */
	
	
	
	
	
	

	/* set base colors */
	
	
	
    


	/* now write the styles */

	/* NOTE: the wb-content class needs to prepend all the styles so they are ONLY applied to hosted website content, not other content on the page - eg. for the website builder, it shouldn't impact the builder menu on the left */

	.wb-content .cs-header p, 
	.wb-content .cs-header div, 
	.cs-footer-sublink-label,
	.cs-header-sublink-label{
		font-family: Lato !important;  
	}

	.wb-content h1{
		font-size: 64px;
		font-weight: normal;
		font-family: Cormorant Garamond;
	}

    .custom-font-wrap h1{
		font-family: Cormorant Garamond;
	}

	.wb-content h2 {
		font-size: 42px;
		font-weight: normal;
		font-family: Cormorant Garamond;
	}

    .custom-font-wrap h2{
		font-family: Cormorant Garamond;
	}

	.wb-content h3{
		font-size: 28px;
		font-weight: normal;
		font-family: Cormorant Garamond;
	}

	.wb-content select{
		font-size: 28px;
		font-weight: normal;
		font-family: Cormorant Garamond;
	}

    .custom-font-wrap h3{
		font-family: Cormorant Garamond;
	}

	.wb-content p, 
    .wb-content div{
		font-size: 16px;
		font-weight: normal;
		font-family: Lato;
	}

    .custom-font-wrap p, 
    .custom-font-wrap div{
		font-family: Lato;
	}

	.wb-content button,
    .custom-font-wrap button
    {
		font-family: Cormorant Garamond
	}

	/*-- tab bars --*/

	.cs-tab-bar-option.active, 
	.cs-tab-bar-option:hover
	{
	    color: #fff !important;
	    background-color: #236651;
	}


	/*-- buttons --*/

	.wb-content button{
	  	color: #fff;
		background-color: #000000;
	}

    /* -- custom code for millbrook --*/
    
    /*-- end custom code for millbrook --*/

	/*-- color schemes --*/

	.wb-content .color_scheme_white .background, 
	.wb-content .color_scheme_white.background
	{
		background-color: #fff;
		color: #181b3e;
	}

	.wb-content .color_scheme_light .background, 
	.wb-content .color_scheme_light.background
	{
		background-color: #eaefef;
		color: #181b3e;
	}

	.wb-content .color_scheme_dark .background, 
	.wb-content .color_scheme_dark.background
	{
		background-color: #000000;
		color: #fff;
	}

	.wb-content .color_scheme_black .background, 
	.wb-content .color_scheme_black.background
	{
		background-color: #000;
		color: #fff;
	}

	.wb-content .color_scheme_accent_light .background, 
	.wb-content .color_scheme_accent_light.background
	{
		background-color: #fff;
		color: #236651;
	}

	.wb-content .color_scheme_accent_dark .background, 
	.wb-content .color_scheme_accent_dark.background
	{
		background-color: #236651;
		color: #fff;
	}

	/*----- color schemes for header ------ */

	.color_scheme_white .cs-header-link-wrap > p, 
	.color_scheme_white .cs-burgee-wrap > p{
	  color: #000000 !important;
	}

	.color_scheme_white .cs-header-link-wrap::after{
	  background: #000000;
	}

	.color_scheme_light .cs-header-background{
	  background-color: #eaefef;
	}

	.color_scheme_light .cs-header-link-wrap > p, 
	.color_scheme_light .cs-burgee-wrap > p{
	  color: #000000 !important;
	}

	.color_scheme_light .cs-header-link-wrap::after{
	  background: #000000;
	}

	.color_scheme_dark .cs-header-background{
	  background-color: #000000;
	} 

	.color_scheme_dark .cs-header-link-wrap > p, 
	.color_scheme_dark .cs-burgee-wrap > p{
	  color: #fff;
	}

	.color_scheme_dark .cs-header-link-wrap::after{
	  background: #fff;
	}

	.color_scheme_black .cs-header-background{
	  background-color: #000;
	}

	.color_scheme_black .cs-header-link-wrap > p, 
	.color_scheme_black .cs-burgee-wrap > p{
	  color: #fff;
	}

	.color_scheme_black .cs-header-link-wrap::after{
	  background: #fff;
	}

	.color_scheme_accent_light .cs-header-background{
	  background-color: #fff;
	}

	.color_scheme_accent_light .cs-header-link-wrap > p, 
	.color_scheme_accent_light .cs-burgee-wrap > p{
	  color: #236651;
	}

	.color_scheme_accent_light .cs-header-link-wrap::after{
	  background: #236651;
	}

	.color_scheme_accent_dark .cs-header-background{
	  background-color: #236651;
	}

	.color_scheme_accent_dark .cs-header-link-wrap > p, 
	.color_scheme_accent_dark .cs-burgee-wrap > p{
	  color: #fff;
	}

	.color_scheme_accent_dark .cs-header-link-wrap::after{
	  background: #fff;
	}


</style>        <!-- favicon -->
        
            <!-- try to fall back to the burgee url, but google might not love this if it's not sized properly, so we really want favicon_url set -->
            <link rel="shortcut icon" href="https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439">
            <link rel="icon" sizes="16x16 32x32 64x64" href="https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439">
        
        <!-- touch icon (mobile web) -->
        
        <!-- web app title (mobile safari) -->
        
            <meta name="apple-mobile-web-app-title" content="Delavan Lake Yacht Club">
        
        <!-- app_manifest (android) -->
        
    

    

    
    
        <title>Home - Delavan Lake Yacht Club</title>
    
    <!-- fb open graph tags -->
    <meta property="fb:app_id" content="314788812688609" />
    
        <meta property="og:image" content="https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439">
    
    

    <!-- Google Analytics for clubs -->
     
    <!-- END google analytics for clubs -->

    <!-- FB pixel for clubs -->
     
    <!-- FB pixel for clubs -->

    

    <!-- vue date picker -->
    <!-- see: https://vue3datepicker.com/ -->
    <script src="/public/assets/js/vue-date-picker-8.5.1.js"></script>
    <link rel="stylesheet" href="/public/assets/css/vue-date-picker.css">

</head>    <body 
        class='wb-content hosted-page' 
        data-club-id='VI8DfNDE1X' 
        data-club-name='Delavan Lake Yacht Club'
        data-timezone='America/Chicago'
    >
        
    <div class="globalMessageInsert flexNoWrap easeFast hideForPrinting">
        <div class="global-message-icon-loading">
            <div class="global-message-icon-spinner"></div>
        </div>
        <p>
            <i class="fa-solid fa-square-check global-message-icon-good"></i>
            <i class="fa-solid fa-square-xmark global-message-icon-bad"></i>
            <span></span>
        </p>
    </div>


        <!-- start standard content -->
        <div id="v-content" class="hidden relative leftText relative easeFast paddingTopHeader">
            <!-- header -->
            <custom-page-header></custom-page-header>
            <!-- page components -->
            
            
                
                    
                        <!-- check the config -->



<!-- clean them first, to weed out null values -->


    

    

    

    

    































 



























<!-- now generate markup -->

    <hero-banner-component
        :client_id="'Z6x0WhJKc8U_1652617443'"
        :formatting="'{&#34;section_height&#34;:&#34;70&#34;,&#34;section_width&#34;:&#34;70&#34;,&#34;align_items&#34;:&#34;flex-start&#34;,&#34;background_size&#34;:&#34;inset&#34;,&#34;overlay_opacity&#34;:&#34;0&#34;}'"
        :class_string="' color_scheme_dark inset orientation-left number_of_columns-3 caption_style-show_on_hover'"
        :style_string="'min-height:70vh;align-items:flex-start;background-color:#fff'"
        :element_style_string="'max-width:70%;'"
        :component_type="'hero-banner'"
        :elements_string="'%5B%5D'"
        :images_string="'[&#34;https://d282wvk2qi4wzk.cloudfront.net/Z6x0WhJKc8U_1652617443_0_image_1711143758400&#34;,&#34;https://d282wvk2qi4wzk.cloudfront.net/Z6x0WhJKc8U_1652617443_1_image_1711143816607&#34;,&#34;https://d282wvk2qi4wzk.cloudfront.net/Z6x0WhJKc8U_1652617443_2_image_1711143888001&#34;,&#34;https://d282wvk2qi4wzk.cloudfront.net/1652617500888_6489&#34;,&#34;https://d282wvk2qi4wzk.cloudfront.net/Z6x0WhJKc8U_1652617443_4_image_1711144164838&#34;]'"
    ></hero-banner-component>

                    
                
                    
                        <!-- check the config -->



<!-- clean them first, to weed out null values -->
































 



























<!-- now generate markup -->
	
    <div class="cs-text background flexWrap relative  color_scheme_white orientation-left number_of_columns-1 caption_style-show_on_hover" style="min-height:1vh;align-items:flex-start;">
        
            <div class="element-wrapper flexNoWrap flexWrapOnMobile" class="'element-wrapper_' + text" style="max-width:100%;">
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch1%20style%3D%5C%22font-weight%3A%20bold%3B%20text-align%3A%20center%3B%5C%22%3E%3Cspan%20class%3D%5C%22cs-font-size-46%5C%22%20style%3D%5C%22%5C%22%3E%3Cspan%20style%3D%5C%22color%3A%20rgb%2528251%2C%2087%2C%2031%2529%3B%5C%22%20class%3D%5C%22cs-color-PSFZCWTwx2g_1653515197%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fdfcfc%5C%22%20class%3D%5C%22cs-color-BgJ63NvjRWE_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23f5f5f5%5C%22%20class%3D%5C%22cs-color-S4tPwnRi7OR_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23efecec%5C%22%20class%3D%5C%22cs-color-rCEy8uQOWbu_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ebe6e6%5C%22%20class%3D%5C%22cs-color-XHPI7k6Ugrk_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23e2dfdf%5C%22%20class%3D%5C%22cs-color-YObsubA9opr_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23dbd7d7%5C%22%20class%3D%5C%22cs-color-Fxhfdd1EySQ_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23dcd6d6%5C%22%20class%3D%5C%22cs-color-AbMyCDWjX8Z_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23d7d1d1%5C%22%20class%3D%5C%22cs-color-DqEvkLWyKIt_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23d2cbcb%5C%22%20class%3D%5C%22cs-color-N242GdEeCJk_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23cbc3c3%5C%22%20class%3D%5C%22cs-color-N5oh141j3cc_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23c3bbbb%5C%22%20class%3D%5C%22cs-color-GIsT1aCUhrJ_1653515318%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23bdb2b2%5C%22%20class%3D%5C%22cs-color-vLS6EbkjBhD_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23bab0b0%5C%22%20class%3D%5C%22cs-color-pu4RbQ0Tz3C_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23aea3a3%5C%22%20class%3D%5C%22cs-color-LkmFCoT41iq_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23a59c9c%5C%22%20class%3D%5C%22cs-color-oBatLDV1Xbj_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23a09898%5C%22%20class%3D%5C%22cs-color-M9Sb8D7CLz8_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23938a8a%5C%22%20class%3D%5C%22cs-color-pJ2gK4kPBym_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%238b8484%5C%22%20class%3D%5C%22cs-color-xyg9inpk7C1_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23888181%5C%22%20class%3D%5C%22cs-color-fAqgXG0kluV_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23797272%5C%22%20class%3D%5C%22cs-color-pD4DVmYK8wk_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23766f6f%5C%22%20class%3D%5C%22cs-color-xoGfS2x6Ql8_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23696363%5C%22%20class%3D%5C%22cs-color-BwJI4E8yriA_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23615c5c%5C%22%20class%3D%5C%22cs-color-FObOQcamV1N_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23575252%5C%22%20class%3D%5C%22cs-color-irzaTJ33IpW_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23535050%5C%22%20class%3D%5C%22cs-color-AxRSFv3hEnP_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%234c4848%5C%22%20class%3D%5C%22cs-color-0qUQOJSoxuw_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23444141%5C%22%20class%3D%5C%22cs-color-7SOWtggytVd_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%233c3939%5C%22%20class%3D%5C%22cs-color-NTB78MZDWWN_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23393737%5C%22%20class%3D%5C%22cs-color-LRYdv6T51qZ_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23313030%5C%22%20class%3D%5C%22cs-color-tE0LOWRJqKF_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23292828%5C%22%20class%3D%5C%22cs-color-O6cATuCuxr0_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%231f1f1f%5C%22%20class%3D%5C%22cs-color-qBYeyszuLaH_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23171717%5C%22%20class%3D%5C%22cs-color-5JiJkIaHZUq_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23121212%5C%22%20class%3D%5C%22cs-color-FmfG81gJkOi_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%230f0f0f%5C%22%20class%3D%5C%22cs-color-Xp7v51il2DJ_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23080808%5C%22%20class%3D%5C%22cs-color-waXQPHN4lig_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23050505%5C%22%20class%3D%5C%22cs-color-sZcjOG7vExd_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23000000%5C%22%20class%3D%5C%22cs-color-jszi7v7a8Nm_1653515319%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23020000%5C%22%20class%3D%5C%22cs-color-lm1vtZzNst8_1653515428%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23190000%5C%22%20class%3D%5C%22cs-color-G8ANbMKAgde_1653515428%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fb0000%5C%22%20class%3D%5C%22cs-color-htoH9sqLSKk_1653515428%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fb0800%5C%22%20class%3D%5C%22cs-color-3AJAakS3FgZ_1653515432%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fb5700%5C%22%20class%3D%5C%22cs-color-jIosIeH5awO_1653515433%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fb5703%5C%22%20class%3D%5C%22cs-color-woewk1qr7I9_1653515440%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fb571f%5C%22%20class%3D%5C%22cs-color-A46TpaWDfuP_1653515440%5C%22%3E%3Cspan%20style%3D%5C%22color%3A%2300571f%5C%22%20class%3D%5C%22cs-color-fxsv8lyQUUS_1653515452%5C%22%3E%3Cspan%20style%3D%5C%22color%3A%2300001f%5C%22%20class%3D%5C%22cs-color-yLi1NbGFXeA_1653515456%5C%22%3E%3Cspan%20style%3D%5C%22color%3A%23000000%5C%22%20class%3D%5C%22cs-color-AVhmSub0mpk_1653515460%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff4c2c%5C%22%20class%3D%5C%22cs-color-1IlqYwSFLM2_1656584533%5C%22%3ED%3C%2Fspan%3E%3Cspan%20style%3D%5C%22background-color%3A%23886d6d%5C%22%20class%3D%5C%22cs-color-PlhOf5V4n2N_1656584668%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23026d6d%5C%22%20class%3D%5C%22cs-color-NgEQbTaIlIP_1656584671%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23196d6d%5C%22%20class%3D%5C%22cs-color-qvPNuUqP8xz_1656584672%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff6d6d%5C%22%20class%3D%5C%22cs-color-JI6bjznv3gD_1656584672%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff026d%5C%22%20class%3D%5C%22cs-color-YsvMcZW3e8n_1656584673%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff196d%5C%22%20class%3D%5C%22cs-color-DpD1GmxCFtX_1656584674%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff6d%5C%22%20class%3D%5C%22cs-color-N0N7wgYZB9a_1656584674%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff02%5C%22%20class%3D%5C%22cs-color-mNy7u5ZWPhd_1656584677%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff19%5C%22%20class%3D%5C%22cs-color-f2MtQgQ30RI_1656584678%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffffff%5C%22%20class%3D%5C%22cs-color-zfOLsBeeEcF_1656584678%5C%22%3Eelavan%20%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3EL%3Cspan%20style%3D%5C%22background-color%3A%23a06a6a%5C%22%20class%3D%5C%22cs-color-DYq98pI2ibH_1656584645%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23026a6a%5C%22%20class%3D%5C%22cs-color-F34JzTzcXoV_1656584649%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23196a6a%5C%22%20class%3D%5C%22cs-color-jvIsFBw1WaO_1656584650%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff6a6a%5C%22%20class%3D%5C%22cs-color-VcAwayOpMBO_1656584650%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff026a%5C%22%20class%3D%5C%22cs-color-urYDMi8zOYd_1656584652%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff196a%5C%22%20class%3D%5C%22cs-color-bAOebaqlFn5_1656584653%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff6a%5C%22%20class%3D%5C%22cs-color-xCRYq5KHOgo_1656584653%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff02%5C%22%20class%3D%5C%22cs-color-ci2iFFnqIHV_1656584655%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff19%5C%22%20class%3D%5C%22cs-color-ax33cPNGM1d_1656584655%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffffff%5C%22%20class%3D%5C%22cs-color-7aDj3CkNpai_1656584655%5C%22%3Eake%20%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3EY%3Cspan%20style%3D%5C%22background-color%3A%2302fdfe%5C%22%20class%3D%5C%22cs-color-Xm6hbfiBW9s_1656584613%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%2319fdfe%5C%22%20class%3D%5C%22cs-color-HciMcHZkSM3_1656584613%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fffdfe%5C%22%20class%3D%5C%22cs-color-akPih26URKP_1656584614%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff03fe%5C%22%20class%3D%5C%22cs-color-sKdgWQEQ1Mx_1656584617%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff23fe%5C%22%20class%3D%5C%22cs-color-Cl1qBJh5tdW_1656584617%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff02fe%5C%22%20class%3D%5C%22cs-color-yMOx5E5nzMw_1656584620%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ff19fe%5C%22%20class%3D%5C%22cs-color-jHSBpjH7oSF_1656584621%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23fffffe%5C%22%20class%3D%5C%22cs-color-0hlNvLRnLRM_1656584621%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff02%5C%22%20class%3D%5C%22cs-color-OrWpzyFWhR3_1656584624%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffff19%5C%22%20class%3D%5C%22cs-color-w0GPPQYBQiW_1656584624%5C%22%3E%3Cspan%20style%3D%5C%22background-color%3A%23ffffff%5C%22%20class%3D%5C%22cs-color-kOu14oJ9X1l_1656584625%5C%22%3Eacht%20%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3EC%3Cspan%20style%3D%5C%22background-color%3A%23fcfdfe%5C%22%20class%3D%5C%22cs-color-uAEa7Cjj56I_1656584574%5C%22%3Elub%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fspan%3E%3C%2Fh1%3E%22%7D%5D'"
                        :column_index="'0'"
                    ></text-component>	
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch2%20style%3D%5C%22text-align%3A%20center%3B%5C%22%3EClick%20to%20edit%3C%2Fh2%3E%22%7D%2C%7B%22type%22%3A%22h3-center%22%2C%22content%22%3A%22%3Ch3%20style%3D%5C%22text-align%3A%20center%3B%5C%22%3EClick%20to%20edit%3C%2Fh3%3E%22%7D%5D'"
                        :column_index="'1'"
                    ></text-component>	
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch2%20style%3D%5C%22text-align%3A%20center%3B%5C%22%3EClick%20to%20edit%3C%2Fh2%3E%22%7D%2C%7B%22type%22%3A%22h3-center%22%2C%22content%22%3A%22%3Ch3%20style%3D%5C%22text-align%3A%20center%3B%5C%22%3EClick%20to%20edit%3C%2Fh3%3E%22%7D%5D'"
                        :column_index="'2'"
                    ></text-component>	
                
            </div>
        
    </div>

                    
                
                    
                        <!-- check the config -->



<!-- clean them first, to weed out null values -->


    

    

    

    

    

    

    

    

    

    































 



























<!-- now generate markup -->

    <image-grid-component
        :client_id="'ut3tyc3qhH6_1652619772'"
        :class_string="' color_scheme_white orientation-left number_of_columns-3 caption_style-show_on_hover'"
        :image_grid_layout="'grid'"
        :images_per_row="'5'"
        :caption_size="'24'"
        :subtext_size="'24'"
        :link_label_size="'24'"
        :text_position="'center'"
        :caption_font_weight="'400'"
        :image_grid_opacity="'40'"
        :image_grid_border_radius="'0'"
        :formatting="'{&#34;caption_style&#34;:&#34;show_on_hover&#34;,&#34;overlay_opacity&#34;:&#34;40&#34;}'"
        :images_string="'[{\&#34;id\&#34;:\&#34;CuSS50t2nYr_1652619784\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/1652619783395_9459\&#34;},{\&#34;id\&#34;:\&#34;zJud5oXcy4s_1652620007\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/1652620006222_1064\&#34;},{\&#34;id\&#34;:\&#34;Zz6S5w5vdj3_1652620015\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/1652620014809_7139\&#34;},{\&#34;id\&#34;:\&#34;YEWrgR32PGg_1652620035\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/1652620034542_605\&#34;},{\&#34;id\&#34;:\&#34;gS9EOJWvFvX_1711144036\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144027223\&#34;,\&#34;is_video\&#34;:false},{\&#34;id\&#34;:\&#34;twG4mu5H213_1711144336\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144323423\&#34;,\&#34;is_video\&#34;:false},{\&#34;id\&#34;:\&#34;gJSPaSJadJ9_1711144503\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144488327\&#34;,\&#34;is_video\&#34;:false},{\&#34;id\&#34;:\&#34;f7aeiQgaPCs_1711144598\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144578992\&#34;,\&#34;is_video\&#34;:false},{\&#34;id\&#34;:\&#34;QOxytAQMTaM_1711144538\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144527839\&#34;,\&#34;is_video\&#34;:false},{\&#34;id\&#34;:\&#34;O8S2wyGBM5E_1711144670\&#34;,\&#34;url\&#34;:\&#34;https://d282wvk2qi4wzk.cloudfront.net/ut3tyc3qhH6_1652619772_grid_image_1711144663169\&#34;,\&#34;is_video\&#34;:false}]'"
    ></image-grid-component>

                    
                
                    
                        <!-- check the config -->



<!-- clean them first, to weed out null values -->
































 



























<!-- now generate markup -->
	
    <div class="cs-text background flexWrap relative  color_scheme_white orientation-left number_of_columns-1 caption_style-show_on_hover" style="min-height:1vh;align-items:center;">
        
            <div class="element-wrapper flexNoWrap flexWrapOnMobile" class="'element-wrapper_' + text" style="max-width:100%;">
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch2%20style%3D%5C%22text-align%3Acenter%5C%22%3E%3Cp%20class%3D%5C%22MsoNormal%5C%22%3E%3C%2Fp%3E%3C%2Fh2%3E%3Ch3%20style%3D%5C%22text-align%3Acenter%5C%22%3E%3Cspan%20style%3D%5C%22font-size%3A18.0pt%3Bline-height%3A107%25%3Bfont-family%3A%26quot%3BArial%26quot%3B%2Csans-serif%5C%22%3E%3Cspan%20class%3D%5C%22cs-EDqs5I8qQ7O_1715257127_1715257127372%5C%22%20style%3D%5C%22background-color%3Argb%2528248%2C%20180%2C%2032%2529%5C%22%3E%3Cspan%20class%3D%5C%22cs-font-size-42%5C%22%20style%3D%5C%22background-color%3Argb%2528248%2C%20184%2C%2048%2529%5C%22%3ECLICK%20TO%20ACCESS%20RACE%20COMMITTEE%20VOLU%3Ca%20href%3D%5C%22https%3A%2F%2Fwww.signupgenius.com%2Fgo%2F10C054CA9AF29A2FACF8-56018278-2025%5C%22%20target%3D%5C%22_blank%5C%22%20class%3D%5C%22cs-link-MzNJaVUrr7U_1746536039%5C%22%3E%3C%2Fa%3ENTEER%20SIGNUP%3C%2Fspan%3E%3C%2Fspan%3E%3Co%3Ap%3E%3C%2Fo%3Ap%3E%3C%2Fspan%3E%3C%2Fh3%3E%3Cp%3E%3C%2Fp%3E%22%2C%22client_id%22%3A%221K0WltQICWh8OTt1%22%2C%22column_count%22%3A1%2C%22column_gap%22%3A0%7D%5D'"
                        :column_index="'0'"
                    ></text-component>	
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch2%20style%3D%5C%22text-align%3Acenter%5C%22%3EClick%20to%20edit%3C%2Fh2%3E%22%2C%22client_id%22%3A%22DdGlNorG3yBmxS2S%22%2C%22column_count%22%3A1%2C%22column_gap%22%3A0%7D%2C%7B%22type%22%3A%22h3-center%22%2C%22content%22%3A%22%3Ch3%20style%3D%5C%22text-align%3Acenter%5C%22%3EClick%20to%20edit%3C%2Fh3%3E%22%2C%22client_id%22%3A%22iFxWOgG8hW0YC5sx%22%2C%22column_count%22%3A1%2C%22column_gap%22%3A0%7D%5D'"
                        :column_index="'1'"
                    ></text-component>	
                
                    <text-component
                        :number_of_columns="'1'"	
                        :column_prop="'%5B%7B%22type%22%3A%22h2-center%22%2C%22content%22%3A%22%3Ch2%20style%3D%5C%22text-align%3Acenter%5C%22%3EClick%20to%20edit%3C%2Fh2%3E%22%2C%22client_id%22%3A%2264YC6qip4OfqlOOu%22%2C%22column_count%22%3A1%2C%22column_gap%22%3A0%7D%2C%7B%22type%22%3A%22h3-center%22%2C%22content%22%3A%22%3Ch3%20style%3D%5C%22text-align%3Acenter%5C%22%3EClick%20to%20edit%3C%2Fh3%3E%22%2C%22client_id%22%3A%22Mk9rP2TgPDIw8wqF%22%2C%22column_count%22%3A1%2C%22column_gap%22%3A0%7D%5D'"
                        :column_index="'2'"
                    ></text-component>	
                
            </div>
        
    </div>

                    
                
            
            <!-- footer -->
            

<!-- check the config -->

    
<div class="cs-footer relative color_scheme_white" style="" >
    <div class="">
        <div class="cs-footer-flex-wrap-row">
            <div class="cs-footer-logo-wrap background">
                
                    
                    
                    <div class="cs-burgee-wrap relative" style="height:70px;width:120px;">
                        <div class="cs-burgee" style="background-image:url(https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439)"></div>
                        <a class="absoluteA" href="/"></a>
                    </div>
                
            </div>
            <div>
                <div class="flexWrapLeftAlign">
                    <div class="cs-footer-link-wrap flexGrowOne noPaddingBottom">
                        
                            
                            
                            
                                
                                    <!-- component -->
                                    <div class="footer-link-section flexGrowOne">
                                        
                                        
                                            <p class="footer-sublink-section-header smallMarginTop">262-725-1426</p>
                                        
                                        <!-- handle sub-components -->
                                        
                                        
                                    </div>
                                
                            
                        
                            
                            
                            
                                
                                    <!-- component -->
                                    <div class="footer-link-section flexGrowOne">
                                        
                                        
                                            <p class="footer-sublink-section-header smallMarginTop">P.O. BOX 482  DELAVAN, WI</p>
                                        
                                        <!-- handle sub-components -->
                                        
                                        
                                    </div>
                                
                            
                        
                            
                            
                            
                                
                                    <!-- component -->
                                    <div class="footer-link-section flexGrowOne">
                                        
                                        
                                            <p class="footer-sublink-section-header smallMarginTop">[email protected]</p>
                                        
                                        <!-- handle sub-components -->
                                        
                                        
                                    </div>
                                
                            
                        
                            
                            
                            
                                
                                    <!-- component -->
                                    <div class="footer-link-section flexGrowOne">
                                        
                                        
                                            <p class="footer-sublink-section-header smallMarginTop">
                                                facebook
                                                <a class="absoluteA" href="https://www.facebook.com/DelavanLakeYachtClub"></a>
                                            </p>
                                        
                                        <!-- handle sub-components -->
                                        
                                        
                                    </div>
                                
                            
                        
                            
                            
                            
                                
                                    <!-- component -->
                                    <div class="footer-link-section flexGrowOne">
                                        
                                        
                                            <p class="footer-sublink-section-header smallMarginTop">
                                                instagram
                                                <a class="absoluteA" href="https://www.instagram.com/delavanlakeyachtclub/"></a>
                                            </p>
                                        
                                        <!-- handle sub-components -->
                                        
                                        
                                    </div>
                                
                            
                        
                        <!-- social icons -->
                        
                    </div>
                </div> 
                <div class="cs-footer-link-wrap noPaddingTop">
                    <div class="powered_by_wrap relative">
                        <div class="flexNoWrap align-items-center">
                            <p class="powered_by"><i class="fa-solid fa-shield-check" style="padding-right:3px;"></i> Powered by</p>
                            <p class="modern pointer powered_by_text relative" style="font-weight:bold;">Clubspot <a class="absoluteA" href="https://theclubspot.com"></a></p>
                        </div>
                        
                        <p style="display:flex;font-family:roboto !important;" class="cs-footer-sublink-label roboto copyright_text noPointer">© 2025 Delavan Lake Yacht Club, All rights reserved.</p>
                    </div> 
                </div>
            </div>
        </div>
    </div>
</div>
            <!-- react native tab bar -->
            <native-tab-bar-component></native-tab-bar-component>

        </div>
        <div id="v-overlays" class="hidden">
            <!-- common -->
            <template v-if="overlays.overflow_overlay">
                <overflow-overlay></overflow-overlay>
            </template>

            <template v-if="overlays.view_all_events">
                <view-all-events-overlay></view-all-events-overlay>
            </template>

            <template v-if="overlays.view_photo_carousel">
                <view-photo-carousel></view-photo-carousel>
            </template>

        </div>
        <div id="overlay_membership-directory-popup" class="standardOverlay scrollable hugePaddingBottom">
    <div class="standardOverlayCard centeredBlock eightyThenNinety overflowHidden relative">
        <div class="xButton" onclick="fadeOut('#overlay_membership-directory-popup');"></div>
        <div class="profile-background overflowHidden">
            <div class="profile-background-inner hundop" style="height:100%;"></div>
        </div>
        <div class="profile-picture color_scheme_accent_dark background capitalize"></div>
        <div class="paddingAllAround smallMarginBottom">

            <p class="insert insert_name product-card-label"></p>

            <div class="section-wrap tinyMarginTop tinyMarginBottom">
                <p class="flexGrowOne inline-value" data-db-key="street"></p>
                <p class="flexGrowOne inline-value" data-db-key="city"></p>
                <p class="flexGrowOne inline-value" data-db-key="state"></p>
                <p class="flexGrowOne inline-value" data-db-key="zip"></p>
            </div>

            <div class="section-wrap tinyMarginTop tinyMarginBottom">
                <h4 class="smallBlockLetters leftText smallMarginTop">Contact</h4>
                <p class="flexGrowOne inline-value tinyPaddingTop" data-db-key="email"></p>
                <p class="flexGrowOne inline-value tinyPaddingTop" data-db-key="mobile"></p>
            </div>

            <div class="section-wrap tinyMarginTop tinyMarginBottom">
                <h4 class="smallBlockLetters leftText smallMarginTop">Secondary address</h4>
                <p class="flexGrowOne inline-value dark tinyPaddingTop" data-db-key="street_secondary"></p>
                <p class="flexGrowOne inline-value dark" data-db-key="city_secondary"></p>
                <p class="flexGrowOne inline-value dark" data-db-key="state_secondary"></p>
                <p class="flexGrowOne inline-value dark" data-db-key="zip_secondary"></p>
            </div>

            <div class="section-wrap section-wrap_custom_fields tinyMarginTop tinyMarginBottom">
                
            </div>

            <!-- boat fields -->
            <div class="section-wrap tinyMarginTop tinyMarginBottom">
                <p class="flexGrowOne inline-value" data-db-key="boatName"></p>
                <p class="flexGrowOne inline-value" data-db-key="sailNumber" data-prepend="Sail #:"></p>
                <p class="flexGrowOne inline-value" data-db-key="hullNumber" data-prepend="Hull #:"></p>
                <p class="flexGrowOne inline-value" data-db-key="class" data-prepend="Class: "></p>
                <p class="flexGrowOne inline-value" data-db-key="registration" data-prepend="Registration #:"></p>
            </div>

            <div class="section-wrap section-wrap_documents hidden tinyMarginTop tinyMarginBottom">
                <h4 class="smallBlockLetters leftText smallMarginTop">Documents</h4>
                <!-- documents inserted here -->

            </div>

            <div class="section-wrap section-wrap_family tinyMarginTop tinyMarginBottom">
                <h4 class="smallBlockLetters leftText smallMarginTop version_member">Family</h4>
                <h4 class="smallBlockLetters leftText smallMarginTop version_boat hidden">Related Members</h4>
                <!-- family members inserted here -->

            </div>

            <div class="section-wrap section-wrap_boats hidden tinyMarginTop tinyMarginBottom">
                <h4 class="smallBlockLetters leftText smallMarginTop version_member">Boats</h4>
                <h4 class="smallBlockLetters leftText smallMarginTop version_boat hidden">Related boats</h4>
                <!-- boats inserted here -->

            </div>

        </div>
    </div>
</div>        <div id="overlay_event-description-popup" class="standardOverlay scrollable hugePaddingBottom" style="display:none;opacity:0;">
    <div class="standardOverlayCard centeredBlock eightyThenNinety">
        <h3></h3>
        <div class="standardCardBody noPadding fff">
            <div class="centeredBlock eightyThenNinety maxSixHundo bigPaddingBottom marginTop">
                <p class="inline-label smallerMarginBottom">Date</p>
                <p class="metric marginBottom leftText tinyMarginTop metric_start_date" style="margin-bottom:20px;"></p>
                <p class="inline-label smallerMarginBottom">Time</p>
                <p class="metric marginBottom leftText tinyMarginTop metric_start_date_time" style="margin-bottom:20px;"></p>
                <p class="inline-label smallerMarginBottom">Event Details</p>
                <p class="metric marginBottom leftText tinyMarginTop metric_description" style="margin-bottom:20px;"></p>
            </div>
        </div>
        <div class="standardCardFooter flexNoWrap">
            <div class="flexGrowOne"></div>
            <button class="cardFooterButton easeFast" onclick="fadeOut('#overlay_event-description-popup');">Done</button>
        </div>
    </div>
</div>
        


    </body>
    <script>

        //add the timezone to the global store
        store.timezone = $('body').data('timezone');

        //add to global store
        store.eventBus = ref({
            listeners: {},
            $on(event, callback) {
                if (!this.listeners[event]) {
                this.listeners[event] = [];
                }
                this.listeners[event].push(callback);
            },
            $emit(event, ...args) {
                if (this.listeners[event]) {
                for (const callback of this.listeners[event]) {
                    callback(...args);
                }
                }
            },
        });

        //create the app
        var app_content = createApp({
            data() {
                return store
            },
            mounted() {
                console.log("mounted vue app: main content");
                $('#v-content').removeClass('hidden');
            },
            methods: {
               
            },
        });

        //create the app
        var app_overlays = createApp({
            data() {
                return store
            },
            mounted() {
                console.log("mounted vue app: overlays");
                $('#v-overlays').removeClass('hidden');
            }
        });

    </script>

    <!-- define/register vue components  -->
    <script type="text/html" id="template-custom-page-header">
    

    <!-- globals -->
    
    

    <!-- check the config -->
    
    
    
    

    <!-- color scheme -->
    
    
    
    

    <!-- opacity -->
    
    

    <!-- font-size -->
    
    
    

    <!-- font-weight -->
    
    
    

    <!-- header style (eg stacked vs inline vs centered) -->
    
    
    

    <!-- header position (eg relative vs absolute) -->
    
    
    

    <!-- header background image, eg. for inverness yc -->
    

    <!-- burgee url -->
    

    <!-- ok, start header markup -->
    <div class="cs-header easeFast absolute-header color_scheme_white cs-font-size-16 header-400 header-style_inline header-position_relative" style="">
        <div class="cs-header-background background" style="opacity: 100%;"></div>
        <div class="innerHeader align-items-middle flexNoWrap">
            <div class="hamburgerWrap marketingMenu">
                <div style="position: fixed; height: 1px; width: 1px; opacity: .01;"></div>
                <div class="hamburger hideOnDesktop">
                    
                        <div id="headerLineTop" class="ease"></div>
                        <div id="headerLineMiddle" class="ease"></div>
                        <div id="headerLineBottom" class="ease"></div>
                    
                </div>
                
                    <p class="burger-menu-text hideOnDesktop hideOnMobile">Menu</p>
                
            </div>

            
                
                
                
                    <div class="cs-burgee-wrap hideOnMobile" style="height:0px;width:0px;">
                        <div class="cs-burgee" style="background-image: url(https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439)"></div>
                        <a href="/" class="absoluteA"></a>
                    </div>
                
                <div class="cs-burgee-wrap-mobile">
                    <div class="cs-burgee" style="background-image:url(https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439);background-size:contain;"></div>
                    <a :href="burgee_link" class="absoluteA"></a>
                </div>
            

            <div class="cs-desktop-menu-wrap flexGrowOne flexWrapRightAlign hideOnMobile  header-style_inline">
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Regattas</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Regattas</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/regattas"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Lodging</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/lodging"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">ILYA</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="https://ilya.org/"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Racing</p>
                                <!-- link -->
                                
                                
                                    <a class="absoluteA" href="/race-schedule"></a>
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Official Notice Board</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/official-notice-board"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">X Boat</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/fleet-x-boat"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">MC Scow</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/fleet-mc"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">C Scow</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/fleet-c"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">E Scow</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/fleet-e"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Flying Scot</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/fleet-flying-scot"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Wallen All Sail</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/wallen-all-sail"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Uncle Elmer&#39;s</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/uncle-elmers"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Events</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Calendar</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/event-calendar"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Club Rental</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/club-rental"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Social Events</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/dlyc-social-events-"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Reservations</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/reservations-"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">News</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Edmonds Videos</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/edmonds"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Menus</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Menus</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/menus"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Youth</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Day Camp</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/day-camp"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">DLSS</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="https://www.delavanlakesailingschool.com/"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">About</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">2024 early Advertisers</p>
                                                        
                                                        
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Advertisers</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/advertisers"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">FAQ</p>
                                                        
                                                        
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">History</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/history"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">Contact Us</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="/contact-us-"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  header-style_inline">
                                <p class="button_link_p" style="">Merchandise</p>
                                <!-- link -->
                                
                                
                                <!-- handle sub-components -->
                                
                                
                                    <div class="cs-header-sublink-outer easeFast">
                                        
                                            
                                            
                                            
                                                
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                            
                                        
                                            
                                            
                                            
                                                
                                                
                                                    <div class="cs-header-sublink-wrap relative">
                                                        <p class="cs-header-sublink-label">DLYC Merchandise</p>
                                                        
                                                        
                                                        
                                                            <a class="absoluteA" href="https://dlycgear.itemorder.com/shop/home/"></a>
                                                        
                                                    </div>
                                                
                                            
                                        
                                    </div>
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                    
                
                    
                    
                    
                    
                        
                        
                            
                            <div class="cs-header-link-wrap  link-style-button header-style_inline">
                                <p class="button_link_p" style="background-color:#f77408 !important; color:#ffffff !important;">Member Login</p>
                                <!-- link -->
                                
                                
                                    <a class="absoluteA" href="/login"></a>
                                
                                <!-- handle sub-components -->
                                
                                
                            </div>
                        
                    
                
                    
                    
                    
                    
                        
                        
                    
                
            </div>
        </div>
    </div>

    <!-- now the mobile menu -->
    <div class="mobileMenuOverlay hideOnDesktop ease"></div>
    <div class="mobileMenu hideOnDesktop easeFast scrollable">
        <div class="innerMenu">
            <div class="mobile-link-wrap">


                
                    <div class="cs-burgee-wrap" style="width:175px;height:60px;float:none;margin-top:-40px;margin-bottom:15px;">
                        <div class="cs-burgee" style="background-position:left;background-image:url(https://myclubspot.s3-us-west-2.amazonaws.com/yVq6rz613F_burgee_1574269334439);background-size:contain;margin-bottom:15px;"></div>
                        <a :href="burgee_link" class="absoluteA"></a>
                    </div>
                


                <div class="mobile-sublink-outer easeFast">

                    
                        <div class="header-sublink-wrap relative">
                            <p class="header-sublink-label">My Account</p>
                            <p class="header-sublink-explain">Click below to view your account</p>
                            <button class="wb-button-primary easeFast boxShadowBottom smallMarginTop">
                                View my account
                                <a class="absoluteA" href="/account"></a>
                            </button>
                        </div>
                    
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">Regattas</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Regattas
                                                            <a class="absoluteA" href="/regattas"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Lodging
                                                            <a class="absoluteA" href="/lodging"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            ILYA
                                                            <a class="absoluteA" href="https://ilya.org/"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">
                                        Racing
                                        <a class="absoluteA" href="/race-schedule"></a>
                                    </p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Official Notice Board
                                                            <a class="absoluteA" href="/official-notice-board"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            X Boat
                                                            <a class="absoluteA" href="/fleet-x-boat"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            MC Scow
                                                            <a class="absoluteA" href="/fleet-mc"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            C Scow
                                                            <a class="absoluteA" href="/fleet-c"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            E Scow
                                                            <a class="absoluteA" href="/fleet-e"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Flying Scot
                                                            <a class="absoluteA" href="/fleet-flying-scot"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Wallen All Sail
                                                            <a class="absoluteA" href="/wallen-all-sail"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Uncle Elmer&#39;s
                                                            <a class="absoluteA" href="/uncle-elmers"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">Events</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Calendar
                                                            <a class="absoluteA" href="/event-calendar"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Club Rental
                                                            <a class="absoluteA" href="/club-rental"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Social Events
                                                            <a class="absoluteA" href="/dlyc-social-events-"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Reservations
                                                            <a class="absoluteA" href="/reservations-"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">News</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Edmonds Videos
                                                            <a class="absoluteA" href="/edmonds"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">Menus</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Menus
                                                            <a class="absoluteA" href="/menus"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">Youth</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Day Camp
                                                            <a class="absoluteA" href="/day-camp"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            DLSS
                                                            <a class="absoluteA" href="https://www.delavanlakesailingschool.com/"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">About</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">2024 early Advertisers</p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Advertisers
                                                            <a class="absoluteA" href="/advertisers"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">FAQ</p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            History
                                                            <a class="absoluteA" href="/history"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            Contact Us
                                                            <a class="absoluteA" href="/contact-us-"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">Merchandise</p>
                                
                                <!-- handle sub-components -->
                                
                                
                                    
                                        
                                        
                                        
                                            
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                        
                                    
                                        
                                        
                                        
                                            
                                            
                                                <div class="cs-header-sublink-wrap relative">
                                                    
                                                    
                                                        <p class="cs-header-sublink-label">
                                                            DLYC Merchandise
                                                            <a class="absoluteA" href="https://dlycgear.itemorder.com/shop/home/"></a>
                                                        </p>
                                                    
                                                </div>
                                            
                                        
                                    
                                
                            
                        
                    
                        
                        
                        
                            
                            
                        
                    
                        
                        
                        
                            
                            
                                <!-- component -->
                                
                                
                                    <p class="header-sublink-section-header smallMarginTop">
                                        Member Login
                                        <a class="absoluteA" href="/login"></a>
                                    </p>
                                
                                <!-- handle sub-components -->
                                
                                
                            
                        
                    
                        
                        
                        
                            
                            
                        
                    
                </div>
            </div>
        </div>
    </div>
    
</script>



<script>

    //define the component
    app_content.component("custom-page-header", {
        template: "#template-custom-page-header",
        data() {
            return {}
        }, 
        props: {},
        mounted(){
            console.log("mounted hosted page header")
        },
        methods: {
            
        },
        computed: {
            burgee_link(){
                if( this.is_react_native_member_app ){
                    return "/account"
                }
                return "/"
            },
            current_user(){
                return Parse.User.current()
            },
            is_react_native_member_app(){
                return store.is_react_native_member_app;
            }
        },
    });


</script>    <script type="text/html" id="template-image-grid">
    <template v-if="!image_grid_layout || image_grid_layout !== 'carousel'">
        <div 
            class="image-grid-wrap centeredBlock"
            :class="'image-grid-wrap_' + client_id + ' images_per_row_' + images_per_row + ' ' + class_string"
        >
            <!-- draggable start for image-grid-image -->
            <div 
                v-if="!loading && images?.length > 0" 
                class="image-grid-insert flexWrapLeftAlign" 
                :class=" is_admin ? 'draggable-container_image_grid_' + component.id : ''  "
            >
                <template v-for="(image, index) in images" :key="image?.id">
                    <div 
                        v-if="image && image.url" 
                        class="image-grid-image relative" 
                        :class="'image-grid-image_' + image?.id"
                        :id="image?.id"
                    >
                        <!-- video -->
                        <div 
                            v-if="image.is_video" 
                            class="image-grid-image-inner" 
                            style="align-items:center;display:flex;" 
                            :style="{'border-radius': image_grid_border_radius + 'px' }"
                        >
                            <video class="cs-background-video" autoplay playsinline loop muted :src="image.url" style="display:block;"></video>
                            <div v-if="is_admin" class="image-grid-drag-handle-wrap draggable-handle">
                                <i class="fa-regular fa-grip-dots image-grid-drag-handle"></i>
                            </div>
                        </div>
                        <!-- image -->
                        <div 
                            v-else
                            class="image-grid-image-inner" 
                            :style="{'background-image': 'url(' + image.url + ')', 'border-radius': image_grid_border_radius + 'px' }"
                        >
                            <div v-if="is_admin" class="image-grid-drag-handle-wrap draggable-handle">
                                <i class="fa-regular fa-grip-dots image-grid-drag-handle"></i>
                            </div>
                        </div>
                        <!-- overlay -->
                        <div v-if="is_admin" class="image-grid-image-overlay flexWrap easeFast" :style="{ 'background-color': returnRGBAStringForImageGridImageOverlayOpacity( image_grid_opacity ), 'border-radius': image_grid_border_radius + 'px' }" @click.stop>
                            <div class="image-toolbar-wrapper flexNoWrap centeredBlock" @click.stop>
                                <div 
                                    class="image-toolbar-option easeFast" 
                                    data-option="update" 
                                    style="border-right:1px solid #fff;" 
                                    @click.stop="prepThenDisplayImageSettings(image)"
                                >Update</div>
                                <div 
                                    class="image-toolbar-option easeFast" 
                                    data-option="remove" 
                                    @click.stop="tapped_remove_image(image)"
                                ><i class="fa-regular fa-trash" style="font-size:14px;"></i></div>
                            </div>
                            <div class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                <h2 
                                    v-if="image.caption"
                                    class="image-grid-image-caption"
                                    :style="{ 'font-size': caption_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.caption }}</h2>
                                <p
                                    v-if="image.subtext"
                                    class="image-grid-image-caption marginTopFour"
                                    :style="{ 'font-size': subtext_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.subtext }}</p>
                                <p
                                    v-if="image.link_label"
                                    class="image-grid-image-caption marginTopFour"
                                    style="text-decoration: underline;"
                                    :style="{ 'font-size': link_label_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.link_label }}</p>
                            </div>
                        </div> 
                        <div v-if="!is_admin" class="image-grid-image-overlay flexWrap easeFast" :style="{ 'background-color': returnRGBAStringForImageGridImageOverlayOpacity( image_grid_opacity ), 'border-radius': image_grid_border_radius + 'px' }">
                            <div class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                <h2 
                                    v-if="image.caption"
                                    class="image-grid-image-caption"
                                    :style="{ 'font-size': caption_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.caption }}</h2>
                                <p
                                    v-if="image.subtext"
                                    class="image-grid-image-caption marginTopFour"
                                    :style="{ 'font-size': subtext_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.subtext }}</p>
                                <p
                                    v-if="image.link_label"
                                    class="image-grid-image-caption marginTopFour"
                                    style="text-decoration: underline;"
                                    :style="{ 'font-size': link_label_size + 'px', 'font-weight': caption_font_weight }"
                                >{{ image.link_label }}</p>
                                <a
                                    v-if="image.link_to"
                                    class="absoluteA"
                                    :href="image.link_to"
                                    rel="noopener noreferrer"
                                ></a>
                            </div>
                        </div> 
                    </div>
                </template>
                <!-- upload image **for admin -->
                <template v-if="is_admin">
                    <div class="image-grid-image image-grid-image_upload non-draggable">
                        <div class="image-grid-image-inner">
                            <div class="uploadImageZone relative pointer">
                                <input 
                                    @change="imageUploadChange($event)"
                                    class="image-grid-upload-input absoluteInput" 
                                    type="file" accept="image/*,video/*"
                                >
                                <p class="centeredBlock" style="font-family:roboto !important;">+ Upload image/video</p>
                                <div class="uploadImageOverlay">
                                    <div class="uploadImageSpinner centeredBlock"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </template>
            </div>
            <!-- draggable end for image-grid-image -->
            <div v-if="!loading && images?.length === 0 && is_admin" class="image-grid-insert flexWrapLeftAlign">
                <div class="image-grid-image image-grid-image_upload">
                    <div class="image-grid-image-inner">
                        <div class="uploadImageZone relative pointer">
                            <input 
                                @change="imageUploadChange($event)"
                                class="image-grid-upload-input absoluteInput" 
                                type="file" accept="image/*,video/*"
                            >
                            <p class="centeredBlock" style="font-family:roboto !important;">+ Upload image/video</p>
                            <div class="uploadImageOverlay">
                                <div class="uploadImageSpinner centeredBlock"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div v-if="loading" class="cardBodySpinnerWrap active relative">
                <div class="cardBodySpinner centeredBlock"></div>
            </div>
        </div>
    </template>
    <template v-else>

        <div style="box-sizing: border-box; padding: 20px;" class="event-list-wrap centeredBlock centeredText" :class="'event-list-wrap_' + client_id">
            <!-- <div 
                class="flexNoWrap align-items-center event_list_carousel_default"
                style="padding: 0px 0px 15px 5px;"
            >
                <p>PLACEHOLDER</p>
            </div> -->
            <div 
                class="image-grid-wrap centeredBlock"
                :class="'image-grid-wrap_' + client_id + class_string"
                style="padding: 20px;"
            >
                <div 
                    class="tableInsert event-list-card-wrapper"
                    style="overflow: scroll !important; scrollbar-width: 5px !important; flex-wrap: nowrap;"
                    :style="{ 'gap': formatting_obj.card_spacing ? Number(formatting_obj.card_spacing) + 'px' : '25px' }"
                >
                    <template v-for="(image, index) in images" :key="image.id">
                        <div
                            class="event-list-card noPadding noMargin" 
                            :class="{
                                'small-card-image-grid': formatting_obj.card_size == 'small',
                                'medium-card-image-grid': !formatting_obj.card_size || formatting_obj.card_size == 'medium',
                                'large-card-image-grid': formatting_obj.card_size == 'large',
                                'box-shadow-light': formatting_obj.box_shadow == 'light',
                                'box-shadow-dark': formatting_obj.box_shadow == 'dark',
                            }"
                            :style="{'border-radius': image_grid_border_radius + 'px' ||'0px' }"
                        >
                            <div 
                                v-if="image && image.url" 
                                class="image-grid-image relative" 
                                :class="'image-grid-image_' + image?.id"
                                :id="image?.id"
                            >
                                <!-- video -->
                                <div 
                                    v-if="image.is_video" 
                                    class="image-grid-event-image"
                                    style="align-items:center;display:flex;" 
                                    :style="{'border-radius': image_grid_border_radius + 'px' }"
                                >
                                    <video class="cs-background-video" autoplay playsinline loop muted :src="image.url" style="display:block;"></video>
                                </div>
                                <!-- image -->
                                <div 
                                    v-else
                                    class="image-grid-event-image"
                                    :style="{'background-image': 'url(' + image.url + ')', 'border-radius': image_grid_border_radius + 'px' }"
                                ></div>
                                <!-- overlay -->
                                <div 
                                    @click.stop
                                    v-if="is_admin" 
                                    class="image-grid-image-overlay flexWrap easeFast" 
                                    style="left:0px;right:0px;bottom:0px;top:0px"
                                    :style="{ 'background-color': returnRGBAStringForImageGridImageOverlayOpacity( image_grid_opacity ), 'border-radius': image_grid_border_radius + 'px' }"
                                >
                                    <div class="image-toolbar-wrapper flexNoWrap centeredBlock" @click.stop>
                                        <div 
                                            class="image-toolbar-option easeFast" 
                                            data-option="update" 
                                            style="border-right:1px solid #fff;" 
                                            @click.stop="prepThenDisplayImageSettings(image)"
                                        >Update</div>
                                        <div 
                                            class="image-toolbar-option easeFast" 
                                            data-option="remove" 
                                            @click.stop="tapped_remove_image(image)"
                                        ><i class="fa-regular fa-trash" style="font-size:14px;"></i></div>
                                    </div>
                                    <div v-if="formatting_obj.caption_align !== 'under'" class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                        <h2 
                                            v-if="image.caption"
                                            class="image-grid-image-caption"
                                            :style="{ 'font-size': caption_size + 'px', 'font-weight': caption_font_weight }"
                                        >{{ image.caption }}</h2>
                                        <p
                                            v-if="image.subtext"
                                            class="image-grid-image-caption marginTopFour"
                                            :style="{ 'font-size': subtext_size + 'px', 'font-weight': caption_font_weight }"
                                        >{{ image.subtext }}</p>
                                        <p
                                            v-if="image.link_label"
                                            class="image-grid-image-caption marginTopFour"
                                            style="text-decoration: underline;"
                                            :style="{ 'font-size': link_label_size + 'px', 'font-weight': caption_font_weight }"
                                        >{{ image.link_label }}</p>
                                    </div>
                                </div> 
                                <div v-if="!is_admin" class="image-grid-image-overlay flexWrap easeFast" style="left:0px;right:0px;bottom:0px;top:0px" :style="{ 'background-color': returnRGBAStringForImageGridImageOverlayOpacity( image_grid_opacity ), 'border-radius': image_grid_border_radius + 'px' }">
                                    <div v-if="formatting_obj.caption_align !== 'under'" class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                        <h2 
                                            v-if="image.caption"
                                            class="image-grid-image-caption"
                                            :style="{ 'font-size': caption_size + 'px', 'font-weight': caption_font_weight }"
                                        >{{ image.caption }}</h2>
                                        <p
                                            v-if="image.subtext"
                                            class="image-grid-image-caption marginTopFour"
                                            :style="{ 'font-size': subtext_size + 'px', 'font-weight': caption_font_weight }"
                                        >{{ image.subtext }}</p>
                                        <p
                                            v-if="image.link_label"
                                            class="image-grid-image-caption marginTopFour"
                                            style="text-decoration: underline;"
                                            :style="{ 'font-size': link_label_size + 'px', 'font-weight': caption_font_weight }"
                                        >
                                            <a
                                                v-if="image.link_to"
                                                class="absoluteA"
                                                :href="image.link_to"
                                                rel="noopener noreferrer"
                                            >{{ image.link_label }}</a>
                                        </p>
                                        <a
                                            v-if="image.link_to"
                                            class="absoluteA"
                                            :href="image.link_to"
                                            rel="noopener noreferrer"
                                        ></a>
                                    </div>
                                </div> 
                            </div>
                            <div 
                                v-if="formatting_obj.caption_align === 'under'"
                                class="image-grid-card-content background"
                                :style="{'border-radius': image_grid_border_radius + 'px' ||'0px' }"
                            >
                                <div class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                    <h2 
                                        v-if="image.caption"
                                        class="image-grid-image-caption visible"
                                        :style="{ 'font-size': caption_size + 'px', 'font-weight': caption_font_weight }"
                                    >{{ image.caption }}</h2>
                                    <p
                                        v-if="image.subtext"
                                        class="image-grid-image-caption visible marginTopFour"
                                        :style="{ 'font-size': subtext_size + 'px', 'font-weight': caption_font_weight }"
                                    >{{ image.subtext }}</p>
                                    <p
                                        v-if="image.link_label"
                                        class="image-grid-image-caption visible marginTopFour"
                                        style="text-decoration: underline;"
                                        :style="{ 'font-size': link_label_size + 'px', 'font-weight': caption_font_weight }"
                                    >{{ image.link_label }}</p>
                                </div>
                            </div>
                        </div>
                    </template>
                    <!-- upload image **for admin -->
                    <template v-if="is_admin">
                        <div 
                            class="event-list-card pointer" 
                            :class="{
                                'small-card-image-grid': formatting_obj.card_size == 'small',
                                'medium-card-image-grid': !formatting_obj.card_size || formatting_obj.card_size == 'medium',
                                'large-card-image-grid': formatting_obj.card_size == 'large',
                            }"
                        >
                            <div class="image-grid-image relative upload-image-grid-image-zone">
                                <div class="image-grid-event-image"></div>
                                <input 
                                    @change="imageUploadChange($event)"
                                    class="image-grid-upload-input absoluteInput" 
                                    type="file" accept="image/*,video/*"
                                >
                                <p class="centeredBlock" style="font-family:roboto !important;">+ Upload image/video</p>
                                <!-- <div class="uploadImageOverlay">
                                    <div class="uploadImageSpinner centeredBlock"></div>
                                </div> -->
                            </div>
                            <div 
                                v-if="formatting_obj.caption_align === 'under'"
                                class="image-grid-card-content"
                                :style="{'border-radius': image_grid_border_radius + 'px' ||'0px' }"
                            >
                                <div class="image-text-wrapper" :style="{ alignItems: text_position === 'start' ? 'flex-start' : text_position === 'center' ? 'center' : 'flex-end' }">
                                    <!-- PLACEHOLDER -->
                                </div>
                            </div>
                        </div>
                    </template>
                </div>
            </div>
        </div>
    </template>
</script>

<style>
    .image-grid-image.dragging{
        overflow: hidden;
        border-radius: 10px;
    }
    .image-grid-image.dragging .image-grid-image-inner {
        transition: all 0.35s ease-in-out;
        border: 1.2px solid #fff;
        border-radius: 10px;
        z-index: 1000;
        transform: scale(1.1);
        cursor: grab;
        cursor: move;
    }
    .image-grid-image.dragging .image-grid-drag-handle-wrap {
        display: none;
        position: relative;
    }
    .event-list-card {
        overflow: hidden;
        background: white;
        font-family: 'Inter', sans-serif;
        display: flex;
        flex-direction: column;
        flex: 0 0 auto;
        transition: transform 0.1s ease;
    }
    .event-list-card.small-card-image-grid {
        width: 190px;
    }
    .event-list-card.medium-card-image-grid {
        width: 230px;
    }
    .event-list-card.large-card-image-grid {
        width: 300px;
    }
    .event-list-card.box-shadow-light {
        box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2);
    }
    .event-list-card.box-shadow-dark {
        box-shadow: 6px 6px 16px rgba(0, 0, 0, 0.2);
    }
    .event-list-card .image-grid-event-image {
        display: flex;
        text-align: center;
        align-items: center;
        width: 100%;
        height: 100%;
        background-size: cover;
        background-repeat: no-repeat;
        background-position: center;
        color: #fff;
        position: absolute;
    }
    .image-grid-card-content {
        height: 100px;
        padding: 12px 5px;
    }
    .upload-image-grid-image-zone{
        color: #323d63;
        text-align: center;
        border-radius: 2px;
        background-color: #f1f5f9;
        position: relative;
        display: flex;
        align-items: center;
    }
</style>

<script>

    app_content.component("image-grid-component", {
        template: "#template-image-grid",
        data() {
            return {
                global: store,
                loading: false,
            };
        },
        props: {
            client_id: String,
            class_string: String,
            image_grid_layout: String,
            images_per_row: [String, Number],
            caption_size: String,
            subtext_size: String,
            link_label_size: String,
            text_position: String,
            caption_font_weight: String,
            image_grid_opacity: String,
            images_string: String,
            image_grid_border_radius: String,
            // carousel
            formatting: String,
            // admin
            is_admin: false,
            data_source_type: String,
            images_arr: Array,
            component: Object,
            last_update: Number,
        },
        mounted() {
            this.$nextTick(() => {
                if (this.is_admin && this.images_arr){
                    this.makeElementsSortable_image_grid();
                }
            })
        },
        methods: {
            makeElementsSortable_image_grid(){
                //now create the new instance
                const containerSelector = `.draggable-container_image_grid_${this.component.id}`;
                const containers = document.querySelectorAll(containerSelector);
                if (containers?.length === 0) {
                    return false;
                }
                const sortable = new Draggable.Sortable(containers, {
                    draggable: '.image-grid-image:not(.non-draggable)',
                    handle: '.draggable-handle',
                });
                //now register listeners
                sortable.on('sortable:start', event => {
                    var target = event.data.dragEvent.source;
                    target.classList.add('dragging');
                });
                sortable.on('sortable:stop', event => {
                    var target = event.data.dragEvent.source;
                    target.classList.remove('dragging');
                    //now handle ui updates inside a timeout due to a draggable library issue (https://github.com/Shopify/draggable/issues/92)
                    setTimeout(() => {  
                        this.handle_sortable_stop( event );
                    }, 0)
                });
            },
            handle_sortable_stop( event ){
                let targetId = event.data.dragEvent.source.id;
                let dropElement = document.getElementById(targetId);
                var reordered_ids = Array.from(event.newContainer.children).map(event => event.id);
                reordered_ids.pop(); //pop off last value which is an empty string placeholder for image upload
                var reordered_images = [];
                reordered_ids.forEach(image_id => {
                    //find the image 
                    var this_image = null;
                    this.images.forEach(image => {
                        if( image.id == image_id ){
                            this_image = image
                        }
                    });
                    if( this_image ){
                        reordered_images.push( this_image );
                    }
                });
                //save changes
                save_changes_for_component( this.component, 'images', reordered_images );
            },
            returnRGBAStringForImageGridImageOverlayOpacity( opacity ){
                if( ! opacity && opacity !== 0 ){
                    opacity = 40;
                }
                return "rgba(8,8,19,"+ opacity / 100 +")";
            },
            confirmed_remove_image( data ){
                var image = data.image;
                var component = data.component;
                //find existing images
                var images = component.get('config_latest').images || [];
                //loop through to remove this one
                var new_images = [];
                for (var i = 0; i <= images?.length - 1; i++) {
                    if( images[i].id !== image.id ){
                        new_images.push( images[i] );
                    }
                }
                //now save and update the preview
                save_changes_for_component( component, 'images', new_images );
                store.overlays.are_you_sure = false;
            },
            tapped_remove_image( image ){
                //ask for confirmation
                var params = {};
                params["fn"] = this.confirmed_remove_image;                
                params["title"] = "Remove image";
                params["subtext"] = "Are you sure you want to permanently remove this tile from the image grid?";
                params["button_label"] = "Remove";
                params["data"] = {
                    "image": image,
                    "component": this.component
                };
                are_you_sure( params );
                return
            },
            prepThenDisplayImageSettings(imageObject){
                store.components.image_settings_overlay.componentObject = this.component;
                store.components.image_settings_overlay.imageObject = imageObject;
                store.components.image_settings_overlay.settings = {
                    link_input: imageObject.link_to  || '',
                    caption_input: imageObject.caption || '',
                    subtext_input: imageObject.subtext || '',
                    link_label_input: imageObject.link_label || '',
                }
                store.components.image_settings_overlay.image_grid_props = {
                    client_id: this.client_id,
                    caption_size: this.caption_size,
                    caption_font_weight: this.caption_font_weight,
                };
                this.global.overlays.image_settings_overlay = !this.global.overlays.image_settings_overlay;
                this.$nextTick(() => {
                    this.updatePositionForImageSettings( imageObject );
                });
            },
            updatePositionForImageSettings(imageObject){
                var image_object = imageObject;
                if( ! image_object ){
                    return
                }
                var element = $(".image-grid-image_" + image_object.id);
                if( ! element ){
                    return
                }
                var offset = element.offset();
                var top = offset.top;
                var bottom = top + element.height();
                var correct_top = top - ( $('.image-settings').height() + 25 );
                store.components.image_settings_overlay.position = {
                    top: `${correct_top}px`,
                    left: `${offset.left}px`
                };
            },
            imageUploadChange($event){
                var file = event.target.files[0];
                var componentObject = this.component;
                if(file && componentObject){
                    //update the ui
                    $(this).parents('.uploadImageZone').addClass('loading');
                    //set attributes
                    var type = 'image_grid';
                    var timestamp = Date.now();
                    //check the file type
                    var is_video = this.returnIsVideo( file['name'] ) || false;
                    if( is_video ){
                        //ok, it's a video
                        //.. handle the video
                        var file_name = componentObject.get('client_id')+"_grid_video_"+timestamp;
                        return uploadFileToAWSV2( file, file_name ).then(( url )=>{
                            this.handleUploadedImageGridImage( url, componentObject, true );
                        });
                    }else{
                        //assume it's an image!
                        var file_name = componentObject.get('client_id')+"_grid_image_"+timestamp;
                        //handle the image
                        loadCleanImage(file, this.handleCleanImage_image_grid, type, file_name, componentObject.get('client_id') );
                    }
                }
                //reset input value to detect change if same file is uploaded
                event.target.value = '';
            },
            returnIsVideo(filename) {
                var ext = this.getExtension(filename);
                switch (ext.toLowerCase()) {
                    case 'm4v':
                    case 'avi':
                    case 'mpg':
                    case 'mp4':
                    case 'mp3':
                    case 'mov':
                    // etc
                    return true;
                }
                return false;
            },
            getExtension(filename) {
                var parts = filename.split('.');
                return parts[parts?.length - 1];
            },
            completed_crop(params){
                const { fileType, is_video, file_name, blob, componentObject } = params;
                //upload it
                return uploadFileToAWSV2( blob, file_name ).then(( url )=>{
                    this.handleUploadedImageGridImage( url, componentObject, is_video );
                });
            },
            handleCleanImage_image_grid( canvas, type, file_name, componentID, image_index, is_video, fileType ){
                $('body').data('can', canvas);
                let componentObject = this.component;
                if(!fileType) {
                    fileType = 'image/jpeg'
                }
                var url = canvas.toDataURL(fileType);
                var params = {};
                params["url"] = url;
                params["fn"] = this.completed_crop;
                params["componentID"] = componentID;
                params["fileType"] = fileType;
                params["is_video"] = is_video || false;
                params["file_name"] = file_name;
                params["componentObject"] = componentObject;
                launch_image_cropper( params );
            },
            handleUploadedImageGridImage(url, componentObject, is_video){
                if( componentObject ){
                    //it's still in the dom
                    //.. update it
                    var images = componentObject.get('config_latest')?.images || [];
                    images.push({
                        "id": generateClientID(),
                        "url": url, 
                        "is_video": is_video
                    });
                    save_changes_for_component( this.component, 'images', images );
                    //store.eventBus.$emit('saveChangesForComponent', this.component, option, value)
                    //message
                    if( is_video ){
                        displayMessage("Video uploaded. It may take a moment for your video to appear.", false, 5000);
                    }else{
                        displayMessage("Image uploaded.", false, 3000);
                    }
                }
            },
        },
        computed: {
            images(){
                if (!this.is_admin && this.images_string){
                    try {
                        const parsedObject = JSON.parse(this.images_string);
                        return parsedObject
                    } catch (error) {
                        console.error('Error parsing JSON: ', error)
                    }
                } else if (this.is_admin && this.images_arr){
                    return this.images_arr || [];
                }
            },
            formatting_obj(){
                if (this.formatting){
                    return JSON.parse(this.formatting);
                }
                return {};
            },
        },
    })

</script>    <script type="text/html" id="template-photo-gallery">
    <div class="photo-gallery-wrap centeredBlock centeredText">
        <!-- hosted site -->
        <div v-if="!loading && !is_admin">
            <div 
                v-if="photo_album_id && json_photos"
                class="photo-gallery"
            >
                <div 
                    v-for="(photo, index) in json_photos" 
                    class="photo-container" 
                    :id="photo.id"
                    @click="clicked_gallery_photo( index )"
                    :style="calculate_container_dimensions()"
                >
                    <video v-if="photo && returnIsVideo(photo.file_name)" class="video-cover paddingTop" autoplay muted loop playsinline>
                        <source :src="photo.url" type="video/mp4">
                    </video>
                    <div 
                        v-else-if="photo && photo.url" 
                        class="photo-cover"
                        :style="'background-image:url('+encodeURI(photo.url)+')'"
                    ></div>
                    <!-- overlay -->
                    <div class="photo-overlay"></div>
                </div>
            </div>
        </div>
        <!-- admin -->
        <div v-if="!loading && is_admin">
            <div
                v-if="!photo_album_id"
                @click="link_photo_album()"
                class="noObjectsMSG centeredBlock centeredText"
                style="padding: 5em;"
            >
                <p style="cursor: pointer; font-family: 'Roboto', 'Arial' !important;"><i class="fa-light fa-images smallMarginRight"></i>Click to link a photo album</p>
            </div>
            <div 
                v-else-if="photo_album_id && json_photos"
                class="photo-gallery"
            >
                <div 
                    v-for="(photo, index) in json_photos" 
                    class="photo-container" 
                    :id="photo.id"
                    @click="clicked_gallery_photo( index )"
                    :style="calculate_container_dimensions()"
                >
                    <video v-if="photo && returnIsVideo(photo.file_name)" class="video-cover paddingTop" autoplay muted loop playsinline>
                        <source :src="photo.url" type="video/mp4">
                    </video>
                    <div 
                        v-else-if="photo && photo.url" 
                        class="photo-cover"
                        :style="'background-image:url('+encodeURI(photo.url)+')'"
                    ></div>
                    <!-- overlay -->
                    <div class="photo-overlay"></div>
                </div>
            </div>
        </div>
    </div>
</script>

<style>
    .photo-gallery-wrap{
        height: fit-content;
        width: 100%;
    }
    .photo-gallery{
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: flex-start; /* center for mobile */
    }
    .photo-container {
        position: relative;
        box-sizing: border-box;
        margin: 0.3em;
        text-align: center;
    }
    .photo-container .video-cover {
        width: 100%;
        object-fit: cover;
    }
    .photo-container > .photo-cover {
        height: 100%;
        width: inherit;
        display: block;
        overflow: hidden;
        margin: 0 auto;
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        opacity: 1;
    }
    .photo-overlay{
        position: absolute;
        display: flex;
        align-items: center;
        justify-content: center;
        top: 0;
        left: 0;
        height: 100%;
        width: 100%;
        opacity: 0;
        background-color: rgba(8,8,19,0.3);
        transition: opacity 0.2s ease-out;
    }
    .photo-container:hover .photo-overlay {
        cursor: pointer;
        opacity: 0.8 !important;
    }
</style>

<script>

    app_content.component("photo-gallery-component", {
        template: "#template-photo-gallery",
        data() {
            return {
                global: store,
                loading: false,
                json_photos: [],
            };
        },
        props: {
            client_id: String,
            is_admin: Boolean,
            component: Object,
            last_update: Number,
            photo_album: [String, Object],
            show_caption: Boolean,
            caption_size: Number,
            caption_font_weight: Number,
            photos_per_row: Number,
        },
        mounted() {
            this.load_photo_albums( this.client_id );
        },
        methods: {
            calculate_container_dimensions(){
                const percentage = 100 / this.photos_per_row;
                const isMobile = window.innerWidth <= 600;
                if ( isMobile ){
                    return {
                        flex: `1 1 calc(${percentage}% - 0.6em)`,
                        maxWidth: `calc(${percentage}% - 0.6em)`,
                        height: `calc(${100}px * (${percentage} / 100) * 2.5)`,
                    };
                }
                return {
                    flex: `1 1 calc(${percentage}% - 0.6em)`,
                    maxWidth: `calc(${percentage}% - 0.6em)`,
                    height: `calc(${500}px * (${percentage} / 100) * 2.5)`,
                };
            },
            load_photo_albums( client_id, overrides = {} ){
                this.loading = true;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    var params = {};
                    params["client_id"] = client_id;
                    params["photo_album_id"] = this.photo_album_id;
                    params["overrides"] = overrides;
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(retrieved_photos => {
                    this.json_photos = retrieved_photos;
                    return Parse.Promise.as();
                }).then(() => {
                    this.loading = false;
                }, error => {
                    checkParseError(error);
                    this.loading = false;
                });
                return thisPromise;
            },
            clicked_gallery_photo( index ){
                store.components.view_photo_carousel.json_photos = this.json_photos;
                store.components.view_photo_carousel.current_index = index;
                store.components.view_photo_carousel.json_config = {
                    show_caption: this.show_caption || false,
                    caption_size: this.caption_size || 16,
                    caption_font_weight: this.caption_font_weight || 400,
                };
                store.overlays.view_photo_carousel = true;
            },
            link_photo_album(){
                store.components.link_photo_album.component = this.component;
                store.components.link_photo_album.last_update = this.last_update;
                store.overlays.link_photo_album = true;
            },
            returnIsVideo(filename) {
                var ext = this.getExtension(filename);
                switch (ext.toLowerCase()) {
                    case 'm4v':
                    case 'avi':
                    case 'mpg':
                    case 'mp4':
                    case 'mp3':
                    case 'mov':
                    // etc
                    return true;
                }
                return false;
            },
            getExtension(filename) {
                var parts = filename.split('.');
                return parts[parts.length - 1];
            },
        },
        computed: {
            photo_album_obj(){
                if (this.photo_album && typeof this.photo_album === 'string'){
                    return JSON.parse(unescape(decodeURIComponent(this.photo_album)));
                } else if (this.photo_album){
                    return this.photo_album;
                } 
                return;
            },
            photo_album_id(){
                return this.photo_album_obj.id || null;
            },
            photo_album_name(){
                return this.photo_album_obj.name || null;
            },
        },
        watch: {
            last_update(newVal, oldVal){
                if (newVal !== oldVal){
                    this.load_photo_albums( this.client_id );
                }
            }
        }
    })

</script>    <script type="text/html" id="template-membership-calendar">
    <!-- calendar grid component -->
    <calendar-grid-component
        v-if="loadCalendarGrid"
        :client_id="client_id"
        :class_string="class_string"
        :style_string="style_string"
        :filterOptions="filterOptions"
        :schedules="schedules"
        :selectedFilterOptions="selectedFilterOptions"
        :is_membership_cal="is_membership_cal"
        @handleFilterSelection="handleFilterSelection"
        @load_cal="load_membership_cal"
        @createSchedule="createSchedule"
        @clickSchedule="clickSchedule"
        ref="calendarComponentRef"
    >
    </calendar-grid-component>
    <!-- spinner -->
    <div v-if="!loadCalendarGrid" class="cardBodySpinnerWrap relative active marginTop">
        <div class="cardBodySpinner centeredBlock"></div>
    </div>
</script>

<script>    
    /* ----- STORE ----- */
    store.components['membership_cal'] = {
        clubId: null,
        // client_id: 'primary',
        filterOptions: [],
        events: [],
        recurringEvents: [],
        schedules: [],
        loadCalendarGrid: false,
        selectedFilterOptions: [ 'all' ],
        is_admin: false,
        is_membership_cal: true,
        config_obj: {},
    };
    /* ----- COMPONENT ----- */
    app_content.component('membership-calendar-component', {
        template: '#template-membership-calendar',
        data() {
            return store.components['membership_cal'];
        },
        props: {
            config: String,
            client_id: String,
            class_string: String,
            style_string: String,
            //admin
            component: Object,
            last_update: Number,
        },
        mounted() {
            if (this.config){
                this.config_obj = JSON.parse(this.config);
            }
            this.clubId = $('body').data('club-id'); 
            this.load_membership_cal(this.client_id);
            this.is_admin = window.location.href.indexOf('website-builder') !== -1;
            this.checkThenHandleEventTagsForCalendar(this.client_id);
            //eventBus for overflow-overlay
            store.eventBus.$on('clickSchedule_membership_cal', (event) => {
                this.clickSchedule(event)
            })
        },
        created() {
            if(store.components.calendar_grid.view_preference !== 'Month') {
                this.loadCalendarGrid = false;            
                this.setViewPreference();
            }
            store.components.calendar_grid.currentDate = dayjs() || new Date();
        },
        methods: {
            async setViewPreference() {
                store.components.calendar_grid.view_preference = 'Month';
            },
            checkThenHandleEventTagsForCalendar(client_id) {
                //see if we should get tags, or if we already have them
                var event_tags = $(`.cs-calendar-wrap_${ client_id }`).data('event_tags');
                if(! event_tags) {
                    var club_id = $('body').data('club-id');
                    if(! club_id && $('body').data('clubObject')) {
                        club_id = $('body').data('clubObject').id;
                    }
                    //ok, we should query for them
                    var query = new Parse.Query('event_tags');
                    query.equalTo('clubObject', {
                        __type: 'Pointer',
                        objectId: club_id,
                        className: 'clubs'
                    });
                    query.equalTo('archived', false);
                    query.ascending('name');
                    query.find().then(retrieved_tags => {
                        $(`.cs-calendar-wrap_${ client_id }`).data('event_tags', retrieved_tags);
                        // $('.cs-calendar-wrap_'+ client_id).find('.insert_event_tags').html('');
                        // $('.cs-calendar-wrap_'+ client_id).find('.insert_event_tags').append('<div class="cs-tab-bar-option cs-tab-bar-option_event_tags cs-tab-bar-option_event_tags_all mobile-order active" data-option="all">All events</div>');
                        //plug them in
                        this.filterOptions = [{ id: 'all' }, ...retrieved_tags ].map((tag, i) => {
                            if(i === 0) {
                                return {
                                    name: 'All events',
                                    data_option: tag.id
                                };
                            } else {
                                return {
                                    name: tag.get('name'),
                                    data_option: tag.id
                                };
                            }
                        });
                    });
                }
            },
            load_membership_cal(client_id) {
                this.loadCalendarGrid = false;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    //get data
                    var { startTimestamp, endTimestamp } = this.getRenderRangeForWebBuilderCalendar();
                    var params = {};
                    params['startTimestamp'] = startTimestamp;
                    params['endTimestamp'] = endTimestamp;
                    if(this.is_admin || $(`#componentPreview_${ this.client_id }`).data('componentObject')) {
                        // var calendarComponentObject = $(`#componentPreview_${ this.client_id }`).data('componentObject');
                        // let event_types = this.component?.get('config_latest').event_types || []; /* returnEventTypesForComponent(calendarComponentObject); */
                        let event_types = this.event_types;
                        params['filters'] = event_types.length > 0 ? event_types : null;
                    } else {
                        // let event_types = this.config_obj.event_types;
                        let event_types = this.event_types;
                        params['filters'] = event_types?.length ? [...event_types] : null;
                        //set filters on server
                        params['client_id'] = this.client_id;
                    }
                    params['club_id'] = this.clubId;
                    // filtering logic
                    var event_tag_id = this.selectedFilterOptions;
                    if(this.selectedFilterOptions.indexOf('all') === -1) {
                        params['event_tag_id'] = event_tag_id[0];
                    }
                    return Parse.Cloud.run('retrieve_events_for_primary_calendar_v2', params);
                }).then((foundEventsJSON) => {
                    events = foundEventsJSON.events;
                    var socialEvents = events.filter(e => e.className == 'events');
                    var recurringEvents = this.formatRecurringCalendarEvents(foundEventsJSON.recurring_events, socialEvents);
                    $('body').data('recurringCalendarEvents', recurringEvents);
                    //vue
                    this.events = events;
                    this.recurringEvents = recurringEvents;
                    return Parse.Promise.as();
                }).then(() => {
                    this.pluginEvents();
                    this.loadCalendarGrid = true;
                    this.$nextTick(() => {
                        this.$refs.calendarComponentRef.calculateTitleRange(); //ref on child component
                        this.$refs.calendarComponentRef.generateCalendar(); //ref on child component
                    });
                    //and return
                    return Parse.Promise.as();
                });
                return thisPromise;
            },
            getRenderRangeForWebBuilderCalendar() {
                // var client_id = $('.cs-calendar-wrap').data('client-id');
                // var calendar = $('.cs-calendar-wrap_'+client_id).data('calendar');
                var calendarDate = store.components.calendar_grid.currentDate ? new Date(new Date(store.components.calendar_grid.currentDate).setHours(0, 0, 0, 0)) : new Date(new Date().setHours(0, 0, 0, 0));
                var calendarMonth = calendarDate.getMonth();
                var startTimestamp = new Date(calendarDate).setMonth(calendarMonth - 1, 15);
                var endTimestamp = new Date(calendarDate).setMonth(calendarMonth + 1, 15);
                return { startTimestamp, endTimestamp };
            },
            formatRecurringCalendarEvents(recurringEvents, socialObjects) {
                var recurringCalendarEvents = [];
                for(var i = 0; i < recurringEvents.length; i++) {
                    var thisEventObject = recurringEvents[i];
                    var socialObject = socialObjects.filter(s => s.id == thisEventObject.raw.eventObject)[0];
                    var correctedTs = thisEventObject.ts; //to handle daylight savings
                    if(new Date(thisEventObject.ts).getHours() == 23) {
                        correctedTs += 1000 * 60 * 60;
                    } else if(new Date(thisEventObject.ts).getHours() == 1) {
                        correctedTs -= 1000 * 60 * 60;
                    }
                    thisEventObject.ts = correctedTs;
                    var startTs = new Date(thisEventObject.ts).setHours(thisEventObject.hours_mins_start.hours, thisEventObject.hours_mins_start.minutes, 0, 0);
                    var endTs = new Date(thisEventObject.ts).setHours(thisEventObject.hours_mins_end.hours, thisEventObject.hours_mins_end.minutes, 0, 0);
                    thisEventObject['start'] = new Date(startTs).toISOString();
                    thisEventObject['end'] = new Date(endTs).toISOString();
                    var color = '#e8edf1'; //default
                    var dot_color = null;
                    var event_tags = socialObject.get('event_tags');
                    if(event_tags) {
                        for(var t = 0; t <= event_tags.length - 1; t++) {
                            if(! event_tags[t].get('archived')) {
                                if(event_tags[t].get('hex_value')) {
                                    color = event_tags[t].get('hex_value');
                                    thisEventObject['color'] = '#ffffff';
                                    dot_color = event_tags[t].get('hex_value');
                                }
                            }
                        }
                    }
                    thisEventObject['bgColor'] = color;
                    thisEventObject['recurring'] = true;
                    thisEventObject['external_event_url'] = socialObject.get('external_event_url');
                    thisEventObject['description'] = socialObject.get('description');
                    // //add
                    // thisEventObject["className"] = socialObject.className;
                    if(dot_color && thisEventObject.raw) {
                        thisEventObject.raw.dot_color = dot_color;
                    } else if(dot_color && !thisEventObject.raw) {
                        thisEventObject.raw = { dot_color };
                    }
                    var isAllDay = socialObject.get('all_day');
                    if(isAllDay) {
                        thisEventObject.title = socialObject.get('name');
                    }
                    thisEventObject.isAllDay = isAllDay;
                    recurringCalendarEvents.push(thisEventObject);
                }
                return recurringCalendarEvents;
            },
            pluginEvents() {
                var schedules = this.recurringEvents || [];
                for(var i = 0; i <= this.events.length - 1; i++) {
                    var this_event = this.events[i];
                    var this_start_date = this_event.get('startDate');
                    if(this_start_date) {
                        var this_end_date = this_event.get('endDate');
                        if(this_end_date) {
                            if(! this_event.get('endTime')) {
                                this_end_date.setDate(this_end_date.getDate() + 1);
                            }
                        } else {
                            this_end_date = this_start_date;
                        }
                        //convert start/end dates from utc to browser date
                        this_start_date = returnOffsetDateForUTCDate(this_start_date);
                        this_end_date = returnOffsetDateForUTCDate(this_end_date);
                        //handle start/end times set explicitly on the event
                        if(this_event.get('startTime') && this_event.get('endTime')) {
                            var start_data = returnHoursAndMinutesForMilitaryTime(this_event.get('startTime'));
                            this_start_date.setHours(this_start_date.getHours() + start_data.hours);
                            this_start_date.setMinutes(this_start_date.getMinutes() + start_data.minutes);
                            var end_data = returnHoursAndMinutesForMilitaryTime(this_event.get('endTime'));
                            this_end_date.setHours(this_end_date.getHours() + end_data.hours);
                            this_end_date.setMinutes(this_end_date.getMinutes() + end_data.minutes);
                        }
                        var seconds = (this_end_date.getTime() - this_start_date.getTime()) / 1000;
                        //continue
                        var this_object = {};
                        this_object['id'] = this_event.id;
                        this_object['calendarId'] = this.client_id;
                        //add
                        this_object['className'] = this_event.className;
                        this_object['calendarOnly'] = this_event.get('calendarOnly');

                        this_object["raw"] = {};
                        //the code below is to account for all day events (only single day) on dates where there is a dls change
                        //START DLS LOGIC
                        var start_offset = this_start_date.getTimezoneOffset();
                        var end_offset = this_end_date.getTimezoneOffset();
                        var hasEndTime = this_event.get('endTime');
                        var is_dls_all_day = false;
                        if(start_offset != end_offset && seconds <= 93600) {
                            //ok its an all day event for just a particular day where the offset is changing (dls)
                            //dont need to change the endDate for objects with an endTime as those will be correctly set already
                            if(start_offset > end_offset && !hasEndTime) {
                                this_end_date = new Date(new Date(this_end_date).setHours(this_end_date.getHours() + 1, 0, 0, 0));
                            } else if(start_offset < end_offset && !hasEndTime) {
                                this_end_date = new Date(new Date(this_end_date).setHours(this_end_date.getHours() - 1, 0, 0, 0));
                            }
                            is_dls_all_day = true;
                        }
                        //END DLS LOGIC
                        if( this_start_date.getTime() == this_end_date.getTime() || seconds == 86400 || is_dls_all_day){
                            this_object["category"] = "allday";
                            this_object["isAllDay"] = true;
                            this_object["title"] = this_event.get('name');
                        }else{
                            this_object["category"] = "time";
                            this_object["isAllDay"] = false;
                            this_object["title"] = this_event.get('name');
                            if( seconds < 86400 ){
                                var nice_time = formatHoursAndMinutesForDate( this_start_date );
                                this_object.raw.nice_time = nice_time;
                            }
                        }
                        //check event type
                        if(this_event.className == 'regattas' || this_event.className == 'subevents') {
                            /*
                            this_object['bgColor'] = '#87d4f9';
                            this_object.raw.dot_color = '#87d4f9';
                            */
                            var bgColor = "#87d4f9"; //default
                            var dot_color = "#87d4f9";
                            var event_tags;
                            if ( this_event.className === "regattas" ){
                                event_tags = this_event.get('event_tags');
                            } else if ( this_event.className === "subevents" && this_event.get('regattaObject') ){
                                event_tags = this_event.get('regattaObject').get('event_tags');
                            }
                            if( event_tags ){
                                event_tags.forEach(event_tag => {
                                    if ( ! event_tag.get('archived') ){
                                        bgColor = event_tag.get('hex_value');
                                        dot_color = event_tag.get('hex_value');
                                    }
                                })
                            }
                            this_object["bgColor"] = bgColor;
                            this_object.raw.dot_color = bgColor;
                        } else if(this_event.className == 'camps') {
                            /*
                            this_object['bgColor'] = '#236651';
                            this_object.raw.dot_color = '#236651';
                            this_object['color'] = '#ffffff';
                            */
                            var bgColor = "#236651"; //default
                            var dot_color = "#236651";
                            var event_tags = this_event.get('event_tags');
                            if( event_tags ){
                                event_tags.forEach(event_tag => {
                                    if ( ! event_tag.get('archived') ){
                                        bgColor = event_tag.get('hex_value');
                                        dot_color = event_tag.get('hex_value');
                                    }
                                })
                            }
                            this_object["bgColor"] = bgColor;
                            this_object.raw.dot_color = bgColor;
                            this_object["color"] = "#ffffff";
                        } else {
                            var color = '#e8edf1'; //default
                            var dot_color = null;
                            var event_tags = this_event.get('event_tags');
                            if(event_tags) {
                                for(var t = 0; t <= event_tags.length - 1; t++) {
                                    if(! event_tags[t].get('archived')) {
                                        if(event_tags[t].get('hex_value')) {
                                            color = event_tags[t].get('hex_value');
                                            this_object['color'] = '#ffffff';
                                            dot_color = event_tags[t].get('hex_value');
                                        }
                                    }
                                }
                            }
                            this_object['bgColor'] = color;
                            this_object.raw.dot_color = dot_color;
                        }
                        //set dates
                        // this_object['start'] = this_start_date.toISOString();
                        // this_object['end'] = this_end_date.toISOString();
                        if(this_event.className == 'regattas' || this_event.className == "subevents" && this_event.get('startDate') && this_event.get('endDate')) {
                            var clubObject = this_event.get('clubObject');
                            var start_date_params = {timezone: clubObject.get('timezone'), date: this_event.get('startDate')};
                            var end_date_params = {timezone: clubObject.get('timezone'), date: this_event.get('endDate')};
                            var start_time_components_at_club = this.return_date_components_v2(start_date_params);
                            var end_time_components_at_club = this.return_date_components_v2(end_date_params);
                            this_object["start"] = new Date(start_time_components_at_club.year, start_time_components_at_club.month, start_time_components_at_club.date).toISOString();
                            this_object["end"] = new Date(end_time_components_at_club.year, end_time_components_at_club.month, end_time_components_at_club.date).toISOString();
                        } else {
                            this_object["start"] = this_start_date.toISOString();
                            this_object["end"] = this_end_date.toISOString();
                        }
                        //push it if not recurring (handled already)
                        if(!this_event.get('recurring_event')) {
                            schedules.push(this_object);
                        }
                    }
                }
                // this.schedules = schedules;
                // this.schedules = schedules.sort((a, b) => { return dayjs(a.start).isBefore(dayjs(b.start)) ? -1 : 1 });
                this.schedules = schedules.sort((a, b) => {
                    if(
                        !dayjs(a.start).isSame(dayjs(a.end), 'day') &&
                            !dayjs(b.start).isSame(dayjs(b.end), 'day')
                    ) {
                        //both schedules have different start and end dates, compare them
                        return dayjs(a.start).isBefore(dayjs(b.start)) ? -1 : 1;
                    } else if(!dayjs(a.start).isSame(dayjs(a.end), 'day')) {
                        //only schedule a has different start and end dates, so it comes first
                        return -1;
                    } else if(!dayjs(b.start).isSame(dayjs(b.end), 'day')) {
                        //only schedule b has different start and end dates, so it comes first
                        return 1;
                    } else {
                        //both schedules have the same start and end dates, compare them
                        return dayjs(a.start).isBefore(dayjs(b.start)) ? -1 : 1;
                    }
                });
            },
            handleFilterSelection(optionObject) {
                store.components.calendar_grid.loading = true;
                this.selectedFilterOptions = [ optionObject.data_option ];
                return this.load_membership_cal();
            },
            clickSchedule(event) {
                if(! this.is_admin) {
                    var is_recurring_event = event.recurring;
                    // open detail view
                    var this_event = returnObjectByID(event.id, this.events);
                    if(is_recurring_event) {
                        var { external_event_url, description, title, start, end, ts } = event;
                        if(external_event_url) {
                            //its external, just pop open the window
                            return window.open(external_event_url);
                        }
                        $('#overlay_event-description-popup h3').text(title);
                        $('#overlay_event-description-popup .metric_start_date').text(formatUTCDate(new Date(ts), true, false, true));
                        var start_date_time_string = formatTimestampDate(new Date(start)).split(', ')[1];
                        if(end) {
                            start_date_time_string += ` - ${ formatTimestampDate(new Date(end)).split(', ')[1] }`;
                        }
                        $('#overlay_event-description-popup .metric_start_date_time').text(start_date_time_string);
                        if(event.description) {
                            $('#overlay_event-description-popup .metric_description').text(event.description).removeClass('incomplete');
                        } else {
                            $('#overlay_event-description-popup .metric_description').text('Not provided').addClass('incomplete');
                        }
                        fadeIn('#overlay_event-description-popup');
                    } else if(this_event) {
                        if(this_event.className == 'regattas') {
                            if(this_event.get('regatta_external') && this_event.get('external_regatta_url')) {
                                window.open(this_event.get('external_regatta_url'));
                            } else {
                                window.open(`/regatta/${ this_event.id }`);
                            }
                        } else if(this_event.className == 'subevents') {
                            //go to microsite
                            var regattaObject = this_event.get('regattaObject');
                            window.open(`/regatta/${ regattaObject.id }`);
                        } else if(this_event.className == 'events') {
                            if(this_event.get('external_event') && this_event.get('external_event_url')) {
                                window.open(this_event.get('external_event_url'));
                            } else if(! this_event.get('calendarOnly')) {
                                window.open(`/event/${ this_event.id }`);
                            } else {
                                $('#overlay_event-description-popup h3').text(this_event.get('name'));
                                if(is_recurring_event) {
                                    $('#overlay_event-description-popup .metric_start_date').text(formatUTCDate(new Date(this_event.start), true, false, true));
                                } else {
                                    $('#overlay_event-description-popup .metric_start_date').text(formatUTCDate(this_event.get('startDate'), true, false, true));
                                }
                                var startTime = this_event.get('startTime');
                                var endTime = this_event.get('endTime');
                                var startTime_hours_mins = returnHoursAndMinutesForMilitaryTime(startTime);
                                var endTime_hours_mins = returnHoursAndMinutesForMilitaryTime(endTime);
                                var dateTime_start = new Date(new Date().setHours(startTime_hours_mins.hours, startTime_hours_mins.minutes));
                                var dateTime_end = new Date(new Date().setHours(endTime_hours_mins.hours, endTime_hours_mins.minutes));
                                var start_date_time_string = formatTimestampDate(dateTime_start).split(', ')[1];
                                if(this_event.get('endDate')) {
                                    start_date_time_string += ` - ${ formatTimestampDate(dateTime_end).split(', ')[1] }`;
                                }
                                $('#overlay_event-description-popup .metric_start_date_time').text(start_date_time_string);
                                if(this_event.get('description')) {
                                    $('#overlay_event-description-popup .metric_description').text(this_event.get('description')).removeClass('incomplete');
                                } else {
                                    $('#overlay_event-description-popup .metric_description').text('Not provided').addClass('incomplete');
                                }
                                fadeIn('#overlay_event-description-popup');
                            }
                        } else if(this_event.className == 'camps') {
                            //go to registration
                            window.open(`/register/camp/${ this_event.id }/class`);
                        }
                    }
                }
            },
            createSchedule(){
                //placeholder prop
            },
            return_date_components_v2( params ){
                return return_date_components_v2( params );
            }
        },
        computed: {
            event_types(){
                if(this.is_admin) {
                    return this.component?.get('config_latest').event_types || [];
                } else {
                    return this.config_obj.event_types;
                }
            },
        },
        watch: {
            last_update(newVal, oldVal){
                if (newVal !== oldVal){
                    if (this.config){
                        this.config_obj = JSON.parse(this.config);
                    }
                    this.clubId = $('body').data('club-id'); 
                    this.load_membership_cal(this.client_id);
                    this.is_admin = window.location.href.indexOf('website-builder') !== -1;
                    this.checkThenHandleEventTagsForCalendar(this.client_id);
                }
            }
        },
    });
</script>    <script type="text/html" id="template-membership-directory">
    <div class="cs-background-image relative" :class="class_string" :style="style_string">
        <template v-if="formatting && formatting.overlay_opacity">
            <div class="cs-image-overlay" :style="{ 'opacity': formatting.overlay_opacity.toString() }"></div>
        </template>
        <div class="element-wrapper" :class="'element-wrapper_' + component_type" :style="element_style_string">
            <div class="membership-directory-wrap centeredBlock centeredText" :data-client-id="client_id">
                <div class="ease flexNoWrap show_when_loaded">
                    <div class="inputWrap searchBarWrap flexGrowOne" style="min-width:100%;">
                        <input class="searchBar easeFast" placeholder="Search members..." v-model="search">
                    </div>
                    <div class="flexGrowOne"></div>
                </div> 
                <div v-if="!loading && member_tags?.length >= 1" class="scrollable posScrollbar lightBorderTop noPaddingBottom">
                    <div class="flexNoWrap insert_member_tags" style="padding:15px;">
                        <div :class="{ 'active' : selectedTag === 'all' }" class="cs-tab-bar-option cs-tab-bar-option_member_tags cs-tab-bar-option_member_tags_all mobile-order" data-option="all" @click="handleTagSelection( 'all' )">All members</div>
                        <template v-for="tag in member_tags" :key="tag.id">
                            <div :class="{ 'active' : selectedTag === tag.id }" class="cs-tab-bar-option cs-tab-bar-option_member_tags mobile-order" :data-option="tag.id" @click="handleTagSelection( tag.id )">{{ tag.get('name') }}</div>
                        </template>
                    </div>
                </div>
                <!-- <div class="show_when_loaded table_markup_insert"> -->
                <div class="lightBorderTop scrollable fff noPadding">
                <table v-if="!loading && filtered_members?.length >= 1 && configurable_columns.length >= 2" class="tableInsert hundop">
                    <tbody>
                        <tr class="tableHeaderRow" :class="{ 'ascending' : sortObject.order == 'ascending' }">
                            <template v-for="column in configurable_columns">
                                <th v-if="!Array.isArray(column.headerName) && !column.headerClasses.includes('sortable')" :class="column.headerClasses" :style="column.headerStyle">{{ column.headerName }}</th>
                                <th v-if="!Array.isArray(column.headerName) && column.headerClasses.includes('sortable')" 
                                    :style="column.headerStyle" 
                                    :data-db-key="column['data-db-key']"
                                    @click="clicked_sort(column['data-db-key'])"
                                    :class="[column.headerClasses, { 'sorted': sortObject.key === column['data-db-key'] }]"
                                    >
                                        {{ column.headerName }}
                                        <div class="sort-arrow"></div>
                                </th>
                                <template v-for="headerName in column.headerName">
                                    <th v-if="Array.isArray(column.headerName)" :class="column.headerClasses">{{ headerName }}</th>
                                </template>
                            </template>
                        </tr>
                        <!-- member rows injected here -->
                        <template v-for="member in filtered_members" :key="member.id">
                            <tr 
                                v-if="check_archive_status( member )"
                                class="tableRow pointer" 
                                :class="{ 'member-row_' : member.id }"
                                @click="clicked_member_row( member )"
                            >
                                <!-- photo column -->
                                <td v-if="check_configurable_classes('column_photo')" class="lessPadding column_photo first-cell" style="padding-right:0px;">
                                    <div v-if="member && member.get('profPicURL')" class="smallIcon noMargin noBorder" :style="{ backgroundImage: 'url(' + member.get('profPicURL') + ')' }"></div>
                                    <div v-else 
                                        class="smallIcon noMargin noBorder flexWrap align-items-center" 
                                        style="padding-right:0px;
                                        background-color: #f1f5fa;
                                        text-align: center;
                                        font-size: 16px;"
                                    >
                                        <i class="fa-regular fa-user"></i>
                                    </div>
                                </td>
                                <!-- firstName column -->
                                <td v-if="check_configurable_classes('firstName')">
                                    <p v-if="(member && member.get('firstName')) && !member.get('nickname')" class="capitalize">{{ member.get('firstName') }}</p>
                                    <p v-if="(member && member.get('firstName')) && member.get('nickname')" class="capitalize">{{ member.get('firstName') }} ({{ member.get('nickname') }})</p>
                                    <p v-if="member && !member.get('firstName')" class="incomplete">None</p>
                                </td>
                                <!-- lastName column -->
                                <td v-if="check_configurable_classes('lastName')">
                                    <p v-if="(member && member.get('lastName'))" class="capitalize">{{ member.get('lastName') }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- member number column -->
                                <td v-if="check_configurable_classes('column_member_number')" class="column_member_number">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('memberNumber')" class="uppercase">{{ member.get('membershipObject').get('memberNumber') }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- email column -->
                                <td v-if="check_configurable_classes('column_email')" class="column_email">
                                    <p v-if="member && member.get('email')"><a @click.stop :href="'mailto:' + member.get('email')">{{ member.get('email')}}</a></p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- mobile column -->
                                <td v-if="check_configurable_classes('column_mobile')" class="column_mobile">
                                    <p v-if="member && member.get('mobile')"><a @click.stop :href="'tel:' + member.get('mobile')">{{ member.get('mobile')}}</a></p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- home phone column -->
                                <td v-if="check_configurable_classes('column_phone_home')" class="column_phone_home">
                                    <p v-if="member && member.get('phone_home')"><a @click.stop :href="'tel:' + member.get('phone_home')">{{ member.get('phone_home')}}</a></p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- member tags column -->
                                <td v-if="check_configurable_classes('column_member_tags')" class="column_member_tags">
                                    <div class="flexWrapLeftAlign" v-html="return_member_tags( member ) || ''"></div>
                                </td>
                                <!-- ghin number column -->
                                <td v-if="check_configurable_classes('column_ghin_number')" class="column_ghin_number">
                                    <p v-if="member && member.get('ghin_number')">{{ member.get('ghin_number') }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- address ( street, city, state, zip) columns -->
                                <template v-if="check_configurable_classes('column_address')">
                                    <td class="column_address">
                                        <p v-if="member && member.get('street')">{{ member.get('street') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address">
                                        <p v-if="member && member.get('city')">{{ member.get('city') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address">
                                        <p v-if="member && member.get('state')">{{ member.get('state') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address">
                                        <p v-if="member && member.get('zip')">{{ member.get('zip') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                </template>
                                <!-- secondary address ( street, city, state, zip ) columns -->
                                <template v-if="check_configurable_classes('column_address_secondary')">
                                    <td class="column_address_secondary">
                                        <p v-if="member && member.get('street_secondary')">{{ member.get('street_secondary') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address_secondary">
                                        <p v-if="member && member.get('city_secondary')">{{ member.get('city_secondary') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address_secondary">
                                        <p v-if="member && member.get('state_secondary')">{{ member.get('state_secondary') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                    <td class="column_address_secondary">
                                        <p v-if="member && member.get('zip_secondary')">{{ member.get('zip_secondary') }}</p>
                                        <p v-else class="incomplete">None</p>
                                    </td>
                                </template>
                                <!-- start date column -->
                                <td v-if="check_configurable_classes('column_start_date')" class="column_start_date">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('startDate')">{{ format_utc_date( member.get('membershipObject').get('startDate') ) }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- end date column -->
                                <td v-if="check_configurable_classes('column_end_date')" class="column_end_date">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('endDate')">{{ format_utc_date( member.get('membershipObject').get('endDate')) }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- renewal column -->
                                <td v-if="check_configurable_classes('column_renewed')" class="column_renewed">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('startDate')">{{ format_utc_date( member.get('membershipObject').get('renewed') || member.get('membershipObject').get('startDate') ) }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- category column -->
                                <td v-if="check_configurable_classes('column_category')" class="column_category">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('tierObject')">{{ member.get('membershipObject').get('tierObject').get('name') }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                                <!-- plan column -->
                                <td v-if="check_configurable_classes('column_plan')" class="column_plan">
                                    <p v-if="(member && member.get('membershipObject')) && member.get('membershipObject').get('planObject')">{{ member.get('membershipObject').get('planObject').get('name') }}</p>
                                    <p v-else class="incomplete">None</p>
                                </td>
                            </tr>
                        </template>
                    </tbody>
                </table>
                </div>
                <!-- </div> -->
                <div v-if="loading" class="cardBodySpinnerWrap relative active">
                    <div class="cardBodySpinner centeredBlock"></div>
                </div>
                <p v-if="!loading && filtered_members.length == 0" class="noObjectsMSG withPadding">{{ return_no_results_msg() }}</p>
            </div>
        </div>
    </div>
</script>

<script>

    function prepThenDisplayMembershipDirectoryPopup( memberObject ){
        //clear stuff
        $('#overlay_membership-directory-popup .insert').text('');
        //name
        var name = '';
        //check type
        if( memberObject.className == "boats" ){
            //actually a boat - we re-use the same overlay
            $('#overlay_membership-directory-popup .version_boat').removeClass('hidden');
            $('#overlay_membership-directory-popup .version_member').addClass('hidden');
            name = returnNameStringForBoat( memberObject );
            //handle documents
            $('.section-wrap_documents').find('.inline-value').remove();
            // var documents = $('.membership-directory-wrap').data('documents');
            var documents = store.components.membership_directory.documents;
            if( documents ){
                for (var i = 0; i <= documents.length - 1; i++) {
                    if( documents[i].get('boatObject') ){
                        if( documents[i].get('boatObject').id == memberObject.objectId ){
                            var this_name = documents[i].get('name');
                            if( this_name  && this_name.length >= 1 ){
                                $('#overlay_membership-directory-popup .section-wrap_documents').append('<p class="flexGrowOne inline-value tinyPaddingTop"><a class="tappedDocument" data-document-id="'+ documents[i].id +'" target="_blank" href="'+ documents[i].get('URL') +'">'+ this_name +' ></a></p>');
                            }
                        }
                    }
                }
            }
        }else{
            //ok, it's a member
            $('#overlay_membership-directory-popup .version_boat').addClass('hidden');
            $('#overlay_membership-directory-popup .version_member').removeClass('hidden');
            //name
            if( memberObject.get('firstName') ){
                name += memberObject.get('firstName');
                if( memberObject.get('nickname') ){
                    name += ' ('+ memberObject.get('nickname') + ')';
                }
            }
            if( memberObject.get('lastName') ){
                if( name.length >= 1 ){
                    name += ' ';
                }
                name += memberObject.get('lastName');
            }
        }
        $('#overlay_membership-directory-popup .insert_name').text(name);
        //prof pic
        var profPicURL = memberObject.get('profPicURL');
        if( profPicURL ){
            $('#overlay_membership-directory-popup .profile-picture').text("");
            $('#overlay_membership-directory-popup .profile-picture').css('background-image', 'url('+profPicURL+')' );
            $('#overlay_membership-directory-popup .profile-background-inner').css('background-image', 'url('+profPicURL+')' );
        }else{
            $('#overlay_membership-directory-popup .profile-picture').css('background-image', '' );
            $('#overlay_membership-directory-popup .profile-background-inner').css('background-image', '');
            if( name.length >= 1 ){
                var initial = name.substr(0,1).toLowerCase();
                $('#overlay_membership-directory-popup .profile-picture').text( initial );
            }
        }
        //plug in data
        $('#overlay_membership-directory-popup .inline-value').each(function(){
            var key = $(this).data('db-key');
            if( key ){
                var value = memberObject.get(key);
                if( value ){
                    if( key.toLowerCase().indexOf('email') >= 0 ){
                        //it's an email
                        $(this).html( '<a href="mailto:'+ value +'">'+ value +'</a>' );
                        $(this).removeClass( 'hidden' );
                    }else if( key.toLowerCase().includes('mobile') || key.toLowerCase().includes('phone') ){
                        //it's a mobile number
                        $(this).html( '<a href="tel:'+ returnCleanMobileNumber( value ) +'">'+ formatMobileNumber( value ) +'</a>' );
                        $(this).removeClass( 'hidden' );
                    }else if( $(this).data('prepend') ){
                        $(this).text( $(this).data('prepend') + " " + value );
                        $(this).removeClass( 'hidden' );
                    }else{
                        //not an email, mobile number, or special boat field
                        $(this).text( value );
                        $(this).removeClass( 'hidden' );
                    }
                }else{
                    $(this).text( "" ).addClass('hidden');
                    $(this).data( 'date', null );
                }
            }
        });
        //custom fields
        $('.section-wrap_custom_fields').html('');
        // var custom_fields = $('.membership-directory-wrap').data('custom_fields');
        var custom_fields = store.components.membership_directory.custom_fields;
        if( custom_fields ){
            //plug them in
            for (var i = 0; i <= custom_fields.length - 1; i++) {
                var response = returnResponseForCustomField( memberObject.get('customFieldsArray'), custom_fields[i].id );
                if( response ){
                    $('.section-wrap_custom_fields').append('<h4 class="smallBlockLetters leftText smallMarginTop">'+ custom_fields[i].get('name') +'</h4>');
                    $('.section-wrap_custom_fields').append('<p class="inline-value dark tinyPaddingTop">'+ response +'</p>');
                }
            }
        }
        //family
        $('.section-wrap_family').find('.inline-value').remove();
        var membershipObject = memberObject.get('membershipObject');
        var membersArray = membershipObject.get('membersArray');
        var family_members = [];
        if( membersArray ){
            for (var i = 0; i <= membersArray.length - 1; i++) {
                if( membersArray[i].id != memberObject.id ){
                    var this_member = returnObjectByID( membersArray[i].id, store.components.membership_directory.allMembers );
                    if( this_member ){
                        family_members.push( this_member );
                    }
                }
            }
        }
        for (var i = 0; i <= family_members.length - 1; i++) {
            var this_name = '';
            if( family_members[i].get('firstName') ){
                this_name = family_members[i].get('firstName');
                if( family_members[i].get('lastName') ){
                    this_name += ' ';
                    this_name += family_members[i].get('lastName');
                }
            }
            if( this_name.length >= 1 ){
                $('#overlay_membership-directory-popup .section-wrap_family').append('<p class="flexGrowOne inline-value tinyPaddingTop"><a class="tappedFamilyMember" data-member-id="'+ family_members[i].id +'">'+ this_name +' ></a></p>');
            }
        }
        //boats
        $('.section-wrap_boats').find('.inline-value').remove();
        var boats_map = store.components.membership_directory.boats_map;
        if( boats_map ){
            var these_boats = boats_map[ membershipObject.id ];
            if( these_boats ){
                for (var i = 0; i <= these_boats.length - 1; i++) {
                    var this_name = returnNameStringForBoat( these_boats[i] );
                    if( this_name.length >= 1 ){
                        $('#overlay_membership-directory-popup .section-wrap_boats').append('<p class="flexGrowOne inline-value tinyPaddingTop"><a class="tappedBoat" data-boat-id="'+ these_boats[i].id +'" data-membership-id="'+ membershipObject.id +'">'+ this_name +' ></a></p>');
                    }
                }
            }
        }
        //continue
        $('#overlay_membership-directory-popup .section-wrap').each(function(){
            if( $(this).find('.inline-value').not( $('.hidden') ).length >= 1 ){
                $(this).removeClass('hidden');
            }else{
                $(this).addClass('hidden');
            }
        });
        //fade it in
        fadeIn('#overlay_membership-directory-popup');
    }

    function returnNameStringForBoat( boatObject ){
        var this_name = '';
        if( boatObject.get('boatName') ){
            this_name += boatObject.get('boatName');
        }
        if( boatObject.get('sailNumber') ){
            if( this_name.length >= 1 ){
                this_name += " - ";
            }
            this_name += boatObject.get('sailNumber');
        }
        if( boatObject.get('class') ){
            if( this_name.length >= 1 ){
                this_name += " - ";
            }
            this_name += boatObject.get('class');
        }
        if( boatObject.get('hullNumber') ){
            if( this_name.length >= 1 ){
                this_name += " - ";
            }
            this_name += boatObject.get('hullNumber');
        }
        return this_name;
    }

    function returnResponseForCustomField( customFieldsArray, custom_field_id ){
        if( customFieldsArray ){
            for (var i = 0; i <= customFieldsArray.length - 1; i++) {
                if( customFieldsArray[i].customFieldID == custom_field_id ){
                    if( customFieldsArray[i].response ){
                        return customFieldsArray[i].response;
                    }else if( customFieldsArray[i].optionsStringsArray ){
                        var string = "";
                        for (var s = 0; s <= customFieldsArray[i].optionsStringsArray.length - 1; s++) {
                            if( string.length >= 1 ){
                                string += ', ';
                            }
                            string += customFieldsArray[i].optionsStringsArray[s];
                        }
                        return string;
                    }
                    break;
                }
            }
        }
        return null;
    }
    
    /* ----- STORE ----- */
    store.components["membership_directory"] = {
        clubId: null,
        clubIds: ['8pB9LjQKoE', '2oWU1chg3P'], //for mantoloking and cambridge yc
        allMembers: [],
        member_tags: [],
        json: [],
        boats_map: [],
        custom_fields: [],
        documents: [], //for scira
        selectedTag: 'all',
        // configurable_columns: [],
        count: 0,
        search: '',
        loading: true,
        sortObject: {
            order: 'ascending',
            key: 'lastName'
        },
    };

    /* ----- COMPONENT ----- */
    app_content.component("membership-directory-component", {
        template: "#template-membership-directory",
        data() {
            return store.components['membership_directory']
        },
        props: {
            formatting: Object,
            client_id: String,
            class_string: String,
            style_string: String,
            element_style_string: String,
            component_type: String,
            //admin
            last_update: Number,
        },
        mounted() {
            this.clubId = $('body').data('club-id'); 
            this.load_membership_directory();
            // this.fillColumnClasses();
        },
        methods: {
            sortByFirstName_ascending( a, b ){
                var aFirstName = '';
                if( a.get('firstName') ){
                    aFirstName += a.get('firstName').trim().toLowerCase();
                }
                var bFirstName = '';
                if( b.get('firstName') ){
                    bFirstName += b.get('firstName').trim().toLowerCase();
                }
                if(aFirstName < bFirstName) { return -1; }
                if(aFirstName > bFirstName) { return 1; }
                //they had the same name
                return 0;
            },
            sortByFirstName_descending( a, b ){
                var aFirstName = '';
                if( a.get('firstName') ){
                    aFirstName += a.get('firstName').trim().toLowerCase();
                }
                var bFirstName = '';
                if( b.get('firstName') ){
                    bFirstName += b.get('firstName').trim().toLowerCase();
                }
                if(aFirstName > bFirstName) { return -1; }
                if(aFirstName < bFirstName) { return 1; }
                return 0;
            },
            sortByLastName_ascending( a, b ){
                var aLastName = '';
                if( a.get('lastName') ){
                    aLastName += a.get('lastName').trim().toLowerCase();
                }
                var bLastName = '';
                if( b.get('lastName') ){
                    bLastName += b.get('lastName').trim().toLowerCase();
                }
                if(aLastName < bLastName) { return -1; }
                if(aLastName > bLastName) { return 1; }
                return 0;
            },
            sortByLastName_descending( a, b ){
                var aLastName = '';
                if( a.get('lastName') ){
                    aLastName += a.get('lastName').trim().toLowerCase();
                }
                var bLastName = '';
                if( b.get('lastName') ){
                    bLastName += b.get('lastName').trim().toLowerCase();
                }
                if(aLastName > bLastName) { return -1; }
                if(aLastName < bLastName) { return 1; }
                return 0;
            }, 
            sortByMemberNumber_ascending( a, b ){
                var aMemberNumber = '';
                if( a.get('membershipObject') && a.get('membershipObject').get('memberNumber') ){
                    aMemberNumber += a.get('membershipObject').get('memberNumber').trim().toLowerCase();
                }
                var bMemberNumber = '';
                if( b.get('membershipObject') && b.get('membershipObject').get('memberNumber') ){
                    bMemberNumber += b.get('membershipObject').get('memberNumber').trim().toLowerCase();
                }
                if(aMemberNumber < bMemberNumber) { return -1; }
                if(aMemberNumber > bMemberNumber) { return 1; }
                return 0;
            },
            sortByMemberNumber_descending( a, b ){
                var aMemberNumber = '';
                if( a.get('membershipObject') && a.get('membershipObject').get('memberNumber') ){
                    aMemberNumber += a.get('membershipObject').get('memberNumber').trim().toLowerCase();
                }
                var bMemberNumber = '';
                if( b.get('membershipObject') && b.get('membershipObject').get('memberNumber') ){
                    bMemberNumber += b.get('membershipObject').get('memberNumber').trim().toLowerCase();
                }
                if(aMemberNumber > bMemberNumber) { return -1; }
                if(aMemberNumber < bMemberNumber) { return 1; }
                return 0;
            },
            sortByStartDate_ascending( a, b ){
                var aStartDate;
                if( a.get('membershipObject') && a.get('membershipObject').get('startDate') ){
                    aStartDate = a.get('membershipObject').get('startDate');
                }
                var bStartDate;
                if( b.get('membershipObject') && b.get('membershipObject').get('startDate') ){
                    bStartDate = b.get('membershipObject').get('startDate');
                }
                if(aStartDate < bStartDate) { return -1; }
                if(aStartDate > bStartDate) { return 1; }
                return 0;
            },
            sortByStartDate_descending( a, b ){
                var aStartDate;
                if( a.get('membershipObject') && a.get('membershipObject').get('startDate') ){
                    aStartDate = a.get('membershipObject').get('startDate');
                }
                var bStartDate;
                if( b.get('membershipObject') && b.get('membershipObject').get('startDate') ){
                    bStartDate = b.get('membershipObject').get('startDate');
                }
                if(aStartDate > bStartDate) { return -1; }
                if(aStartDate < bStartDate) { return 1; }
                return 0;
            },
            sortByRenewed_ascending( a, b ){
                var aRenewed;
                if( a.get('membershipObject') && a.get('membershipObject').get('renewed') ){
                    aRenewed = a.get('membershipObject').get('renewed');
                }else if( a.get('membershipObject') && a.get('membershipObject').get('startDate') ){
                    aRenewed = a.get('membershipObject').get('startDate');
                }
                var bRenewed;
                if( b.get('membershipObject') && b.get('membershipObject').get('renewed') ){
                    bRenewed = b.get('membershipObject').get('renewed');
                }else if( b.get('membershipObject') && b.get('membershipObject').get('startDate') ){
                    bRenewed = b.get('membershipObject').get('startDate');
                }
                if(aRenewed < bRenewed) { return -1; }
                if(aRenewed > bRenewed) { return 1; }
                return 0;
            },
            sortByRenewed_descending( a, b ){
                var aRenewed;
                if( a.get('membershipObject') && a.get('membershipObject').get('renewed') ){
                    aRenewed = a.get('membershipObject').get('renewed');
                }else if( a.get('membershipObject') && a.get('membershipObject').get('startDate') ){
                    aRenewed = a.get('membershipObject').get('startDate');
                }
                var bRenewed;
                if( b.get('membershipObject') && b.get('membershipObject').get('renewed') ){
                    bRenewed = b.get('membershipObject').get('renewed');
                }else if( b.get('membershipObject') && b.get('membershipObject').get('startDate') ){
                    bRenewed = b.get('membershipObject').get('startDate');
                }
                if(aRenewed > bRenewed) { return -1; }
                if(aRenewed < bRenewed) { return 1; }
                return 0;
            },
            sortByEndDate_ascending( a, b ){
                var aEndDate;
                if( a.get('membershipObject') && a.get('membershipObject').get('endDate') ){
                    aEndDate = a.get('membershipObject').get('endDate');
                }
                var bEndDate;
                if( b.get('membershipObject') && b.get('membershipObject').get('endDate') ){
                    bEndDate = b.get('membershipObject').get('endDate');
                }
                if(aEndDate < bEndDate) { return -1; }
                if(aEndDate > bEndDate) { return 1; }
                return 0;
            },
            sortByEndDate_descending( a, b ){
                var aEndDate;
                if( a.get('membershipObject') && a.get('membershipObject').get('endDate') ){
                    aEndDate = a.get('membershipObject').get('endDate');
                }
                var bEndDate;
                if( b.get('membershipObject') && b.get('membershipObject').get('endDate') ){
                    bEndDate = b.get('membershipObject').get('endDate');
                }
                if(aEndDate > bEndDate) { return -1; }
                if(aEndDate < bEndDate) { return 1; }
                return 0;
            },
            load_membership_directory(){
                //update the ui
                store.components.membership_directory.loading = true;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    //get new data
                    var params = {};
                    params["client_id"] = $('.membership-directory-wrap').data('client-id');
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(result => {
                    //vue 
                    store.components.membership_directory.member_tags = result.member_tags;
                    store.components.membership_directory.loading = false;   
                    var json = [];
                    var retrieved_members = result.members;
                    for (var i = 0; i <= retrieved_members.length - 1; i++) {
                        var boats_string = "";
                        var number = "";
                        if( retrieved_members[i].get('membershipObject') ){
                            number = retrieved_members[i].get('membershipObject').get('memberNumber');
                        }
                        var boats_map = result.boats_map;
                        if( boats_map && retrieved_members[i].get('membershipObject') ){
                            var these_boats = boats_map[ retrieved_members[i].get('membershipObject').id ];
                            if( these_boats ){
                                for (var b = these_boats.length - 1; b >= 0; b--) {
                                    if( boats_string.length >= 1 ){
                                        boats_string += " ";
                                    }
                                    boats_string += returnNameStringForBoat( these_boats[b] );
                                }
                            }
                        }
                        retrieved_members[i].boats_string = boats_string
                        json.push({
                            "objectId": retrieved_members[i].id,
                            "name": retrieved_members[i].get('firstName') + " " + retrieved_members[i].get('lastName'),
                            "boats_string": boats_string,
                            "number": number
                        })
                    }
                    //refactor for search
                    store.components.membership_directory.allMembers = retrieved_members;
                    //vue 
                    store.components.membership_directory.json = json;
                    store.components.membership_directory.boats_map = result.boats_map;
                    store.components.membership_directory.custom_fields = result.custom_fields;
                    store.components.membership_directory.documents = result.documents; //for scira
                }, function(error){
                    checkParseError( error );
                });
                return thisPromise;
            },
            /* ----- common methods ----- */
            clicked_sort( key ){
                if( this.sortObject.key == key ){
                    //already sorting by this one - flip it
                    if( this.sortObject.order == "descending" ){
                        this.sortObject.order = "ascending";
                    }else{
                        this.sortObject.order = "descending";
                    }
                }else{
                    //not sorting by this yet
                    this.sortObject.key = key;
                    this.sortObject.order = "descending";
                }
            },
            /* ----- table methods ----- */
            handleTagSelection( tag_id ){
                this.selectedTag = tag_id;
            },
            fillColumnClasses(){
                // let configureColumns = {
                //     'show_photo': {
                //         order: 1,
                //         headerClasses: 'column_photo lessPadding',
                //         headerStyle: 'padding-left:10px;0px',
                //         headerName: null,
                //     },
                //     'show_member_number': {
                //         order: 4,
                //         headerClasses: 'column_member_number sortable',
                //         'data-db-key': 'memberNumber',
                //         headerName: 'Number'
                //     },
                //     'show_email': {
                //         order: 5,
                //         headerClasses: 'column_email',
                //         headerName: 'Email'
                //     },
                //     'show_mobile': {
                //         order: 6,
                //         headerClasses: 'column_mobile',
                //         headerName: 'Mobile'
                //     },
                //     'show_phone_home': {
                //         order: 7,
                //         headerClasses: 'column_phone_home',
                //         headerName: 'Home Phone'
                //     },
                //     'show_member_tags': {
                //         order: 8,
                //         headerClasses: 'column_member_tags',
                //         headerName: 'Tags'
                //     },
                //     'show_ghin_number': {
                //         order: 9,
                //         headerClasses: 'column_ghin_number',
                //         headerName: 'GHIN Number'
                //     },
                //     'show_address': {
                //         order: 10,
                //         headerClasses: 'column_address',
                //         headerName: ['Street', 'City', 'State', 'Postal Code']
                //     },
                //     'show_address_secondary': {
                //         order: 11,
                //         headerClasses: 'column_address_secondary',
                //         headerName: ['Street (Secondary)', 'City (Secondary)', 'State (Secondary)', 'Postal Code (Secondary)']
                //     },
                //     'show_start_date': {
                //         order: 12,
                //         headerClasses: 'sortable column_start_date',
                //         'data-db-key': 'startDate',
                //         headerName: 'Start Date'
                //     },
                //     'show_end_date': {
                //         order: 13,
                //         headerClasses: 'sortable column_end_date',
                //         'data-db-key': 'endDate',
                //         headerName: 'End Date'
                //     },
                //     'show_renewed': {
                //         order: 14,
                //         headerClasses: 'sortable column_renewed',
                //         'data-db-key': 'renewed',
                //         headerName: 'Renewed'
                //     },
                //     'show_category': {
                //         order: 15,
                //         headerClasses: 'column_category',
                //         headerName: 'Category'
                //     },
                //     'show_plan': {
                //         order: 16,
                //         headerClasses: 'column_plan',
                //         headerName: 'Plan'
                //     },
                // }
                // let classStringArr = this.class_string.split(' ');
                // this.configurable_columns = classStringArr.reduce((acc, currentClass) => {
                //     if (configureColumns[currentClass] !== undefined){
                //         acc.push(configureColumns[currentClass])
                //     }
                //     return acc;
                // }, [
                //     {
                //         order: 2,
                //         headerClasses: 'sortable firstName',
                //         'data-db-key': 'firstName',
                //         required: true,  
                //         headerName: 'First Name'
                //     },
                //     {
                //         order: 3,
                //         headerClasses: 'sortable lastName',
                //         'data-db-key': 'lastName',
                //         required: true,  
                //         headerName: 'Last Name'
                //     },
                // ]).sort((a, b) => {
                //     return a.order - b.order;
                // })
            },
            check_archive_status( memberObject ){
                var membershipObject = memberObject.get('membershipObject');
                if(membershipObject && ! membershipObject.get('archived') && membershipObject.get('status') != 'canceled' ){
                    return true;
                }
                return false;
            },
            clicked_member_row( memberObject ){
                $('#overlay_membership-directory-popup').data('members', this.allMembers);
                $('#overlay_membership-directory-popup').data('boats_map', this.boats_map);
                prepThenDisplayMembershipDirectoryPopup( memberObject );
            },
            check_configurable_classes( className ){
                for (let i = 0; i < this.configurable_columns.length; i++){
                    if (this.configurable_columns[i].headerClasses.includes(className)){
                        return true;
                        break;
                    }
                }
                return false;
            },
            return_member_tags( memberObject ){
                var member_tags = memberObject.get('member_tags') || [];
                var tag_string = "";
                var tagsSituation = '';
                if( member_tags.length >= 1 ){
                    for (var i = 0; i <= member_tags.length - 1; i++) {
                        if( member_tags[i].className == "member_tags" ){
                            if( ! member_tags[i].get('archived') && ! member_tags[i].get('hidden') ){
                                if( tag_string.length >= 1 ){
                                    tag_string += ',';
                                }
                                tag_string += member_tags[i].id;
                                if( member_tags[i].get('hex_value') ){
                                    //custom color
                                    tagsSituation += '<p class="table-row-tag" style="background-color:#'+ member_tags[i].get('hex_value') +';">' + member_tags[i].get('name') + '</p>';
                                }else{
                                    //default color
                                    tagsSituation += '<p class="table-row-tag grey">' + member_tags[i].get('name') + '</p>';
                                }
                            }
                        }
                    }
                }
                if( tagsSituation.length >= 1 ){
                    return tagsSituation;
                }else{
                    return '<p class="incomplete">None</p>'
                }
            },
            format_utc_date( memberObject ){
                return formatUTCDate( memberObject, true, false, true )
            },
            return_no_results_msg(){
                if (this.clubIds.includes(this.clubId)){
                    return 'Search a member to get started.' //for mantoloking, cambridge yc, northport yc
                } else {
                    return 'No members found.';
                }
            },
            sortMembershipDirectory( members ){
                var sortObject = store.components.membership_directory.sortObject;
                if( ! sortObject ){
                    sortObject = {}
                }
                if( ! sortObject.key ){
                    sortObject.key = "startDate";
                }
                if( ! sortObject.order ){
                    sortObject.order = "descending"
                }
                if( sortObject.key == "firstName" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByFirstName_ascending );
                    }else{
                        members = members.sort( this.sortByFirstName_descending );
                    }
                }else if( sortObject.key == "lastName" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByLastName_ascending );
                    }else{
                        members = members.sort( this.sortByLastName_descending );
                    }
                }else if( sortObject.key == "memberNumber" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByMemberNumber_ascending );
                    }else{
                        members = members.sort( this.sortByMemberNumber_descending );
                    }
                }else if( sortObject.key == "startDate" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByStartDate_ascending );
                    }else{
                        members = members.sort( this.sortByStartDate_descending );
                    }
                }else if( sortObject.key == "endDate" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByEndDate_ascending );
                    }else{
                        members = members.sort( this.sortByEndDate_descending );
                    }
                }else if( sortObject.key == "renewed" ){
                    if( sortObject.order == "ascending" ){
                        members = members.sort( this.sortByRenewed_ascending );
                    }else{
                        members = members.sort( this.sortByRenewed_descending );
                    }
                }
                return members;
            }
        },
        computed: {
            filtered_members(){
                let val = this.search.toLowerCase();
                let filteredMembers;
                if (this.clubIds.includes(this.clubId)){
                    filteredMembers = []; //for mantoloking, cambridge yc, northport yc
                } else {
                    filteredMembers = this.allMembers;
                }
                // handle search results using all members
                if (this.search.length > 0){
                    filteredMembers = this.allMembers.filter(member => {
                        let firstName = member.get('firstName').toLowerCase() || '';
                        let lastName = member.get('lastName').toLowerCase() || '';
                        let boats_string = member['boats_string'].toLowerCase() || '';
                        let number = member?.get('membershipObject')?.get('memberNumber').toLowerCase() || '';
                        // change this to includes
                        if ( firstName.includes(val) || lastName.includes(val) || boats_string.includes(val) || number.includes(val) ){
                            return member;
                        }
                    })
                }
                // handle member tag selection using filtered search results
                if (this.selectedTag !== 'all'){
                    filteredMembers = filteredMembers.filter(member => {
                        let memberTags = member.get('member_tags') || [];
                        for (let i = 0; i < memberTags.length; i++){
                            if (memberTags[i].id === this.selectedTag){
                                return member;
                                break;
                            }
                        }
                    })
                }
                if (this.clubIds.includes(this.clubId) && filteredMembers.length > 20){
                    return this.sortMembershipDirectory( filteredMembers.slice(0, 20) ); //for mantoloking, cambridge yc, northport yc
                } else {
                    return this.sortMembershipDirectory( filteredMembers );
                }
            },
            configurable_columns(){
                let configureColumns = {
                    'show_photo': {
                        order: 1,
                        headerClasses: 'column_photo lessPadding',
                        headerStyle: 'padding-left:10px;0px',
                        headerName: null,
                    },
                    'show_member_number': {
                        order: 4,
                        headerClasses: 'column_member_number sortable',
                        'data-db-key': 'memberNumber',
                        headerName: 'Number'
                    },
                    'show_email': {
                        order: 5,
                        headerClasses: 'column_email',
                        headerName: 'Email'
                    },
                    'show_mobile': {
                        order: 6,
                        headerClasses: 'column_mobile',
                        headerName: 'Mobile'
                    },
                    'show_phone_home': {
                        order: 7,
                        headerClasses: 'column_phone_home',
                        headerName: 'Home Phone'
                    },
                    'show_member_tags': {
                        order: 8,
                        headerClasses: 'column_member_tags',
                        headerName: 'Tags'
                    },
                    'show_ghin_number': {
                        order: 9,
                        headerClasses: 'column_ghin_number',
                        headerName: 'GHIN Number'
                    },
                    'show_address': {
                        order: 10,
                        headerClasses: 'column_address',
                        headerName: ['Street', 'City', 'State', 'Postal Code']
                    },
                    'show_address_secondary': {
                        order: 11,
                        headerClasses: 'column_address_secondary',
                        headerName: ['Street (Secondary)', 'City (Secondary)', 'State (Secondary)', 'Postal Code (Secondary)']
                    },
                    'show_start_date': {
                        order: 12,
                        headerClasses: 'sortable column_start_date',
                        'data-db-key': 'startDate',
                        headerName: 'Start Date'
                    },
                    'show_end_date': {
                        order: 13,
                        headerClasses: 'sortable column_end_date',
                        'data-db-key': 'endDate',
                        headerName: 'End Date'
                    },
                    'show_renewed': {
                        order: 14,
                        headerClasses: 'sortable column_renewed',
                        'data-db-key': 'renewed',
                        headerName: 'Renewed'
                    },
                    'show_category': {
                        order: 15,
                        headerClasses: 'column_category',
                        headerName: 'Category'
                    },
                    'show_plan': {
                        order: 16,
                        headerClasses: 'column_plan',
                        headerName: 'Plan'
                    },
                }
                let classStringArr = this.class_string.split(' ');
                return classStringArr.reduce((acc, currentClass) => {
                    if (configureColumns[currentClass] !== undefined){
                        acc.push(configureColumns[currentClass])
                    }
                    return acc;
                }, [
                    {
                        order: 2,
                        headerClasses: 'sortable firstName',
                        'data-db-key': 'firstName',
                        required: true,  
                        headerName: 'First Name'
                    },
                    {
                        order: 3,
                        headerClasses: 'sortable lastName',
                        'data-db-key': 'lastName',
                        required: true,  
                        headerName: 'Last Name'
                    },
                ]).sort((a, b) => {
                    return a.order - b.order;
                })
            },
        }
    })
</script>    <script type="text/html" id="template-event-list-card">
    <div 
        class="event-row overlay-event-row flexEventOne noBorderBottom"
        :class="'event-row_' + event.id"
        :data-event-id="event.id"
    > 
        <div
            class="event-list-card" 
            :class="{
                'small-card': formatting.card_size == 'small',
                'large-card': formatting.card_size == 'large',
                'box-shadow-light': formatting.box_shadow == 'light',
                'box-shadow-dark': formatting.box_shadow == 'dark',
            }"
            :style="{ 'border-radius': formatting.border_radius + 'px' || '0px' }"
        >
            <div 
                v-if="event_image"
                class="event-image" 
                :class="{
                    'small-card': formatting.card_size == 'small',
                    'large-card': formatting.card_size == 'large'
                }"
                :style="{ backgroundImage: `url(${event_image})` }"
            >
                <div class="date-badge">
                    <p class="event-list-card-month">{{ formatted_date('month') }}</p>
                    <p class="event-list-card-date">{{ formatted_date('date')  }}</p>
                </div>
            </div>
            <div 
                v-else 
                class="event-image"
                :class="{
                    'small-card': formatting.card_size == 'small',
                    'large-card': formatting.card_size == 'large'
                }"
            >
                <div class="date-badge">
                    <p class="event-list-card-month">{{ formatted_date('month') }}</p>
                    <p class="event-list-card-date">{{ formatted_date('date')  }}</p>
                </div>
                <p class="no-background">{{ event.get('name').charAt(0).toUpperCase() }}</p>
            </div>

            <div 
                class="card-content"
                :style="{ 'border-radius': formatting.border_radius + 'px' || '0px' }"
            >
                <p class="event-type">{{ event_type }}</p>
                <p class="event-title">{{ event_title }}</p>
                <div class="event-time">
                    <i class="fa-regular fa-clock" style="font-size: 0.8em;"></i>
                    <span>{{ event_time }}</span>
                </div>
                <button v-if="button_label" class="event-button relative background" v-html="button_label"></button>
            </div>
        </div>
    </div>
</script>

<style>
    .event-list-card {
        width: 190px;
        overflow: hidden;
        background: white;
        font-family: 'Inter', sans-serif;
        display: flex;
        flex-direction: column;
        transition: transform 0.1s ease;
    }
    .event-list-card.small-card {
        width: 190px;
    }
    .event-list-card.large-card {
        width: 230px;
    }
    .event-list-card.box-shadow-light {
        box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2);
    }
    .event-list-card.box-shadow-dark {
        box-shadow: 6px 6px 16px rgba(0, 0, 0, 0.2);
    }
    .event-list-card .event-image {
        display: flex;
        text-align: center;
        align-items: center;
        width: 100%;
        height: 170px;
        background-size: cover; /*contain*/
        background-repeat: no-repeat;
        background-position: center;
        background-color: #77818f;
        color: #fff;
        position: relative;
    }
    .event-list-card .event-image.small-card{
        height: 170px;
    }
    .event-list-card .event-image.large-card{
        height: 220px;
    }
    .event-list-card .event-image .no-background {
        width: 100%;
        font-weight: 500;
        font-size: 5em;
    }
    .date-badge {
        position: absolute;
        top: 5px;
        left: 5px;
        /* background-color: rgba(0,0,0,0.5); */
        background-color: transparent;
        color: white;
        border-radius: 4px;
        padding: 4px 6px;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
        font-weight: bold;
        min-width: 45px;
        max-width: 50%;
        min-height: 45px;
    }
    .date-badge .event-list-card-month {
        font-size: 12px;
        letter-spacing: 1.2px;
        text-transform: uppercase;
    }
    .date-badge .event-list-card-date {
        font-size: 26px;
        letter-spacing: 1.2px;
        font-family: 'Times New Roman', Times, serif;
    }
    .card-content {
        height: 120px;
        padding: 14px 12px;
        background-color: #f9f9f9;
    }
    .event-list-card .event-type {
        font-size: 12px;
        text-transform: uppercase;
        color: #000;
        margin-bottom: 2px;
    }
    .event-list-card .event-title {
        font-size: 18px;
        text-transform: uppercase;
        margin-bottom: 8px;
        color: #000;
        font-family: serif;
        letter-spacing: 0.2px;
    }
    .event-list-card .event-time {
        display: flex;
        align-items: center;
        font-size: 14px;
        color: #000;
        margin-bottom: 12px;
    }
    .event-time i {
        margin-right: 6px;
    }
    .event-list-card .event-button {
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        z-index: 2;
        letter-spacing: 1px;
        line-height: 16px;
        cursor: pointer;
        font-size: 14px;
        font-weight: normal;
        padding: 6px 12px;
        text-transform: uppercase;
        transition: all 0.2s ease;
        border: 1.5px solid #000;
        border-radius: 2px;
    }
    .event-list-card .event-button:hover{
        background-color: #000;
        color: white;
    }
    .res-callout{
        display: flex;
        align-items: center;
        white-space: nowrap;
        height: fit-content;
        width: fit-content;
        padding: 3.5px;
        background-color: #fff;
        border: 1px solid #e4ebf1;
        border-radius: 5px;
        font-size: 10px;
        text-transform: uppercase;
        color: #5c6d7a;
    }
</style>

<script>
    
    var config = defineComponent({
        template: "#template-event-list-card",
        data() {
            return {}
        },
        props: {
            event: Object,
            formatting: Object,
        },
        methods: {
            formatted_date( type ){
                var start_offset, end_offset;
                var start_offset_time, end_offset_time;
                if( this.event.get('startDate') ){
                    start_offset = returnOffsetDateForUTCDate( this.event.get('startDate') );
                    //handle start/end times set explicitly on the event (for socials)
                    if( this.event.get('startTime') ){
                        var start_data = returnHoursAndMinutesForMilitaryTime( this.event.get('startTime') );
                        start_offset.setHours( start_offset.getHours() + start_data.hours );
                        start_offset.setMinutes( start_offset.getMinutes() + start_data.minutes );
                    }
                    start_offset_time = start_offset.getTime();
                }
                var endDate = this.event.get('endDate');
                if( ! endDate && this.event.get('startDate') ){
                    endDate = this.event.get('startDate');
                }
                if( endDate ){
                    end_offset = returnOffsetDateForUTCDate( endDate );
                    //handle start/end times set explicitly on the event (for socials)
                    if( this.event.get('endTime') ){
                        var end_data = returnHoursAndMinutesForMilitaryTime( this.event.get('endTime') );
                        end_offset.setHours( end_offset.getHours() + end_data.hours );
                        end_offset.setMinutes( end_offset.getMinutes() + end_data.minutes );
                    }
                    end_offset_time = end_offset.getTime();
                }

                let month = '';
                let date = '';
                if( start_offset ){
                    date = start_offset.getDate().toString();
                    if( end_offset && ! this.event.get('all_day') ){
                        if( end_offset.getDate() != start_offset.getDate() ){
                            date += '-' + end_offset.getDate();
                        }
                    }
                    if( date.length == 1 ){
                        date = '0' + date;
                    }
                    month = returnShortMonth( start_offset.getMonth() );
                }
                if( type == 'month' ){
                    return month;
                }else if( type == 'date' ){
                    return date;
                }
            },
            return_image_data( eventObject ){
                if( eventObject.className == "subevents" && eventObject.get('regattaObject') ){
                    eventObject = eventObject.get('regattaObject');
                }
                return {
                    url: eventObject.get('imageURL'),
                    crop: eventObject.get('imageCrop')
                }
            },
            returnShowRegisterButtonForEvent( eventObject ){
                //set defaults
                var now = new Date();
                var ended = false;
                var registration_closed = eventObject.get('registration_closed');
                var startDate = eventObject.get('startDate');
                var lastChanceDate = eventObject.get('lastChanceDate');
                var endDate = eventObject.get('endDate');
                if( ! endDate && startDate ){
                    endDate = startDate;
                }
                var endDate_plus_one;
                if( endDate ){
                    endDate_plus_one = new Date( endDate.getTime() ); 
                    endDate_plus_one.setDate( endDate.getDate() + 1 );
                }
                if( now > endDate_plus_one && endDate_plus_one ){ 
                    ended = true; 
                }
                if( now > lastChanceDate && lastChanceDate ){ 
                    registration_closed = true; 
                }
                if( ended || registration_closed || eventObject.get('calendarOnly') ){ 
                    return false;
                } else {
                    return true;
                }
            },
        },
        computed: {
            event_image() {
                return this.return_image_data(this.event).url;
            },
            event_title() {
                return this.event.get('name') || '';
            },
            event_type(){
                if( this.event.className == 'camps' ){
                    return 'camp';
                }else if( this.event.className == 'regattas' ){
                    return 'regatta';
                }else{
                    return 'event';
                }
            },
            event_time() {
                if( this.event.get('startDate') ){
                    if( this.event.className == "regattas" || this.event.className == "subevents" ){
                        //these are stored in the club's time
                        return format_utc_date_v2({
                            "utcDate": this.event.get('startDate'),
                            "timezone": store.timezone,
                        });
                    }else{
                        //these are stored as 12am UTC
                        let date_components = return_date_components_v2({
                            "date": this.event.get('startDate'),
                            "timezone": "UTC"
                        });
                        date_components.amPm = null;
                        if( this.event.get('startTime') ){
                            let time_data = returnHoursAndMinutesForMilitaryTime( this.event.get('startTime') );
                            date_components.hour = time_data.hours;
                            date_components.minute = time_data.minutes;
                        }
                        let offset_date = return_utc_date_v2({
                            "dateComponents": date_components,
                            "timezone": store.timezone
                        });
                        return format_utc_date_v2({
                            "utcDate": offset_date,
                            "timezone": store.timezone,
                            "formatString": "h:mm A"
                        });
                    }
                }
                return null;
            },
            button_label(){
                let eventObject = this.event;
                var href_base = '';
                var clubObject = eventObject.get('clubObject');
                var web_settings = clubObject.get('web_settings');
                if( web_settings ){
                    if( web_settings.get('event_links') == "use_clubspot_regatta_links" && ( eventObject.className == "regattas" || eventObject.className == "subevents" ) ){
                        //force clubspot urls for regattas
                        href_base += 'https://theclubspot.com';
                    }   
                }
                var content;
                var show_register_button = this.returnShowRegisterButtonForEvent( eventObject );
                if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                    if( eventObject.className == "subevents" ){
                        eventObject = eventObject.get('regattaObject');
                    }
                    //check for external events
                    if( eventObject.get('regatta_external') && eventObject.get('external_regatta_url') ){
                        //it's an external event
                        content = 'View event<a class="absoluteA" target="_blank" href="'+ eventObject.get('external_regatta_url') +'"></a>';
                    }else{
                        //handle button status
                        if( show_register_button ){
                            //register
                            content = 'Register<a class="absoluteA" href="'+href_base+'/regatta/'+ eventObject.id +'"></a>';
                        }else{
                            //results
                            content = 'View Results<a class="absoluteA" href="'+href_base+'/regatta/'+ eventObject.id +'/results"></a>';
                        }
                    }
                }else if( eventObject.className == "events" ){
                    var registration_link;
                    if( eventObject.get('events_v2') ){
                        registration_link = '/event/' + eventObject.id;
                    }else if( eventObject.get('external_event') && eventObject.get('external_register_link') ){
                        registration_link = eventObject.get('external_register_link');
                    }else if( eventObject.get('event_product') ){
                        if( eventObject.get('event_product').get('availability') && eventObject.get('event_product').get('availability').startDate ){
                            registration_link = "/reserve/" + eventObject.get('event_product').id + "?date=" + eventObject.get('event_product').get('availability').startDate;
                        }
                    }
                    if( registration_link && show_register_button ){
                        content = 'RSVP<a class="absoluteA" href="'+href_base+''+registration_link+'"></a>';
                    } 
                }else if( eventObject.className == "camps" ){
                    //handle button status
                    if( show_register_button ){
                        //register
                        content = 'Register<a href="'+href_base+'/register/camp/'+ eventObject.id +'/class" class="absoluteA"></a>';
                    }
                }
                return content;
            }
        }
    })
    //define the component
    app_overlays.component("event-list-card-component", config);
    app_content.component("event-list-card-component", config);

</script>    <script type="text/html" id="template-event-list-event">
    <div 
        class="event-row overlay-event-row flexEventOne"
        :class="'event-row_' + event.id"
        :data-event-id="event.id"
    > 
        <!-- date and image wrap -->
        <div class="cs-signups-row-left flexNoWrapCenterAlign">
            <div class="cs-signups-date-wrap relative" style="width: 55px;">
                <div class="centeredBlock relative">
                    <div v-html="return_markup( event, 'date')"></div>
                </div>
            </div>
            <div 
                v-if="return_image_data( event ).url" 
                class="cs-signups-row-image flexWrap" 
                :class="{ 'background-contain' : return_image_data( event ).crop === 'contain', 'background-cover' : return_image_data( event ).crop === 'cover'}"
                :style="{ backgroundImage: 'url(' + return_image_data( event ).url + ')' }"
            >
                <div v-if="return_markup( event, 'check-header-callout' )" class="header-callout">{{ return_markup( event, 'header-callout') }}</div>
            </div>
            <div 
                v-else 
                class="cs-signups-row-image flexWrap" 
            >
                <div v-if="return_markup( event, 'check-header-callout' )" class="header-callout">{{ return_markup( event, 'header-callout') }}</div>
                {{ event.get('name').charAt(0).toUpperCase() }}
            </div>
        </div>
        <!-- event info, links, and host wrap -->
        <div class="cs-signups-row-inner flexWrapLeftAlign ellipsis align-items-center">
            <!-- event info -->
            <div class="cs-signups-name-wrap ellipsis textLeft">
                <span class="flexWrap" style="display: flex; align-items: center; justify-content: flex-start; margin-bottom: 5px;">
                    <div class="cs-signups-name-0 textLeft" style="flex-grow: 0; margin-right: 8px;">{{ event.get('name') }}</div>
                    <!-- <div 
                        v-if="event.get('members_only')" 
                        class="res-callout"
                    >
                        <i class="fa-regular fa-user-check" style="padding-right:5px; font-size: 9px;"></i>
                        <span style="font-size: 10px;">Members Only</span>
                    </div> -->
                </span>
                <div class="event-date-wrap-v2">{{ niceDate( event ) }}</div>
                <div class="event-date-wrap-v2 tiniestPaddingTop">
                    <p>{{ return_markup( event, 'event-host-1') }}</p>
                    <p>{{ return_markup( event, 'event-host-2' )}}</p>
                </div>
            </div>
            <!-- event links -->
            <div class="cs-signups-links-wrap flexGrowOne">
                <div class="cs-signups-links-wrap-inner textLeft">
                    <div class="event-nav-1" v-html="return_markup( event, 'links' )"></div>
                    <div class="event-nav-2" v-html="return_markup( event, 'button' )"></div>
                </div>
            </div>
        </div>
    </div>
</script>

<script>
    
    var config = defineComponent({
        template: "#template-event-list-event",
        data() {
            return {}
        },
        props: {
            event
        },
        methods: {
            return_image_data( eventObject ){
                if( eventObject.className == "subevents" && eventObject.get('regattaObject') ){
                    eventObject = eventObject.get('regattaObject');
                }
                return {
                    url: eventObject.get('imageURL'),
                    crop: eventObject.get('imageCrop')
                }
            },
            niceDate( eventObject ){
                if( eventObject.get('startDate') ){
                    if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                        //these are stored in the club's time
                        return format_utc_date_v2({
                            "utcDate": eventObject.get('startDate'),
                            "timezone": store.timezone,
                        });
                    }else{
                        //these are stored as 12am UTC
                        let date_components = return_date_components_v2({
                            "date": eventObject.get('startDate'),
                            "timezone": "UTC"
                        });
                        date_components.amPm = null;
                        if( eventObject.get('startTime') ){
                            let time_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                            date_components.hour = time_data.hours;
                            date_components.minute = time_data.minutes;
                        }
                        let offset_date = return_utc_date_v2({
                            "dateComponents": date_components,
                            "timezone": store.timezone
                        });
                        return format_utc_date_v2({
                            "utcDate": offset_date,
                            "timezone": store.timezone,
                            "formatString": "MMM D, YYYY, h:mm A"
                        });
                    }
                }
                return null;
            },
            return_markup( eventObject, type ){
                var href_base = '';
                var clubObject = eventObject.get('clubObject');
                var web_settings = clubObject.get('web_settings');
                if( web_settings ){
                    if( web_settings.get('event_links') == "use_clubspot_regatta_links" && ( eventObject.className == "regattas" || eventObject.className == "subevents" ) ){
                        //force clubspot urls for regattas
                        href_base += 'https://theclubspot.com';
                    }   
                }
                var start_offset, end_offset;
                var start_offset_time, end_offset_time;
                if( eventObject.get('startDate') ){
                    start_offset = returnOffsetDateForUTCDate( eventObject.get('startDate') );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('startTime') ){
                        var start_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                        start_offset.setHours( start_offset.getHours() + start_data.hours );
                        start_offset.setMinutes( start_offset.getMinutes() + start_data.minutes );
                    }
                    start_offset_time = start_offset.getTime();
                }
                var endDate = eventObject.get('endDate');
                if( ! endDate && eventObject.get('startDate') ){
                    endDate = eventObject.get('startDate');
                }
                if( endDate ){
                    end_offset = returnOffsetDateForUTCDate( endDate );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('endTime') ){
                        var end_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('endTime') );
                        end_offset.setHours( end_offset.getHours() + end_data.hours );
                        end_offset.setMinutes( end_offset.getMinutes() + end_data.minutes );
                    }
                    end_offset_time = end_offset.getTime();
                }
                // returns here
                if ( type === 'check-header-callout' ) {
                    return start_offset && start_offset.getFullYear() !== new Date().getFullYear()
                } else if ( type === 'start_offset_time' ) {
                    return start_offset_time;
                } else if ( type === 'end_offset_time' ) {
                    return end_offset_time;
                } else if ( type === 'header-callout' ){
                    return start_offset.getFullYear();
                } else if ( type === 'date' ){
                    //date
                    var date = '';
                    if( start_offset ){
                        var style_string = '';
                        if( eventObject.get('imageURL') ){
                            //we always want white text for this
                            style_string = ' style="color:#fff !important;" ';
                        }
                        date += '<p class="cs-signups-date-month">' + returnShortMonth( start_offset.getMonth() ) + '</p>';
                        var days = start_offset.getDate();
                        if( end_offset && ! eventObject.get('all_day') ){
                            if( end_offset.getDate() != start_offset.getDate() ){
                                days += ' - ' + end_offset.getDate();
                            }
                        }
                        date += '<p class="cs-signups-date-day">' + days + '</p>';
                    }
                    return date;
                } else if ( type === 'event-host-1' ){
                    return $('body').data('club-name');
                } else if ( type === 'event-host-2' ){
                    var club_string = '';
                    var location_params = {
                        eventObject: eventObject,
                        hideCountry: true, 
                        hideZip: true,
                        hideStreet: true,
                    }
                    var club_location_params = {
                        eventObject: clubObject,
                        hideCountry: true, 
                        hideZip: true,
                        hideStreet: true,
                    }
                    if(formatLocation(location_params) ){
                        if( club_string.length >= 1 ){
                            club_string += ', ';
                        }
                        club_string += formatLocation(location_params);
                    }else if( clubObject && formatLocation(club_location_params) ){
                        if( club_string.length >= 1 ){
                            club_string += ', ';
                        }
                        club_string += formatLocation(club_location_params);
                    }
                    return club_string;
                }  else if ( type === 'links' ){
                    var content;
                    if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                        //check for external events
                        if( eventObject.get('regatta_external') && eventObject.get('external_regatta_url') ){
                            //it's an external event
                            content = '<p class="tiniestPaddingTop"><a target="_blank" href="'+ eventObject.get('external_regatta_url') +'">Event page</a></p>';
                        }else{
                            if( eventObject.className == "subevents" ){
                                eventObject = eventObject.get('regattaObject');
                            }
                            //event page
                            content = '<p class="tiniestPaddingTop"><a href="'+href_base+'/regatta/'+ eventObject.id +'">Event page</a></p>';
                            //entries
                            content += '<p class="tiniestPaddingTop"><a href="'+href_base+'/regatta/'+ eventObject.id +'/#entry-list">Entries</a></p>';
                            //race docs
                            content += '<p class="tiniestPaddingTop"><a href="'+href_base+'/regatta/'+ eventObject.id +'/#notice-board">Notice board</a></p>';
                        }
                    }else if( eventObject.className == "events" ){
                        //check for external events
                        if( ! eventObject.get('calendarOnly') ){
                            if( eventObject.get('external_event') && eventObject.get('external_event_url') ){
                                //it's an external event
                                content = '<p class="tiniestPaddingTop"><a target="_blank" href="'+ eventObject.get('external_event_url') +'">Event page</a></p>';
                            }else{
                                //event page
                                content = '<p class="tiniestPaddingTop"><a href="'+href_base+'/event/'+ eventObject.id +'">Event page</a></p>';
                            }
                        }
                    }else if( eventObject.className == "camps" ){
                        //it's a camp
                        content = '<p class="tiniestPaddingTop"><a href="'+href_base+'/camp-registrations/'+ eventObject.id +'">Entry list</a></p>';
                    }
                    return content;
                } else if ( type === 'button' ){
                    var content;
                    var show_register_button = this.returnShowRegisterButtonForEvent( eventObject );
                    if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                        if( eventObject.className == "subevents" ){
                            eventObject = eventObject.get('regattaObject');
                        }
                        //check for external events
                        if( eventObject.get('regatta_external') && eventObject.get('external_regatta_url') ){
                            //it's an external event
                            content = '<button class="relative background">View event<a class="absoluteA" target="_blank" href="'+ eventObject.get('external_regatta_url') +'"></a></button>';
                        }else{
                            //handle button status
                            if( show_register_button ){
                                //register
                                content = '<button class="relative background">Register<a class="absoluteA" href="'+href_base+'/register/regatta/'+ eventObject.id +'/class"></a></button>';
                            }else{
                                //results
                                content = '<button class="relative background">View Results<a class="absoluteA" href="'+href_base+'/regatta/'+ eventObject.id +'/results"></a></button>';
                            }
                        }
                    }else if( eventObject.className == "events" ){
                        var registration_link;
                        if( eventObject.get('events_v2') ){
                            registration_link = '/event/' + eventObject.id;
                        }else if( eventObject.get('external_event') && eventObject.get('external_register_link') ){
                            registration_link = eventObject.get('external_register_link');
                        }else if( eventObject.get('event_product') ){
                            if( eventObject.get('event_product').get('availability') && eventObject.get('event_product').get('availability').startDate ){
                                registration_link = "/reserve/" + eventObject.get('event_product').id + "?date=" + eventObject.get('event_product').get('availability').startDate;
                            }
                        } 
                        if( registration_link && show_register_button ){
                            content = '<button class="relative background">RSVP<a class="absoluteA" href="'+href_base+''+registration_link+'"></a></button>';
                        } 
                    }else if( eventObject.className == "camps" ){
                        //handle button status
                        if( show_register_button ){
                            //register
                            content = '<button class="relative background">Register<a href="'+href_base+'/register/camp/'+ eventObject.id +'/class" class="absoluteA"></a></button>';
                        }
                    }
                    return content;
                }
            },
            returnShowRegisterButtonForEvent( eventObject ){
                //set defaults
                var now = new Date();
                var ended = false;
                var registration_closed = eventObject.get('registration_closed');
                var startDate = eventObject.get('startDate');
                var lastChanceDate = eventObject.get('lastChanceDate');
                var endDate = eventObject.get('endDate');
                if( ! endDate && startDate ){
                    endDate = startDate;
                }
                var endDate_plus_one;
                if( endDate ){
                    endDate_plus_one = new Date( endDate.getTime() ); 
                    endDate_plus_one.setDate( endDate.getDate() + 1 );
                }
                if( now > endDate_plus_one && endDate_plus_one ){ 
                    ended = true; 
                }
                if( now > lastChanceDate && lastChanceDate ){ 
                    registration_closed = true; 
                }
                if( ended || registration_closed || eventObject.get('calendarOnly') ){ 
                    return false;
                } else {
                    return true;
                }
            },
        }
    })
    //define the component
    app_overlays.component("event-list-event-component", config);
    app_content.component("event-list-event-component", config);

</script>

<style>
    .res-callout{
        display: flex; /* Add this to make the container a flexbox */
        align-items: center; /* Center items vertically */
        white-space: nowrap; /* Prevent wrapping */
        height: fit-content;
        width: fit-content;
        padding: 3.5px;
        background-color: #fff;
        border: 1px solid #e4ebf1;
        border-radius: 5px;
        font-size: 10px;
        text-transform: uppercase;
        color: #5c6d7a;
    }
</style>    <script type="text/html" id="template-event-list">
    <div class="cs-background-image relative" :class="class_string" :style="style_string">
        <div class="element-wrapper" 
            :class="'element-wrapper_' + component_type" 
            :style="element_style_string" 
            style="max-width:100% !important;min-width:90%;"
        >
            <!-- list view -->
            <template v-if="formatting_obj.layout === 'list' || !formatting_obj.layout">
                <div class="event-list-wrap centeredBlock centeredText" :class="'event-list-wrap_' + client_id" :data-client_id="client_id">
                    <div 
                        class="flexNoWrap align-items-center"
                        style="padding-bottom:5px;"
                    >
                        <h3 class="smallMarginRight" :style="{ 'font-size': '20px !important', 'font-weight': '600 !important', 'padding': '10px' }">{{ event_dates.charAt(0).toUpperCase() + event_dates.slice(1) || 'Upcoming' }} events</h3>
                        <div 
                            class="view-all-events-wrapper tinyMarginLeft"
                            @click="popViewAllEventsOverlay()"
                        >
                            <div :style="{ 'font-size': '14px !important', 'font-weight': '400' }">View all</div>
                            <div class="smallDrilldownHeaderBackButton flip"></div>
                        </div>
                    </div>
                    <div class="standardCardBody noBorderBottom fff noPadding overflowHidden">
                        <div v-if="!loading && filtered_events.length >= 1" class="tableInsert hundop flexWrapEvent">
                            <template v-for="(event, index) in filtered_events" :key="event.id">
                                <event-list-event-component
                                    :event="event"
                                ></event-list-event-component>
                            </template>
                        </div>
                        <div v-if="loading" class="cardBodySpinnerWrap active relative">
                            <div class="cardBodySpinner centeredBlock"></div>
                        </div>
                        <p v-if="!loading && filtered_events.length == 0" class="noObjectsMSG withPadding textLeft">No events found.</p>
                    </div>
                </div>
            </template>

            <!-- carousel view -->
            <template v-if="formatting_obj.layout === 'carousel'">
                <div class="event-list-wrap centeredBlock centeredText" :class="'event-list-wrap_' + client_id" :data-client_id="client_id">
                    <div 
                        class="flexNoWrap align-items-center event_list_carousel_default"
                        style="padding: 0px 0px 15px 5px;"
                    >
                        <h3
                            class="event_list_carousel_header"
                        >{{ event_dates || 'upcoming' }} events</h3>
                        <div 
                            v-if="filter_types_arr && filter_types_arr.length > 0 && event_tags.length > 0"
                            style="display: flex; align-items: center; justify-content: flex-start;"
                        >
                            <h3
                                class="tinyMarginLeft event_list_carousel_header"
                            >in</h3>
                            <select 
                                v-model="selected_event_tag_id" 
                                class="tinyMarginLeft event_list_carousel_header select_filter"
                            >
                                <option
                                    v-for="tag in event_tags"
                                    :key="tag.id"
                                    :value="tag.id"
                                >
                                    {{ tag.get('name') }}
                                </option>
                            </select>
                            <i class="fa-solid fa-sort-down tinyMarginLeft tinyMarginBottom pointer" style="color: #000;"></i>
                        </div>
                    </div>
                    <span
                        @mouseenter="start_auto_scroll('left')"
                        @mouseleave="stop_auto_scroll"
                        class="event-list-auto-scroll left"
                    ></span>
                    <div class="standardCardBody noBorderTop noBorderBottom fff noPadding">
                        <div 
                            ref="event_list_card_wrapper"
                            v-if="!loading && filtered_events.length >= 1"
                            class="tableInsert hundop event-list-card-wrapper"
                            :style="{ gap: formatting_obj.card_spacing + 'px' || '25px' }"
                        >
                            <template v-for="(event, index) in filtered_events" :key="event.id">
                                <event-list-card-component
                                    :event="event"
                                    :formatting="formatting_obj"
                                ></event-list-card-component>
                            </template>
                        </div>
                        <div v-if="loading" class="cardBodySpinnerWrap active relative">
                            <div class="cardBodySpinner centeredBlock"></div>
                        </div>
                        <p v-if="!loading && filtered_events.length == 0" class="noObjectsMSG withPadding textLeft">No events found.</p>
                    </div>
                    <span
                        @mouseenter="start_auto_scroll('right')"
                        @mouseleave="stop_auto_scroll"
                        class="event-list-auto-scroll right"
                    ></span>
                </div>
            </template>
        </div>
    </div>
</script>

<style>
    .event_list_carousel_default {
        --event-list-carousel-font-family: 'Cormorant Garamond';
        --event-list-carousel-font-size: 16px;
        --event-list-carousel-font-weight: 600;
        --event-list-carousel-text-transform: uppercase;
        --event-list-carousel-letter-spacing: 1.2px;
        --event-list-carousel-color: #000;
    }
    .event_list_carousel_header {
        /* font-family: var(--event-list-carousel-font-family) !important; */
        font-size: var(--event-list-carousel-font-size) !important;
        font-weight: var(--event-list-carousel-font-weight) !important;
        text-transform: var(--event-list-carousel-text-transform) !important;
        letter-spacing: var(--event-list-carousel-letter-spacing) !important;
        color: var(--event-list-carousel-color) !important;
    }
    .event_list_carousel_header.select_filter {
        width: 100px !important;
        text-overflow: ellipsis !important;
        border: none !important;
        border-bottom: 0.5px solid black !important;
        appearance: none !important;
        -webkit-appearance: none !important;
        -moz-appearance: none !important;
        background: none !important;
        padding: 0px !important;
        box-shadow: none !important;
        display: inline-block !important;
        background-image: none !important;
    }
    .event-list-card-wrapper {
        position: relative;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        padding: 10px;
        overflow: scroll !important;
        scrollbar-width: none !important;
    }
    .event-list-auto-scroll {
        position: absolute;
        top: 0;
        height: 100%;
        width: 20px;
    }
    .event-list-auto-scroll.left {
        left: 0;
    }
    .event-list-auto-scroll.right {
        right: 0;
    }
</style>

<script>    
    
    app_content.component('event-list-component', {
        template: '#template-event-list',
        data() {
            return {
                allEvents: [],
                active_filters: {
                    eventDates: 'upcoming',
                },
                loading: true,
                sortObject: {
                    order: 'ascending',
                    key: 'startDate'
                },
                event_tags: [],
                selected_event_tag_id: null,
                scroll_animation_frame: null,
            }
        },
        props: {
            class_string: String,
            style_string: String,
            element_style_string: String,
            formatting: String,
            filter_types: String,
            event_dates: String,
            component_type: String,
            client_id: String,
            //admin
            component: Object,
            last_update: Number,
        },
        mounted() {
            this.loadEventList(this.client_id);
        },
        methods: {
            popViewAllEventsOverlay(){
                store.overlays.view_all_events = true;
                store.components.view_all_events.allEvents = this.allEvents;
                //passed props
                store.components.view_all_events.class_string = this.class_string;
                store.components.view_all_events.style_string = this.style_string;
                store.components.view_all_events.element_style_string = this.element_style_string;
                store.components.view_all_events.component_type = this.component_type;
                store.components.view_all_events.client_id = this.client_id;
            },
            start_auto_scroll(direction) {
                const wrapper = this.$refs.event_list_card_wrapper;
                const amount = direction === 'right' ? 10 : -10; //scroll speed
                const scrollStep = () => {
                    wrapper.scrollBy({ left: amount, behavior: 'auto' });
                    this.scroll_animation_frame = requestAnimationFrame(scrollStep);
                };
                scrollStep();
            },
            stop_auto_scroll() {
                cancelAnimationFrame(this.scroll_animation_frame);
                this.scroll_animation_frame = null;
            },
            loadEventList( client_id, overrides = {} ){
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    var params = {};
                    params["client_id"] = client_id;
                    params["overrides"] = overrides;
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(retrieved_events => {
                    this.allEvents = retrieved_events;
                    if( this.filter_types_arr && this.filter_types_arr.indexOf('tags') !== -1 ){
                        this.event_tags = this.retrieve_event_tags();
                        this.selected_event_tag_id = this.event_tags && this.event_tags.length > 0 ? this.event_tags[0].id : null;
                    }
                    if( this.event_dates ){
                        this.active_filters.eventDates = this.event_dates;
                    }
                }).then(() => {
                    this.loading = false;
                }, error => {
                    checkParseError(error);
                    this.loading = false;
                });
                return thisPromise;
            },
            retrieve_event_tags(){
                let event_tags = [];
                this.filtered_events.forEach(event => {
                    if (event.get('event_tags')) {
                        event.get('event_tags').forEach(event_tag => {
                            const exists = event_tags.some(tag => tag.id === event_tag.id);
                            if (!exists) {
                                event_tags.push(event_tag);
                            }
                        });
                    }
                });
                return event_tags;
            },
            sortEventList( events, sortObject ){
                if( ! sortObject ){
                    sortObject = {}
                }
                if( ! sortObject.key ){
                    sortObject.key = "startDate";
                }
                if( ! sortObject.order ){
                    sortObject.order = "ascending"
                }
                if( sortObject.key == "name" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByEventName_ascending );
                    }else{
                        events = events.sort( this.sortByEventName_descending );
                    }
                }else if( sortObject.key == "startDate" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByStartDate_event_ascending );
                    }else{
                        events = events.sort( this.sortByStartDate_event_descending );
                    }
                }else if( sortObject.key == "endDate" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByEndDate_event_ascending );
                    }else{
                        events = events.sort( this.sortByEndDate_event_descending );
                    }
                }
                return events;
            },
            sortByEventName_ascending( a, b ){
                var aName = '';
                if( a.get('name') ){
                    aName += a.get('name').trim().toLowerCase();
                }
                var bName = '';
                if( b.get('name') ){
                    bName += b.get('name').trim().toLowerCase();
                }
                if(aName < bName) { return -1; }
                if(aName > bName) { return 1; }
                //they had the same name
                return 0;
            },
            sortByEventName_descending( a, b ){
                var aName = '';
                if( a.get('name') ){
                    aName += a.get('name').trim().toLowerCase();
                }
                var bName = '';
                if( b.get('name') ){
                    bName += b.get('name').trim().toLowerCase();
                }
                if(aName > bName) { return -1; }
                if(aName < bName) { return 1; }
                //they had the same name
                return 0;
            },
            sortByStartDate_event_ascending( a, b ){
                var aStartDate =  a.get('startDate')
                if( ! aStartDate ){
                    aStartDate = a.createdAt;
                }
                var bStartDate =  b.get('startDate')
                if( ! bStartDate ){
                    bStartDate = b.createdAt;
                }
                if(aStartDate < bStartDate) { return -1; }
                if(aStartDate > bStartDate) { return 1; }
                return 0;
            },
            sortByStartDate_event_descending( a, b ){
                var aStartDate =  a.get('startDate')
                if( ! aStartDate ){
                    aStartDate = a.createdAt;
                }
                var bStartDate =  b.get('startDate')
                if( ! bStartDate ){
                    bStartDate = b.createdAt;
                }
                if(aStartDate > bStartDate) { return -1; }
                if(aStartDate < bStartDate) { return 1; }
                return 0;
            },
            sortByEndDate_event_ascending( a, b ){
                var aEndDate =  a.get('endDate')
                if( ! aEndDate ){
                    aEndDate = a.createdAt;
                }
                var bEndDate =  b.get('endDate')
                if( ! bEndDate ){
                    bEndDate = b.createdAt;
                }
                if(aEndDate < bEndDate) { return -1; }
                if(aEndDate > bEndDate) { return 1; }
                return 0;
            },
            sortByEndDate_event_ascending( a, b ){
                var aEndDate =  a.get('endDate')
                if( ! aEndDate ){
                    aEndDate = a.createdAt;
                }
                var bEndDate =  b.get('endDate')
                if( ! bEndDate ){
                    bEndDate = b.createdAt;
                }
                if(aEndDate > bEndDate) { return -1; }
                if(aEndDate < bEndDate) { return 1; }
                return 0;
            },
            return_start_and_end_timestamps( eventObject ){
                //timestamp defaults
                let start, end;
                //check the dates
                let startDate = eventObject.get('startDate');
                var endDate = eventObject.get('endDate');
                if( ! endDate && eventObject.get('startDate') ){
                    endDate = eventObject.get('startDate');
                }
                if( startDate ){
                    //correct for UTC offset, based on event type
                    if( eventObject.className == "events" ){
                        //these are stored as 12 am utc
                        let start_components = return_date_components_v2({
                            "date": startDate,
                            "timezone": "UTC",
                        });
                        if( eventObject.get('startTime') ){
                            let time_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                            start_components.hour = time_data.hours;
                            start_components.minute = time_data.minutes;
                        }
                        let offset_start = return_utc_date_v2({
                            "dateComponents": start_components,
                            "timezone": store.timezone
                        });
                        start = offset_start.getTime();
                        let end_components = return_date_components_v2({
                            "date": endDate,
                            "timezone": "UTC",
                        });
                        if( eventObject.get('endTime') ){
                            let time_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('endTime') );
                            end_components.hour = time_data.hours;
                            end_components.minute = time_data.minutes;
                        }
                        let offset_end = return_utc_date_v2({
                            "dateComponents": end_components,
                            "timezone": store.timezone
                        });
                        end = offset_end.getTime();
                    }else{
                        //regattas are already stored in the club's time
                        start = startDate.getTime();
                        end = endDate.getTime();
                    }
                }
                //return them
                return {
                    start, 
                    end
                }
            }

            /*
            return_start_and_end_timestamps( eventObject ){
                var start_offset, end_offset;
                var start_offset_time, end_offset_time;
                if( eventObject.get('startDate') ){
                    start_offset = returnOffsetDateForUTCDate( eventObject.get('startDate') );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('startTime') ){
                        var start_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                        start_offset.setHours( start_offset.getHours() + start_data.hours );
                        start_offset.setMinutes( start_offset.getMinutes() + start_data.minutes );
                    }
                    start_offset_time = start_offset.getTime();
                }
                var endDate = eventObject.get('endDate');
                if( ! endDate && eventObject.get('startDate') ){
                    endDate = eventObject.get('startDate');
                }
                if( endDate ){
                    end_offset = returnOffsetDateForUTCDate( endDate );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('endTime') ){
                        var end_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('endTime') );
                        end_offset.setHours( end_offset.getHours() + end_data.hours );
                        end_offset.setMinutes( end_offset.getMinutes() + end_data.minutes );
                    }
                    end_offset_time = end_offset.getTime();
                }
                return {
                    start: start_offset_time,
                    end: end_offset_time
                }
            }
            */

        },
        computed: {
            filtered_events(){
                let filteredEvents = this.allEvents;
                // filter by upcoming events
                var timestamp = new Date().getTime();
                if (this.active_filters.eventDates !== 'all'){
                    filteredEvents = filteredEvents.filter(event => {
                        let start = this.return_start_and_end_timestamps( event ).start;
                        let end = this.return_start_and_end_timestamps( event ).end;
                        if (this.active_filters.eventDates === 'past'){
                            if( start < timestamp && ( end < timestamp || ! end || end == "undefined" ) ){
                                return event;
                            }
                        } else if (this.active_filters.eventDates === 'upcoming'){
                            if ( start > timestamp || end > timestamp ){
                                return event;
                            }
                        }
                    })
                }
                if(this.active_filters.eventDates === 'upcoming'){
                    this.sortObject = {
                        order: 'ascending',
                        key: 'startDate'
                    }
                }else{
                    this.sortObject = {
                        order: 'descending',
                        key: 'startDate'
                    }
                }
                if(!this.formatting_obj.layout || this.formatting_obj.layout === 'list'){
                    return this.sortEventList( filteredEvents, this.sortObject ).slice(0, 5);
                }else{
                    if(this.filter_types_arr.indexOf('tags') !== -1 && this.selected_event_tag_id){
                        return this.sortEventList( filteredEvents, this.sortObject ).filter(event => {
                            if(event.get('event_tags')){
                                return event.get('event_tags').some(event_tag => event_tag.id == this.selected_event_tag_id);
                            }
                        });
                    }else{
                        return this.sortEventList( filteredEvents, this.sortObject );
                    }
                }
            },
            formatting_obj(){
                if (this.formatting){
                    return JSON.parse(this.formatting);
                }
                return {};
            },
            filter_types_arr(){
                if (this.filter_types){
                    return JSON.parse(this.filter_types);
                }
                return [];
            },
        },
        watch: {
            last_update(newVal, oldVal){
                if (newVal !== oldVal){
                    let event_types = this.component.get('config_latest')?.event_types || [];
                    this.loadEventList( this.client_id, { event_types } );
                }
            }
        },
    });
</script>    <script type="text/html" id="template-iframe">
    <div v-if="!loading && !is_admin" class="cs-iframe-wrap" :class="class_string" :style="style_string">
        <iframe class="cs-iframe" :src="iframe_src"></iframe>
    </div>
    <div v-if="!loading && is_admin" class="cs-iframe-wrap cs-min-section-width" :class="class_string" :style="[style_string, { 'max-width': formatting_obj.section_width + '%' }]">
        <template v-if="iframe_src" >
            <iframe class="cs-iframe" sandbox="allow-forms allow-scripts" :src="iframe_src"></iframe>
        </template>
        <template v-if="!iframe_src">
            <p class="noObjectsMSG centeredBlock centeredText">Click on edit to configure your iframe.</p>
        </template>
    </div>
</script>

<script>    
    /* ----- COMPONENT ----- */
    app_content.component('iframe-component', {
        template: '#template-iframe',
        data() {
            return {
                global: store,
                loading: true,
                is_admin: false,
            }
        },
        props: {
            class_string: String,
            style_string: String,
            iframe_src: String,
            //admin
            component: Object,
            formatting_string: String,
            last_update: Number
        },
        mounted() {
            this.is_admin = window.location.href.indexOf('website-builder') !== -1;
            this.loading = false;
        },
        computed: {
            formatting_obj(){
                if (this.formatting_string){
                    return JSON.parse(this.formatting_string);
                }
                return {};
            },
        },
    });
</script>    <script type="text/html" id="template-blog-list">
    <div class="relative" :class="class_string" :style="style_string">
        <div class="element-wrapper cs-min-section-width" :class="'element-wrapper_' + component_type" :style="[element_style_string, { 'min-width': `${formatting_obj.section_width}%`, 'max-width': `${formatting_obj.section_width}%` }]">
            <div class="blog-list-wrap centeredBlock centeredText" :class="'blog-list-wrap_' + client_id" :data-client_id="client_id">
                <div class="ease flexNoWrap show_when_loaded" style="justify-content: center; align-items: center;">
                    <!-- template type - list -->
                    <template v-if="!formatting_obj.template || formatting_obj.template === 'list'">
                        <div class="inputWrap searchBarWrap flexGrowOne" style="min-width:100%;">
                            <input class="searchBar searchBar_blog-list easeFast" placeholder="Search posts..." v-model="search">
                        </div>
                        <div class="flexGrowOne"></div>
                    </template>
                    <!-- template type - bulletin -->
                    <template v-if="formatting_obj.template === 'bulletin'">
                        <div class="searchBarWrap_v2" style="width: 100%;
                        display: flex;
                        flex-direction: row;
                        align-items: center;
                        justify-content: center;
                        margin-right: 8px;
                        margin-left: 8px;
                        margin-bottom: 10px;">
                            <input id="searchBar_blog-list_v2" type="text" placeholder="Search posts..." v-model="search" />
                            <button id="searchBar_blog-list_submit" type="submit">
                                <svg style="width:24px;height:24px" viewBox="0 0 24 24"><path fill="#666666" d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" /></svg>
                            </button>
                        </div>
                    </template>
                </div> 
                <div class="fff noPadding">
                    <!-- template type - list -->
                    <template v-if="!formatting_obj.template || formatting_obj.template === 'list'">
                        <div v-if="!loading && truncated_posts.length >= 1" class="tableInsert hundop">
                            <template v-for="(post, index) in truncated_posts" :key="post.id">
                                <div 
                                    :style="{ 'background-color': formatting_obj.background_color || '#fff', 'border-radius': '4px' }"
                                    class="blog-row flexWrapLeftAlign relative pointer blog-row-border"
                                    :class="'blog-row_' + post.id" 
                                    :data-post-id="post.id"
                                >
                                    <div v-if="post && post.get('thumbnail')" class="blog-post-thumbnail" :style="'background-image:url(' + post.get('thumbnail') + ')'"></div>
                                    <div v-if="post && !post.get('thumbnail')" class="blog-post-thumbnail default-image-icon"></div>
                                    <div class="blog-row-inner flexGrowOne">
                                        <div class="blog-name-wrap-column">
                                            <p 
                                                class="blog-title" 
                                                :style="{ 
                                                    'color': formatting_obj.title_color || '#000',
                                                    'font-weight': formatting_obj.title_styling && formatting_obj.title_styling.bold ? '600 !important' : '400 !important',
                                                    'font-style': formatting_obj.title_styling && formatting_obj.title_styling.italic ? 'italic' : 'normal',
                                                    'text-decoration': formatting_obj.title_styling && formatting_obj.title_styling.underline ? 'underline' : 'none',
                                                }"
                                            >{{ post.get('title') }}</p>
                                            <p 
                                                v-if="post && post.get('subtitle')"
                                                class="blog-subtitle" 
                                                :style="{
                                                    'color': formatting_obj.subtitle_color || '#000',
                                                    'font-weight': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.bold ? '600 !important' : '400 !important',
                                                    'font-style': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.italic ? 'italic' : 'normal',
                                                    'text-decoration': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.underline ? 'underline' : 'none',
                                                }"
                                            >{{ post.get('subtitle') }}</p>
                                            <p class="blog-date" :style="{ 'color': formatting_obj.date_color || '#000' }">{{ niceDate(post) }}</p>
                                            <p><a class="absoluteA" :href="'/blog-post/' + post.id" style="text-transform: none !important; border-bottom: none !important;"></a>
                                                <a
                                                :style="{
                                                    'font-variant': 'small-caps',
                                                    'opacity': '0.9',
                                                    'color': formatting_obj.date_color || '#000',
                                                    'border-bottom': 'none !important',
                                                    'text-decoration': 'underline !important',
                                                    'text-decoration-color': (formatting_obj.date_color || '#000') + ' !important'
                                                }"
                                                >Read more</a>
                                            </p>
                                        </div>
                                    </div>
                                    <div v-if="post && post.get('pinned') === true">
                                        <i class="fa-solid fa-thumbtack thumbtack-icon" style="height: 1em; transform: rotate(45deg);"></i>
                                    </div>
                                </div>
                            </template>
                            <div 
                                v-if="has_more_posts"
                                class="view_more_button flexNoWrapCenter align-items-center"
                                @click="view_all = true"
                                style="margin-bottom:0px;margin-left:0px;margin-right:0px;"
                            >
                                <div>
                                    <p>View more</p>
                                </div>
                                <i class="fa-regular fa-arrow-right easeFast"></i>
                            </div>
                        </div>
                    </template>
                    <!-- template type - bulletin -->
                    <template v-if="formatting_obj.template === 'bulletin'">
                        <div 
                            v-if="!loading && truncated_posts.length >= 1" 
                            :class="class_string"
                        >
                            <div class="blog-list-container">
                                <section 
                                    class="blog-list-cards-v2" 
                                >
                                    <div v-for="(post, index) in truncated_posts" :key="post.id">
                                        <article 
                                            :style="{ 'background-color': formatting_obj.background_color || '#fff' }"
                                            style="display: flex; flex-direction: column; align-items: center; justify-content: flex-start; position: relative;"
                                            class="blog_post_card_v2"
                                            @click="go_to_post( post )"
                                        >
                                            <div class="blog-list-image-container">
                                                <img v-if="post && post.get('thumbnail')" class="blog_post_thumbnail" :src="post.get('thumbnail')">
                                                <div v-if="post && !post.get('thumbnail')" style="display: flex; align-items: center; justify-content: center;">
                                                    <i class="fa-duotone fa-solid fa-newspaper" style="font-size: 10em;"></i>
                                                </div>
                                            </div>
                                            <i v-if="post && post.get('pinned') === true" class="fa-solid fa-thumbtack" style="margin: 3px 0 0 2px; font-size: 1em; color: #fff; transform: rotate(45deg); position: absolute; top: 0; right: 5px;"></i>
                                            <div class="card__content">
                                                <div 
                                                    v-if="post && post.get('title')" 
                                                    class="card__title_v2" 
                                                    :style="{ 
                                                        'color': formatting_obj.title_color || '#000',
                                                        'font-weight': formatting_obj.title_styling && formatting_obj.title_styling.bold ? '600 !important' : '400 !important',
                                                        'font-style': formatting_obj.title_styling && formatting_obj.title_styling.italic ? 'italic' : 'normal',
                                                        'text-decoration': formatting_obj.title_styling && formatting_obj.title_styling.underline ? 'underline' : 'none',
                                                    }"
                                                >
                                                    {{ post.get('title') }}
                                                </div>
                                                <div 
                                                    v-if="post && post.get('subtitle')"
                                                    class="card__subtitle tinyMarginTop"
                                                    :style="{ 
                                                        'color': formatting_obj.subtitle_color || '#000',
                                                        'font-weight': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.bold ? '600 !important' : '400 !important',
                                                        'font-style': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.italic ? 'italic' : 'normal',
                                                        'text-decoration': formatting_obj.subtitle_styling && formatting_obj.subtitle_styling.underline ? 'underline' : 'none',
                                                    }"
                                                >
                                                    {{ post.get('subtitle') }}
                                                </div>
                                                <div class="card__date" :style="{ 'color': formatting_obj.date_color || '#000' }">{{ niceDate(post) }}</div>
                                                <div class="card__excerpt">
                                                    <a 
                                                        @click.stop 
                                                        :href="'/blog-post/' + post.id" 
                                                        :style="{
                                                            'font-variant': 'small-caps',
                                                            'opacity': '0.9',
                                                            'color': formatting_obj.date_color || '#000',
                                                            'border-bottom': 'none !important',
                                                            'text-decoration': 'underline !important',
                                                            'text-decoration-color': (formatting_obj.date_color || '#000') + ' !important'
                                                        }"
                                                    >
                                                        read more
                                                    </a>
                                                </div>
                                            </div>
                                        </article>
                                    </div>
                                </section>
                            </div>
                            <div 
                                v-if="has_more_posts"
                                class="view_more_button flexNoWrapCenter align-items-center"
                                :class="{'larchmont': is_larchmont || is_larchmont === 'true'}"
                                @click="view_all = true"
                                style="margin-bottom:0px;"
                            >
                                <div>
                                    <p>View more</p>
                                </div>
                                <i class="fa-regular fa-arrow-right easeFast"></i>
                            </div>
                        </div>
                    </template>
                    <div v-if="!loading && filtered_posts.length == 0" class="tableInsert hundop blog-list-contain">
                        <p class="noObjectsMSG withPadding textLeft blog-row flexWrapLeftAlign relative pointer">No posts found.</p>
                    </div>
                </div>         
                <div v-if="loading" class="cardBodySpinnerWrap active relative">
                    <div class="cardBodySpinner centeredBlock"></div>
                </div>
            </div>
        </div>
    </div>
</script>

<style>

    /*------------------------ view more buttons --------------------- */

    .view_more_button.card-layout{
        margin-top:0px;
    }
    .view_more_button{
        color: #6a7482;
        margin: 8px;
        border: 1px solid #e5eaec;
        border-top: 1px solid #e5eaec;
        border-radius: 5px;
        cursor: pointer;
        font-size: 16px;
        padding: 16px;
        margin-top: 8px;
    }
    .view_more_button:hover{
        color: #081333;
        background-color: #f8f9fb;
    }
    .view_more_button.larchmont{
        color: #fff;
        margin: 8px;
        border: 1px solid #fff;
        border-top: 1px solid #fff;
        border-radius: 5px;
        cursor: pointer;
        font-size: 16px;
        padding: 16px;
        margin-top: 8px;
    }
    .view_more_button.larchmont:hover{
        background-color: #002D62;
        color: #fff;
    }
    .view_more_button i{
        padding-left: 8px;
    }
    .view_more_button:hover i{
        color: #4a56f8;
        transform: translateX(4px);
    }

    /* -- end view more button --*/

    section.blog-list-cards-v2 {
        margin: 0 auto;
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-auto-rows: auto;
        grid-gap: 16px;
        align-content: center;
        justify-content: center;
        padding: 8px;
        width: 100%;
        box-sizing: border-box;
    }
    .blog-list-image-container {
        width: 100%;
        height: 300px;
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
        border-top-left-radius: 6px;
        border-top-right-radius: 6px;
        border-bottom-left-radius: 0px;
        border-bottom-right-radius: 0px;
        background-color: #f2f2f2;
    }
    .blog_post_thumbnail {
        width: 100%;
        height: 100%;
        object-fit: cover;
        display: block;
    }
    .default_image_icon {
        background-image: url('https://s3-us-west-2.amazonaws.com/myclubspot/upload-photo-icon.jpg');
        background-size: contain;
        background-position: center;
        background-repeat: no-repeat;
        width: 100%;
        height: 100%;
    }
    @media (max-width: 768px) {
        section.blog-list-cards-v2 {
            grid-template-columns: repeat(1, 1fr);
        }
    }
</style>

<script>

    store.components["blog_list"] = {
        allPosts: [],
        search: '',
        loading: true,
        view_all: false,
        post_limit: 6 //how many to show on initial load (before clicking "see more")
    };

    app_content.component("blog-list-component", {
        template: "#template-blog-list",
        data() {
            return store.components['blog_list']
        },
        props: {
            client_id: String,
            class_string: String,
            style_string: String,
            element_style_string: String,
            formatting: String,
            component_type: String,
            is_larchmont: Boolean, String,
            //admin
            component: Object,
            last_update: Number,
        },
        mounted() {
            this.loadBlogList( this.client_id )
        },
        methods: {
            go_to_post( post ){
                window.location.href = "blog-post/" + post.id;
            },
            loadBlogList( client_id, overrides = {} ){
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    //get new data
                    var params = {};
                    params["client_id"] = client_id;
                    params["overrides"] = overrides;
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(retrieved_posts => {
                    // sort with 'pinned' posts on top
                    this.allPosts = retrieved_posts.sort((a, b) => (a.get('pinned') === b.get('pinned') ? 0 : a.get('pinned') ? -1 : 1));
                    this.loading = false;
                    //and return
                    return Parse.Promise.as();
                }, error => {
                    checkParseError( error );
                });
                return thisPromise;
            },
            niceDate( postObject ){
                return dayjs(postObject.get('post_date')).format('MMM DD, YYYY');
            },
            return_grid_column_css(){
                if (window.innerWidth <= 990) {
                    //for mobile
                    return 'repeat(1, 256px)';
                } else {
                    return 'repeat(4, 256px)';
                }
            },
        },
        computed: {
            has_more_posts(){
                if( this.view_all ){
                    return false;
                }
                if( this.filtered_posts.length > this.post_limit ){
                    return true;
                }
                return false;
            },
            truncated_posts(){
                if( this.view_all ){
                    return this.filtered_posts;
                }else{
                    return this.filtered_posts.slice(0, this.post_limit);
                }
            },
            filtered_posts(){
                let val = this.search.toLowerCase();
                let filteredPosts = this.allPosts;
                // handle search results using all posts
                if (this.search.length > 0){
                    filteredPosts = this.allPosts.filter(post => {
                        let title = post.get('title').toLowerCase();
                        if ( title.includes(val) ){
                            return post;
                        }
                    })
                }
                return filteredPosts;
            },
            formatting_obj(){
                if (this.formatting){
                    return JSON.parse(this.formatting);
                }
                return {};
            },
        }
    })
</script>    <script type="text/html" id="template-custom-code">
    <template v-if="preview_element">
        <div class="cs-custom-code-wrap" :class="class_string">
            <textarea 
                @input="debounce(() => customCodeInputChanged($event))"
                @paste="debounce(() => customCodeInputChanged($event))"
                class="custom-code-textarea" 
                placeholder="Enter custom code here..."
                :value="custom_code_value"
            ></textarea>
        </div>
    </template>
    <template v-if="!preview_element">
        <span v-if="!loading" v-html="custom_code"></span>
    </template>
</script>

<script>    
    function createDebounce() {
        let timeout = null;
        return function (fnc, delayMs) {
            clearTimeout(timeout);
            timeout = setTimeout(() => {
                fnc();
            }, delayMs || 800);
        };
    }

    app_content.component('custom-code-component', {
        template: '#template-custom-code',
        data() {
            return {
                loading: true,
                debounce: createDebounce(),
                custom_code_value: '',
            }
        },
        props: {
            custom_code: String,
            //admin
            class_string: String,
            preview_element: {
                type: Boolean,
                default: false,
            },
            component: {
                type: Object,
                default: null,
            },
            last_update: Number,
        },
        mounted() {
            this.loading = false;
            if (this.preview_element){
                this.custom_code_value = this.component.get('config_latest').custom_code;
            }
        },
        methods: {
            customCodeInputChanged(event){
                let value = event.target.value;
                this.custom_code_value = value;
                save_changes_for_component( this.component, 'custom_code', value );
                //store.eventBus.$emit('saveChangesForComponent', this.component, 'custom_code', value, false)
            }
        },
    });
</script>    <script type="text/html" id="template-text">
    <div 
        v-memo="[last_element_update]"
        :class="[{'hidden': (column_index + 1) > number_of_columns }, 'text-column_' + column_index]"
        class="cs-text_text-wrap-column" 
        :data-column="column_index"
    >
        <template v-for="(element, element_index) in nice_elements">
            <template v-if="preview_element">
                <preview-element-component
                    :element="element"
                    :element_type="element.type"
                    :element_content="element.content"
                    :element_column_count="element.column_count"
                    :element_column_gap="element.column_gap"
                    :column_index="column_index"
                    :element_index="element_index"
                    :componentObject="component"
                ></preview-element-component>
            </template>
            <template v-if="!preview_element">
                <element-component
                    :element_type="element.type"
                    :element_content="element.content"
                    :element_column_count="element.column_count"
                    :element_column_gap="element.column_gap"
                ></element-component>
            </template>
        </template>
        <!-- handle case where there are no elements (admin only) -->
        <template v-if="preview_element && elements && elements.length == 0">
            <div class="no-elements-wrap">
                <div 
                    class="tapped-insert-new-element-relative" 
                    @click="tapped_add_element( $event )"
                >+</div>
            </div>
        </template>
    </div>
</script>

<script>
    app_content.component('text-component', {
        template: '#template-text',
        data() {
            return {}
        },
        props: {
            number_of_columns: [String, Number],
            preview_element: Boolean,
            component: Object,
            last_update: Number, //last component update
            last_element_update: Number, //last element update
            elements: Array,
            column_prop: String,
            column_index: Number,
        },
        methods:{
            tapped_add_element(){
                var params = {};
                params["component"] = this.component;
                params["insert_after"] = 0;
                params["column_index"] = this.column_index;
                handle_add_element( params );
            }
        },
        computed: {
            nice_elements(){
                var nice_elements = [];

                if (this.elements){
                    nice_elements = this.elements;
                } else if (this.column_prop && typeof this.column_prop === 'string'){
                    nice_elements = JSON.parse(unescape(decodeURIComponent(this.column_prop)));
                } 
                return nice_elements;
            }
        },
    });
</script>    <script type="text/html" id="template-image-with-text">
    <div ref="animationTarget" class="cs-image-with-text flexWrap relative delay5s" :class="[class_string, { 'scroll-fade': !is_admin && !tab_element }, { 'view_hidden': ! is_admin && ( !formatting_obj.animation || formatting_obj.animation !== 'none' ) }, { 'background': image_mat === 'hide' }]" :style="style_string">
        <template v-if="!loading && left_right_orientation === 'right'">
            <!-- text first (image on the right) -->
            <div class="cs-image-with-text_text-wrap flexGrowOne">
                <div :style="element_style_string">
                    <div v-memo="Object.keys(elements_obj)" class="element-wrapper">
                        <template v-for="(element, element_index) in elements_obj">
                            <template v-if="preview_element">
                                <preview-element-component
                                    :element="element"
                                    :element_type="element.type"
                                    :element_content="element.content"
                                    :element_column_count="element.column_count"
                                    :element_column_gap="element.column_gap"
                                    :element_index="element_index"
                                    :componentObject="component"
                                ></preview-element-component>
                            </template>
                            <template v-if="!preview_element">
                                <element-component
                                    :element_type="element.type"
                                    :element_content="element.content"
                                    :element_column_count="element.column_count"
                                    :element_column_gap="element.column_gap"
                                ></element-component>
                            </template>
                        </template>
                        <!-- handle case where there are no elements (admin only) -->
                        <template v-if="preview_element && elements_obj && elements_obj.length == 0">
                            <div class="no-elements-wrap">
                                <div 
                                    class="tapped-insert-new-element-relative" 
                                    @click="tapped_add_element( $event )"
                                >+</div>
                            </div>
                        </template>
                    </div>
                </div>
            </div>
            <div class="cs-image-with-text_image-wrap flexGrowOne">
                <div class="cs-image-with-text_image-wrap-inner">
                    <div :style="check_full_background()" class="cs-image-with-text_image-slider-outer">
                        <div 
                            v-if="formatting_obj.background_size !== 'full'" 
                            :class="['cs-image-with-text-image-mat', { background: image_mat === 'show' }]"
                        ></div>
                        <image-slider-component
                            :client_id="client_id"
                            :formatting="formatting"
                            :images_string="images_string"
                            :preview_element="preview_element"
                            :component="component"
                            :last_update="last_update"
                        ></image-slider-component>
                    </div>
                </div>
            </div>
        </template>
        <template v-if="!loading && left_right_orientation === 'left'">
            <!-- image first (text on the right) -->
            <div class="cs-image-with-text_image-wrap flexGrowOne">
                <div class="cs-image-with-text_image-wrap-inner">
                    <div :style="check_full_background()" class="cs-image-with-text_image-slider-outer">
                        <div 
                            v-if="formatting_obj.background_size !== 'full'" 
                            :class="['cs-image-with-text-image-mat', { background: image_mat === 'show' }]"
                        ></div>
                        <image-slider-component
                            :client_id="client_id"
                            :formatting="formatting"
                            :images_string="images_string"
                            :preview_element="preview_element"
                            :component="component"
                            :last_update="last_update"
                        ></image-slider-component>
                    </div>
                </div>
            </div>
            <div class="cs-image-with-text_text-wrap flexGrowOne">
                <div :style="element_style_string">
                    <div 
                        v-memo="[last_element_update]" 
                        class="element-wrapper"
                    >
                        <template v-for="(element, element_index) in elements_obj">
                            <template v-if="preview_element">
                                <preview-element-component
                                    :element="element"
                                    :element_type="element.type"
                                    :element_content="element.content"
                                    :element_column_count="element.column_count"
                                    :element_column_gap="element.column_gap"
                                    :element_index="element_index"
                                    :componentObject="component"
                                ></preview-element-component>
                            </template>
                            <template v-if="!preview_element">
                                <element-component
                                    :element_type="element.type"
                                    :element_content="element.content"
                                    :element_column_count="element.column_count"
                                    :element_column_gap="element.column_gap"
                                ></element-component>
                            </template>
                        </template>
                        <!-- handle case where there are no elements (admin only) -->
                        <template v-if="preview_element && elements_obj && elements_obj.length == 0">
                            <div class="no-elements-wrap">
                                <div 
                                    class="tapped-insert-new-element-relative" 
                                    @click="tapped_add_element( $event )"
                                >+</div>
                            </div>
                        </template>
                    </div>
                </div>
            </div>
        </template>
    </div>
</script>

<style>
    .delay5s{
        animation-delay: 0.5s;
    }
    
    .view_hidden{
        opacity: 0;
    }

    @keyframes fade-left-right {
        0% {
            opacity: 0;
            transform: translateX(-100%) scaleX(0.5);
        }
        100% {
            opacity: 1;
            transform: translateX(0) scaleX(1);
        }
    }

    @keyframes fade-right-left {
        0% {
            opacity: 0;
            transform: translateX(100%) scaleX(0.5);
        }
        100% {
            opacity: 1;
            transform: translateX(0) scaleX(1);
        }
    }

    .fade-left-right {
        animation: fade-left-right 1s ease-in-out forwards;
    }

    .fade-right-left {
        animation: fade-right-left 1s ease-in-out backwards;
    }
</style>

<script>
    app_content.component('image-with-text-component', {
        template: '#template-image-with-text',
        data() {
            return {
                is_admin: false,
                loading: true,
            }
        },
        props: {
            class_string: String,
            style_string: String,
            element_style_string: String,
            elements_string: [String, Object],
            left_right_orientation: String,
            image_mat: String,
            //image slider
            client_id: String,
            formatting: String,
            images_string: String,
            //admin
            preview_element: Boolean,
            component: Object,
            last_update: Number, //last component update
            last_element_update: Number, //last element update
            tab_element: Boolean,
        },
        mounted() {
            this.loading = false;
            this.is_admin = window.location.href.indexOf('website-builder') !== -1;
        },
        updated(){
            this.createIntersectionObserver();
        },
        methods: {
            check_full_background(){
                if ( this.formatting_obj && this.formatting_obj.background_size === 'full' ){
                    return {
                        top: 0,
                        bottom: 0,
                        left: 0,
                        right: 0,
                    }
                }
            },
            tapped_add_element(){
                var params = {};
                params["component"] = this.component;
                params["insert_after"] = 0;
                params["column_index"] = 0;
                handle_add_element( params );
            },
            createIntersectionObserver(){
                const options = {
                    root: null, 
                    rootMargin: '0px',
                    threshold: 0.5 //trigger animation when at least 50% of the target is visible
                };
                const observer = new IntersectionObserver(this.handleIntersection, options);
                //observe the target element
                observer.observe(this.$refs.animationTarget);
            },
            handleIntersection(entries, observer) {
                entries.forEach(entry => {
                    //check if target is intersecting
                    if (entry.isIntersecting) {
                        //apply animation class
                        entry.target.classList.add(this.formatting_obj.animation);
                        entry.target.classList.remove('view_hidden');
                        //stop observing to prevent re-triggering
                        observer.unobserve(entry.target);
                    }
                });
            },
        },
        computed: {
            elements_obj(){
                if (this.elements_string && typeof this.elements_string === 'string'){
                    return JSON.parse(unescape(decodeURIComponent(this.elements_string)));
                } else if (this.elements_string){
                    return this.elements_string;
                } else {
                    return {};
                }
            },
            formatting_obj(){
                if (this.formatting){
                    return JSON.parse(this.formatting);
                } else {
                    return {};
                }
            },
        },
    });
</script>    <script type="text/html" id="template-image-slider">
    <div class="cs-image-slider-wrap background">
        <div 
            class="cs-image-slider"
            :class="[ 'cs-image-slider-' + filtered_images_length, 'cs-image-slider_' + client_id ]"
            :data-client-id="client_id" 
            data-interval="8000" 
            data-slider-index="0"
        >
            <!-- now add the images -->
            <template v-if="!loading && filtered_images_length > 0" v-for="(image, index) in filtered_images">
                <template v-if="image && typeof image !== 'object'">
                    <template v-if="image && image.indexOf('video') >= 1">
                        <div
                            class="cs-image-slider-card"
                            :class="[
                                'cs-image-slider-card-' + index,
                                { 'active': index === display_index }
                            ]"
                            style="display:flex;align-items:center;justify-content:center;"
                        >
                            <video class="cs-background-video" autoplay playsinline loop muted :src="image" style="display:initial;"></video>
                        </div>
                    </template>
                    <template v-if="image && typeof image === 'string'">
                        <div
                            class="cs-image-slider-card"
                            :class="[
                                'cs-image-slider-card-' + index,
                                { 'active': index === display_index }
                            ]"
                        >
                            <div class="cs-background-image-photo" :style="`background-image: url(${image})`"></div>
                        </div>
                    </template>
                </template>
                <template v-if="(component && component.get('type') === 'image-with-text') && !image">
                    <div 
                        class="cs-image-slider-card"
                        :class="[
                            'cs-image-slider-card-' + index,
                            { 'active': index === 0 }
                        ]"
                    >
                        <div class="cs-background-image-photo default-image-icon" style="background-size:30%!important;"></div>
                    </div>
                </template>
            </template>
            <template v-if="formatting_obj.overlay_opacity">
                <div class="cs-image-overlay" :style="{ 'opacity': formatting_obj.overlay_opacity / 100 }"></div>
            </template>
        </div>
    </div>
</script>

<script>    
    /* ----- COMPONENT ----- */
    app_content.component('image-slider-component', {
        template: '#template-image-slider',
        data() {
            return {
                loading: true,
                display_index: 0,
            }
        },
        props: {
            client_id: String,
            formatting: String,
            images_string: String,
            //for preview element
            preview_element: {
                type: Boolean,
                default: false,
            },
            component: {
                type: Object,
                default: null,
            },
            last_update: {
                type: Number,
                default: null,
            },
        },
        mounted() {
            this.loading = false;
        },
        created(){
            setInterval(() => {
                if (!this.preview_element){
                    if (this.display_index < this.filtered_images_length - 1){
                        this.display_index++;
                    } else {
                        this.display_index = 0;
                    }
                }
            }, 8000);
        },
        computed: {
            formatting_obj(){
                if (this.formatting){
                    return JSON.parse(this.formatting);
                }
            },
            filtered_images(){
                if (!this.preview_element){
                    return JSON.parse(this.images_string).filter(image => { if ( image !== null ) return image; });
                } else {
                    return JSON.parse(this.images_string);
                }
                return [];
            },
            filtered_images_length(){
                if (!this.preview_element){
                    return JSON.parse(this.images_string).filter(image => { if ( image !== null ) return image; }).length;
                } else {
                    return JSON.parse(this.images_string).length;
                }
                return 0;
            },
        },
        watch: {
            last_update(newVal, oldVal){
                if (newVal !== oldVal){
                    let display_index = this.component.get('config_latest')?.display_index || 0;
                    this.display_index = display_index;
                }
            },
        }
    });
</script>    <script type="text/html" id="template-hero-banner">
    <div class="cs-background-image background relative" :class="[class_string, { 'scroll-fade': !is_admin && !tab_element }]" :style="style_string">
        <image-slider-component
            :client_id="client_id"
            :formatting="formatting"
            :images_string="images_string"
            :preview_element="preview_element"
            :component="component"
            :last_update="last_update"
        ></image-slider-component>
        <div 
            class="element-wrapper" 
            :class="'element-wrapper_' + component_type" 
            :style="element_style_string"
        >
            <div v-memo="[last_element_update]">
                <!-- loop through elements -->
                <template v-for="(element, element_index) in elements_obj">
                    <template v-if="preview_element">
                        <preview-element-component
                            :element="element"
                            :element_type="element.type"
                            :element_content="element.content"
                            :element_column_count="element.column_count"
                            :element_column_gap="element.column_gap"
                            :element_index="element_index"
                            :componentObject="component"
                        ></preview-element-component>
                    </template>
                    <template v-if="!preview_element">
                        <element-component
                            :element_type="element.type"
                            :element_content="element.content"
                            :element_column_count="element.column_count"
                            :element_column_gap="element.column_gap"
                        ></element-component>
                    </template>
                </template>
                <!-- handle case where there are no elements (admin only) -->
                <template v-if="preview_element && elements_obj.length == 0">
                    <div class="no-elements-wrap">
                        <div 
                            class="tapped-insert-new-element-relative" 
                            @click="tapped_add_element( $event )"
                        >+</div>
                    </div>
                </template>
            </div>
        </div>
    </div>
</script>

<script>
    app_content.component('hero-banner-component', {
        template: '#template-hero-banner',
        data() {
            return {
                is_admin: false,
                loading: true,
            }
        },
        props: {
            class_string: String,
            style_string: String,
            element_style_string: String,
            component_type: String,
            elements_string: [String, Object],
            //image slider
            client_id: String,
            formatting: String,
            images_string: String,
            //admin
            preview_element: Boolean,
            component: Object,
            last_update: Number, //last component update
            last_element_update: Number, //last element update
            tab_element: Boolean,
        },
        mounted() {
            this.loading = false;
            this.is_admin = window.location.href.indexOf('website-builder') !== -1;
        },
        methods:{
            tapped_add_element(){
                var params = {};
                params["component"] = this.component;
                params["insert_after"] = 0;
                params["column_index"] = 0;
                handle_add_element( params );
            }
        },
        computed: {
            elements_obj(){
                if (this.elements_string && typeof this.elements_string === 'string'){
                    return JSON.parse(unescape(decodeURIComponent(this.elements_string)))
                } else {
                    return this.elements_string
                }
                return [];
            },
        },
    });
</script>    <script type="text/html" id="template-element">
    <template v-if="element_type === 'accordion_header'">
        <div class="cs-accordion-header">
            <div class="cs-accordion-header-toggle-wrap flexWrap">
                <div class="cs-accordion-header-toggle">+</div>
            </div>
            <span v-html="element_content"></span>
        </div>
    </template>
    <template v-if="element_type === 'accordion_body'">
        <div 
            class="cs-accordion-body"
            v-html="element_content"
            :style="`column-count: ${element_column_count} !important; column-gap: ${element_column_gap}em;`"
        ></div>
    </template>
    <template v-else-if="element_type !== 'accordion_header' && element_type !== 'accordion_body'">
        <div :style="`column-count: ${element_column_count} !important; column-gap: ${element_column_gap}em;`">
            <span v-html="element_content"></span>
        </div>
    </template>
</script>

<script>
    app_content.component('element-component', {
        template: '#template-element',
        data() {
            return {
                loading: true,
            }
        },
        props: {
            element_type: String,
            element_content: String,
            element_column_count: Number,
            element_column_gap: Number,
        },
        mounted() {
            this.loading = false;
        },
    });
</script>    <script type="text/html" id="template-unlayer-component">    
    <template v-if="preview_element">
        <div class="cs-unlayer-component-wrap unlayer-content" :class="class_string">
            <!-- hover button to open unlayer builder -->
            <div class="darken-overlay easeFast">
               <div class="hover-toolbar">          
                   <div class="hover-button flexNoWrap centeredBlock pointer" @click="openUnlayerBuilder()">
                       <div class="hover-button-text">
                           Update <i class="fa-regular fa-pen-to-square" style="padding-left:3px;"></i>
                       </div>
                   </div>
               </div>
           </div>
            <!-- if there is content -->
            <div v-if="!loading && unlayerHtml" class="relative" >
                <div 
                    :id="'freeform_id_' + component.id"  
                    v-html="return_html_with_css()"
                ></div>
            </div>
            <!-- if there is no content -->
            <div v-else-if="!loading">
                <div class="addFreeformContentZone" @click="openUnlayerBuilder()">
                    <div 
                        class="quick-action-wrap noMaxWidth centeredBlock"
                    >
                        <div class="quick-action-icon-wrap">
                            <i class="fa-light fa-scribble"></i>
                        </div>
                        <p class="quick-action-title" style="font-family:roboto;">Freeform section</p>
                    </div>
                </div>
            </div>
        </div>
    </template>
    <template v-if="!preview_element">
        <div class="cs-unlayer-component-wrap">
            <div class="relative"></div>
            <div v-if="!loading" v-html="return_html_with_css()"></div>
        </div>
    </template>
</script>

<script>

    function createDebounce() {
        let timeout = null;
        return function (fnc, delayMs) {
            clearTimeout(timeout);
            timeout = setTimeout(() => {
                fnc();
            }, delayMs || 800);
        };
    }
    app_content.component('unlayer-component', {
        template: '#template-unlayer-component',
        data() {
            return {
                unlayerHtml: null,
                loading: true,
                debounce: createDebounce(),
                template: null,
                unlayer: '',
            }
        },
        props: {
            unlayer_chunks: Object,
            class_string: String,
            preview_element: {
                type: Boolean,
                default: false,
            },
            component: {
                type: Object,
                default: null,
            },
        },
        mounted() {
            if(!this.unlayer_chunks){       
                // find template for component id
                this.return_unlayer_data()
            }
            this.loading = false;
        },
        methods: {
            return_unlayer_data(){
                if(this.component.get('config_latest') && this.component.get('config_latest').unlayer_component.chunks){                
                    this.unlayerHtml = this.component.get('config_latest').unlayer_component.chunks.body
                    this.unlayerHtml = this.unlayerHtml.replace('style="min-height: 100vh;', 'style="min-height: auto;');
                }
            },
            openUnlayerBuilder(){
                var jsonContent
                if(this.component.get('config_latest') && this.component.get('config_latest').unlayer_component){
                    jsonContent = this.component.get('config_latest').unlayer_component.design
                }
                var params = {
                    jsonContent: jsonContent,
                    fn: this.saveUnlayerContent
                }
                launch_unlayer_builder(params)
            },
            saveUnlayerContent(content){
                var promise = Promise.resolve().then(() => {
                    var htmlContent = content.chunks.body
                    htmlContent = htmlContent.replace('style="min-height: 100vh;', 'style="min-height: auto;');
                    this.unlayerHtml = htmlContent
                    save_changes_for_component( this.component, 'unlayer_component', content );
                })
                return promise;
            }, 
            return_html_with_css(){
                let data
                if(this.preview_element){
                    data = this.component.get('config_latest').unlayer_component.chunks
                }else{
                    data = this.unlayer_chunks
                }
                var css = data.css
                var body = data.body
                let html_with_css = juice.inlineContent(body, css);
                html_with_css = html_with_css.replace('100vh', 'auto')
                return html_with_css
            }        
        },
        computed: {
              
        }
    });
</script>

<style scoped>

    @media screen and (max-width: 768px) {
        .u-row {
            flex-wrap: wrap !important; /* Allow columns to wrap */
        }
        .u-col {
            flex: 0 0 50% !important; /* Two columns per row */
            max-width: 50% !important;
        }
    }
    @media screen and (max-width: 480px) {
        .u-col {
            flex: 0 0 100% !important; /* One column per row */
            max-width: 100% !important;
        }
    }

</style>    <script type="text/html" id="template-form">
    <div class="form-wrapper centeredBlock centeredText">
        <template v-if="!loading && is_admin">
            <div
                v-if="!form_id"
                @click="link_form()"
                class="noObjectsMSG centeredBlock centeredText"
                style="padding: 5em;"
            >
                <p style="cursor: pointer;"><i class="fa-light fa-list-dropdown smallMarginRight"></i>Click to link a form</p>
            </div>
        </template>
        <template v-if="!loading">
            <div 
                v-if="form_id && json_form" 
                id="form-template"
                class="cs-min-section-width"
                :style="{ 'max-width': formatting_obj.section_width + '%' }"
            >
                <div
                    class="form-color-theme"
                    :style="{ 'background-color': color_theme }">
                </div>
                <div class="form-header-wrapper">
                    <!-- name -->
                    <div v-if="json_form && json_form.name" class="form-name flex-row-start">
                        <h3 class="default-font-css" style="font-size: 32px; padding: 5px; text-align: left;">{{ json_form.name }}</h3>
                    </div>
                    <!-- description -->
                    <div v-if="json_form && json_form.description" class="form-description flex-row-start tinyMarginTop">
                        <p class="default-font-css" style="padding: 5px; text-align: left;">{{ json_form.description }}</p>
                    </div>
                    <template v-if="!valid_membership">
                        <div
                            @click="tapped_log_in()"
                            class="noObjectsMSG leftText"
                            style="padding: 5px; min-width: fit-content;"
                        >
                            <p style="cursor: pointer;"><i class="fa-light fa-circle-exclamation smallMarginRight"></i>This form is restricted to members only. Please <a :href="login_url">click here to log in</a> and view this form.</p>
                        </div>
                    </template>
                </div>

                <template v-if="valid_membership">

                    <!-- default fields -->
                    <template v-if="collect_default_fields && selected_fields.length > 0">
                        <default-field-component-wb
                            :form="json_form"
                            :is_admin="is_admin"
                            :default_fields="selected_fields"
                            :rerender_key="rerender_key"
                        ></default-field-component-wb>
                    </template>
                    <!-- custom fields -->
                    <template v-if="json_form.custom_fields" v-for="(custom_field, index) in custom_fields">
                        <custom-field-component-wb
                            :id="custom_field.id"
                            :form="json_form"
                            :is_admin="is_admin"
                            :custom_field="custom_field"
                            :last_update="last_update"
                            ref="custom_field_components"
                            @field-updated="handle_field_update"
                        ></custom-field-component-wb>
                    </template>
                    <!-- submit -->
                    <div style="width: 100%; display: flex; justify-content: space-between; align-items: center;" class="tinyMarginTop">
                        <button 
                            v-if="!loading_submission"
                            @click="tapped_submit_form()"
                            :style="{ 'background-color': button_disabled ? 'var(--custom-field-grey-2)' : color_theme }"
                            :class="[ 'default-font-css', 'submit-button', { 'inactive': button_disabled } ]"
                            :disabled="is_admin"
                        >Submit</button>
                        <i 
                            v-if="loading_submission"
                            class="fa-sharp-duotone fa-solid fa-spinner-third fa-spin smallMarginLeft"
                            :style="{ 'color': color_theme, 'font-size': '1.2em', 'animation-duration': '1.2s' }"
                        ></i>
                        <p 
                            @click="!loading_submission && tapped_clear_form()"
                            :style="{ 'color': loading_submission ?  'var(--custom-field-grey-2)': color_theme }"
                            style="font-size: 14px; font-weight: 600; cursor: pointer;"
                        >Clear form</p>
                    </div>
                </template>
            </div>
            <div
                v-if="form_id && !json_form" 
                class="noObjectsMSG centeredBlock centeredText"
                style="padding: 5em;"
            >
                <p style="cursor: pointer;"><i class="fa-light fa-list-dropdown smallMarginRight"></i>No form found.</p>
            </div>
        </template>
    </div>
</script>

<style>
   
    #form-template{
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: flex-start;
        margin: 0.5em 0.5em 1em 0.5em;
        padding: 0 0 1.5em 0;
        width: 100%;
        max-width: 700px; 
        height: 100%;
    }
    #form-template .form-color-theme{
        color: #fff;
        height: 10px;
        border-top-left-radius: 8px;
        border-top-right-radius: 8px;
        width: 100%;
        padding: 0 1.5em 0 1.5em;
        box-sizing: border-box;
    }
    #form-template .default-font-css{
        font-family: Roboto, Arial, Helvetica, sans-serif;
        font-size: 16px;
        font-weight: 400;
    }
    #form-template .flex-row-start{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
    }
    #form-template .submit-button{
        color: #fff; 
        border-radius: 6px; 
        font-size: 14px; 
        padding: 8px 24px; 
        cursor: pointer;
        border: none;
    }
    #form-template .submit-button.inactive{
        color: #fff; 
        border-radius: 6px; 
        font-size: 14px; 
        padding: 8px 24px; 
        cursor: auto;
        border: none;
    }
    .form-wrapper{
        display: flex;
        align-items: center;
        justify-content: center;
        height: fit-content;
        width: 100%;
    }    
    .form-header-wrapper{
        border-width: 0px 1px 1px 1px;
        border-color: rgba(195, 195, 195, 0.7);
        border-style: solid;
        width: 100%;
        border-bottom-left-radius: 8px;
        border-bottom-right-radius: 8px;
        padding: 1.45em;
        box-sizing: border-box;
    }
    .form-name{
        color: rgb(32, 33, 36);
        box-sizing: border-box;
        font-weight: 400;
        font-size: 32px;
        width: 100%;
        min-height: 21px;
        border-bottom: 1.5px solid transparent;
        transition: border-bottom 0.1s;
    }
    .form-description{
        color: rgb(32, 33, 36);
        box-sizing: border-box;
        font-weight: 400;
        font-size: 14px;
        width: 100%;
        line-height: 1.5;
        letter-spacing: 0;
        min-height: 21px;
        border-bottom: 1.5px solid transparent;
        transition: border-bottom 0.1s;
    }
    .form-name.input-is-focused, .form-description.input-is-focused{
        border-bottom: 1.5px solid rgba(195, 195, 195, 0.7);
    }
</style>

<script>
    app_content.component("form-component", {
        template: "#template-form",
        data() {
            return {
                global: store,
                loading: false,
                loading_submission: false,
                json_form: null,
                invalid_membership: false,
                selected_fields: [
                    {
                        label: 'First name',
                        value: 'firstName',
                        selected: false,
                        input_value: null,
                    },
                    {
                        label: 'Last name',
                        value: 'lastName',
                        selected: false,
                        input_value: null,
                    },
                    {
                        label: 'Email',
                        value: 'email',
                        selected: false,
                        input_value: null,
                    },
                    {
                        label: 'Mobile',
                        value: 'mobile',
                        selected: false,
                        input_value: null,
                    },
                ], 
                login_url: null,
            };

        },
        props: {
            client_id: String,
            is_admin: Boolean,
            component: Object,
            form: Object,
            formatting: String,
            last_update: String,
        },
        mounted() {
            this.load_forms( this.client_id );
        },
        methods: {
            load_forms( client_id, overrides = {} ){
                this.loading = true;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    var params = {};
                    params["client_id"] = client_id;
                    params["form_id"] = this.form_id;
                    params["overrides"] = overrides;
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(retrieved_form => {
                    this.json_form = retrieved_form;
                    if(this.json_form.members_only){
                        //check if theres a logged in member and redirect them if needed
                        return this.check_valid_membership().then(is_member => {
                            if(is_member){
                                this.invalid_membership = false;
                                this.set_default_fields();
                                return Parse.Promise.as();
                            }
                        }).catch(error => {
                            if(error === "invalid_membership"){
                                this.invalid_membership = true;
                                this.loading = false;
                                this.set_login_url();
                                // return the error
                                return Parse.Promise.error("invalid_membership");
                            }
                        });
                    }else{
                        this.set_default_fields();
                        return Parse.Promise.as();
                    }
                    
                }).then(() => {
                    this.loading = false;
                }, error => {
                    checkParseError(error);
                    this.loading = false;
                });
                return thisPromise;
            },
            check_valid_membership(){
                var club_id = $('body').data('clubId');
                var user = Parse.User.current();

                var memberObject;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    if( user && user.get('memberObject') ){
                        //ok, get the member and membership
                        var query = new Parse.Query("members");
                        query.select('membershipObject.status');
                        query.select('membershipObject.memberNumber');
                        query.select('membershipObject.tierObject');
                        query.select('clubObject.web_settings.custom_domain');
                        query.include('membershipObject');
                        query.include('clubObject.web_settings');
                        return query.get( user.get('memberObject').id );
                    }else{
                        //redirect to login
                        return Promise.reject("invalid_membership");
                    }
                }).then(( retrievedMember )=>{
                    if( retrievedMember && retrievedMember.get('clubObject')?.id == club_id ){
                        //ok, they're legit
                        memberObject = retrievedMember;
                    }

                    if( ! memberObject ){
                        //redirect to login
                        return Promise.reject("invalid_membership");
                    }
                    //check membership
                    let membershipObject = memberObject.get('membershipObject');
                    if( ! membershipObject ){
                        return Promise.reject("invalid_membership");
                    }
                    if( membershipObject.get('status') == "canceled" ){
                        return Promise.reject("invalid_membership");
                    }   
                    var valid_membership = true;
                    //ok, they're a legit member
                    return Parse.Promise.as(valid_membership);
                });
                return thisPromise;
            },
            set_login_url(){
                const clubId = $('body').data('clubId'); // or wherever you're storing it
                const query = new Parse.Query("clubs");
                query.include("web_settings");
                query.get(clubId).then(club => {
                    const webSettings = club.get('web_settings');
                    const customDomain = webSettings?.get('custom_domain');
                    const currentUrl = window.location.href;

                    let redirectBase = customDomain
                        ? `https://${customDomain}`
                        : "https://theclubspot.com";

                    const loginUrl = `${redirectBase}/login?next=${encodeURIComponent(currentUrl)}&msg=${encodeURIComponent("Please log in to view and complete this form.")}`;
                    this.login_url = loginUrl;
                });


            },
            tapped_clear_form(){
                if ( this.collect_default_fields && this.selected_fields.length > 0 ){
                    this.selected_fields.flat().forEach(default_field => {
                        default_field.input_value = null;
                    })
                }
                if ( this.custom_fields ){
                    this.custom_fields.forEach(custom_field => {
                        custom_field.input_value = null;
                        if ( custom_field.custom_field_options ){
                            custom_field.custom_field_options.forEach(custom_field_option => {
                                custom_field_option.selected = false;
                            })
                        }
                        if ( custom_field.type === 'select' ){
                            let target_custom_field_component = this.$refs.custom_field_components.find(ref => {
                                if ( ref.custom_field.id === custom_field.id ){
                                    ref.clear_dropdown_index();
                                }
                            })
                        }
                    })
                }
            },
            async tapped_submit_form(){
                if ( this.button_disabled ){
                    return displayMessage("Required fields are missing.", true, 4000);
                } 
                let club_id = $('body').data('clubId');
                if ( !club_id || !this.form_id ){
                    return displayMessage("There was an issue submitting your form. Please try again, or contact support if the problem persists.", true, 4000);
                }
                //update ui
                this.loading_submission = true;
                //create new instance
                const formResponseInstance = Parse.Object.extend('form_responses');
                let new_response = new formResponseInstance();
                new_response.set('clubObject', {
                    "__type": "Pointer",
                    "className": "clubs",
                    "objectId": club_id
                });
                new_response.set('formObject', {
                    "__type": "Pointer",
                    "objectId": this.form_id,
                    "className": "forms"
                });
                new_response.set('archived', false);
                if ( this.collect_default_fields && this.selected_fields.length > 0 ){
                    this.selected_fields.flat().forEach(field => {
                        new_response.set(field.value, field.input_value || '')
                    })
                }
                //save
                return new_response.save().then(async saved_form_response => {
                    let form_response_id = saved_form_response.id;
                    if ( this.custom_fields ){
                        let customFieldsArray = await this.create_custom_field_responses( this.custom_fields, club_id, saved_form_response );
                        saved_form_response.set('customFieldsArray', customFieldsArray);
                        //set the acl
                        var acl = new Parse.ACL();
                        acl.setPublicWriteAccess(false);
                        acl.setPublicReadAccess(false);
                        acl.setRoleReadAccess(`club_basic_${club_id}`, true);
                        acl.setRoleWriteAccess(`club_basic_${club_id}`, true);
                        saved_form_response.setACL( acl );
                        //and save it
                        saved_form_response.save().then(saved_form_response_with_custom_fields_arr => {
                            if (saved_form_response_with_custom_fields_arr){
                                var params = {};
                                params["form_response_id"] = saved_form_response_with_custom_fields_arr.id;
                                return Parse.Cloud.run('send_notification_for_form_response', params);
                            }
                        }).catch(error => {
                            checkParseError(error);
                            displayMessage(`There was an error with your form submission: ${error}`, true, 6000);
                        });
                    }
                    //update ui
                    this.loading_submission = false;
                    displayMessage('Your response has been successfully submitted', false, 6000);
                    //clear all inputs to avoid resubmission
                    this.tapped_clear_form();
                }).catch(error => {
                    this.loading_submission = false;
                    checkParseError(error);
                    displayMessage(error, true, 4000);
                })
            },
            async create_custom_field_responses( custom_fields, club_id, form_response ){
                if ( custom_fields && custom_fields.length > 0 ){
                    let custom_field_responses = [];
                    for ( let i = 0; i < custom_fields.length; i++ ){
                        let custom_field = custom_fields[i];
                        //create new instance
                        const customFieldResponseInstance = Parse.Object.extend('customFieldResponses');
                        let new_custom_field_response = new customFieldResponseInstance();
                        //set the acl
                        var acl = new Parse.ACL();
                        acl.setPublicWriteAccess(false);
                        acl.setPublicReadAccess(false);
                        acl.setRoleReadAccess(`club_basic_${club_id}`, true);
                        acl.setRoleWriteAccess(`club_basic_${club_id}`, true);
                        new_custom_field_response.setACL( acl );
                        //continue
                        new_custom_field_response.set('clubObject', {
                            "__type": "Pointer",
                            "objectId": club_id,
                            "className": "clubs"
                        });
                        new_custom_field_response.set('form', {
                            "__type": "Pointer",
                            "objectId": this.form_id,
                            "className": "forms"
                        });
                        new_custom_field_response.set('form_response', form_response);
                        new_custom_field_response.set('custom_field', {
                            "__type": "Pointer",
                            "objectId": custom_field.id,
                            "className": "customFields"
                        });
                        new_custom_field_response.set('field_name', custom_field.name || '');
                        new_custom_field_response.set('field_type', custom_field.type);
                        new_custom_field_response.set('field_is_required', custom_field.required);
                        if ( custom_field.type === 'text' || custom_field.type === 'textarea' || custom_field.type === 'number' ){
                            new_custom_field_response.set('response', custom_field.input_value ? custom_field.input_value.toString() : '');
                        }else if ( custom_field.type === 'radio' || custom_field.type === 'select' || custom_field.type === 'checkbox' ){
                            if ( custom_field.custom_field_options ){
                                let selected_options = [];
                                for ( let i = 0; i < custom_field.custom_field_options.length; i++ ){
                                    let option = custom_field.custom_field_options[i];
                                    if ( option.selected === true ){
                                        selected_options.push({
                                            option_id: option.id,
                                            option_name: option.name || '',
                                        });
                                    }
                                }
                                new_custom_field_response.set('selected_options', selected_options);
                            }
                        }else if ( custom_field.type === 'file_upload' ){
                            let file = custom_field.input_value;
                            if ( file && file.name ){
                                try {
                                    const document = await this.process_file_upload( file, form_response, acl );
                                    new_custom_field_response.set('document', document);
                                    new_custom_field_response.set('field_url', 'https://theclubspot.com/document/' + document.id || null);
                                } catch(error) {
                                    displayMessage("Sorry, something went wrong uploading your file. Please try again, or contact support if the problem persists.", true, 3000);
                                    throw error;
                                }
                            }
                        }
                        await new_custom_field_response.save().then(saved_response => {
                            custom_field_responses.push(saved_response);
                        }).catch(error => {
                            checkParseError(error);
                            displayMessage(error, true, 4000);
                        })
                    }
                    return await custom_field_responses;
                }
            },
            process_file_upload( file, form_response, acl ){
                return upload_private_file_v2({
                    file: file,
                    fileName: file.name
                }).then((result)=>{
                    let {
                        url,
                        file_key
                    } = result;
                    var docsInstance = Parse.Object.extend("documents");
                    var newDoc = new docsInstance();
                    newDoc.set('form_response', form_response);
                    newDoc.set('name', file.name);
                    newDoc.set('active', true);
                    newDoc.set('archived', false);
                    newDoc.set('file_key', file_key);
                    newDoc.set('private', true);
                    if( Parse.User.current() ){
                        newDoc.set('created_by', Parse.User.current() )
                    } 
                    newDoc.set('type', 'custom_field_response');
                    newDoc.setACL( acl );
                    newDoc.set('URL', url);
                    newDoc.set('clubObject', form_response.get('clubObject'));
                    return newDoc.save();
                });
            },
            returnIsVideo(filename) {
                var ext = this.getExtension(filename);
                switch (ext.toLowerCase()) {
                    case 'm4v':
                    case 'avi':
                    case 'mpg':
                    case 'mp4':
                    case 'mp3':
                    case 'mov':
                    // etc
                    return true;
                }
                return false;
            },
            getExtension(filename) {
                var parts = filename.split('.');
                return parts[parts.length - 1];
            },
            load_clean_image( file, type, newFileName ){
                return new Promise((resolve, reject) => {
                    setTimeout(() => {
                        loadImage(file, canvas => {
                            if (canvas) {
                                this.clean_image_callback(canvas, type, newFileName, file)
                                .then(url => resolve(url))
                                .catch(err => reject(err));
                            } else {
                                reject(new Error('Failed to load image'));
                            }
                        },
                        { orientation: 1, canvas: true }
                        );
                    }, 500);
                });
            },
            clean_image_callback( canvas, type, newFileName, file ){
                return new Promise((resolve, reject) => {
                    if (canvas) {
                        var url = canvas.toDataURL(type);
                        canvas.toBlob(blob => {
                            uploadFileToAWSV2( blob, newFileName )
                            .then(uploadUrl => resolve(uploadUrl))
                            .catch(err => reject(err));
                        }, type);
                    } else {
                        reject(new Error('canvas is null'));
                    }
                });
            },
            link_form(){
                store.components.link_form.component = this.component;
                store.overlays.link_form = true;
            },
            set_default_fields(){
                if ( this.json_form && this.default_fields.length > 0 ){
                    this.selected_fields = this.selected_fields.map(default_field => {
                        if ( this.default_fields.indexOf(default_field.value ) !== -1 ){
                            return {
                                ...default_field,
                                selected: true,
                            }
                        } else {
                            return {
                                ...default_field,
                                selected: false,
                            }
                        }
                    });
                }
                if ( this.default_configuration === 'list' ){
                    //list
                    this.selected_fields = this.selected_fields.filter(field => field.selected);
                } else if ( this.default_configuration === 'grid' ){
                    //grid
                    this.selected_fields = this.selected_fields.filter(field => field.selected).reduce((acc, field) => {
                        if ( field.value === 'firstName' || field.value === 'lastName' ){
                            acc[0].push(field);
                        } else {
                            acc[1].push(field);
                        }
                        return acc;
                    }, [[], []])
                }
            },
            handle_field_update({ id, value }){
                const field = this.custom_fields.find(f => f.id === id);
                if (field) {
                    field.input_value = value;
                }
            },
        },
        computed: {
            form_id(){
                if ( typeof( this.form ) === 'string' ){
                    return JSON.parse(this.form).id;
                }
                return this.form.id || null;
            },
            color_theme(){
                if ( this.json_form && this.json_form.color_theme ){
                    return this.json_form.color_theme;
                }
                return '#5280ff';
            },
            custom_fields(){
                if ( this.json_form && this.json_form.custom_fields ){
                    return this.json_form.custom_fields;
                }
                return [];
            },
            default_fields(){
                if ( this.json_form && this.json_form.default_fields  ){
                    return this.json_form.default_fields;
                }
                return [];
            },
            collect_default_fields(){
                if ( this.json_form && this.json_form.collect_default_fields  ){
                    return this.json_form.collect_default_fields;
                }
                return false;
            },
            default_configuration(){
                if ( this.json_form && this.json_form.default_configuration  ){
                    return this.json_form.default_configuration;
                }
                return 'list';
            },
            missing_default_field(){
                if ( this.json_form && this.collect_default_fields && this.selected_fields.length > 0 ){
                    let default_values = this.default_configuration === 'list' 
                        ? this.selected_fields.map(field => field.input_value) 
                        : this.selected_fields.flatMap(arr => arr.map(field => field.input_value));
                    return default_values.includes(null) || default_values.includes('');
                }
                return false;
            },
            missing_custom_field(){
                if ( this.json_form && this.custom_fields ){
                    for ( let i = 0; i < this.custom_fields.length; i++ ){
                        let custom_field = this.custom_fields[i];
                        let option_values = custom_field.custom_field_options && custom_field.custom_field_options.length > 0 
                            ? custom_field.custom_field_options.map(option => option.selected)
                            : [];
                        if ( custom_field.required && ( !custom_field.input_value && option_values.indexOf(true) === -1 ) ){
                            return true;
                            break;
                        }
                    }
                    return false;
                }
            },
            button_disabled(){
                if ( this.is_admin ){
                    return true;
                }else{
                    return this.missing_custom_field || this.missing_default_field;
                }
                return false;
            },
            formatting_obj(){
                if ( this.formatting ){
                    return JSON.parse(this.formatting);
                }
                return;
            },
            valid_membership(){
                if(this.json_form && this.json_form.members_only){
                    return !this.invalid_membership;
                }
                //not members only, doesn't matter
                return true;
            },
        },
        watch: {
            form_id(newVal, oldVal){
                if (newVal !== oldVal){
                    this.load_forms( this.client_id );
                }
            }
        }
    })
</script>    <script type="text/html" id="template-tab-bar">
    <template v-if="is_web_builder()">
        <template v-if="config_latest()['tabs']?.length > 0">
            <div
                class="tab-bar-wrapper"
                :style="{
                    gap: (config_latest().formatting.section_width || 50) + 'px',
                    height: (config_latest().formatting.section_height || 50) + 'px',
                }"
            >
                <div
                    v-for="tab in config_latest()['tabs']"
                    style="width: 200px; display: flex; align-items: center; justify-content: center;"
                >
                    <div
                        @click="selected_tab_id = tab.id"
                        style="width: 100%; text-align: center;"
                        class="tab-bar-label"
                        :class="{ 'active': selected_tab_id === tab.id }"
                    >
                        <span>
                            <preview-element-component
                                v-if="tab.elements"
                                :element="tab.elements"
                                :element_type="tab.elements.type"
                                :element_content="tab.elements.content"
                                :componentObject="component"
                                :disable_remove="true"
                                :disable_column="true"
                                :disable_new_element="true"
                            ></preview-element-component>
                        </span>
                    </div>
                </div>
            </div>
            <web-builder-components
                v-if="selected_tab_id"
                :component="return_page_component(selected_tab_id)"
                :component_index="0"
                :preview_element="true"
            ></web-builder-components>
        </template>
        <template v-else>
            <div
                class="noObjectsMSG centeredBlock centeredText"
                style="padding: 5em;"
            >
                <p style="cursor: pointer;"><i class="fa-light fa-table-columns smallMarginRight"></i>Use the left side menu to start adding tabs</p>
            </div>
        </template>
    </template>
    <template v-if="!is_web_builder() && !loading">
        <template v-if="hosted_config()['tabs']?.length > 0">
            <div
                class="tab-bar-wrapper"
                :style="{
                    gap: (hosted_config().formatting.section_width || 50) + 'px',
                    height: (hosted_config().formatting.section_height || 50) + 'px',
                }"
            >
                <div
                    v-for="tab in hosted_config()['tabs']"
                    :key="tab.id"
                    style="width: 200px; display: flex; align-items: center; justify-content: center;"
                >
                    <div
                        @click="selected_tab_id = tab.id"
                        style="width: 100%; text-align: center;"
                        class="tab-bar-label"
                        :class="{ 'active': selected_tab_id === tab.id }"
                    >
                        <element-component
                            v-if="tab.elements"
                            :element="tab.elements"
                            :element_type="tab.elements.type"
                            :element_content="tab.elements.content"
                            :componentObject="component"
                            :disable_remove="true"
                            :disable_column="true"
                            :disable_new_element="true"
                        ></element-component>
                    </div>
                </div>
            </div>
            <web-builder-components
                v-if="selected_tab_id"
                :component="return_hosted_page_component(selected_tab_id)"
                :component_index="0"
                :tab_element="true"
                :preview_element="false"
            ></web-builder-components>
        </template>
    </template>
</script>

<style>
    .tab-bar-wrapper{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
        border-top: 1.5px solid rgb(204, 203, 203);
        border-bottom: 1.5px solid rgb(204, 203, 203);
        box-sizing: border-box;
    }
    .tab-bar-label span {
        position: relative;
        display: inline-block;
        padding-bottom: 4px;
        border-bottom: none !important;
        text-decoration: none !important;
    }
    .tab-bar-label span::after {
        content: "";
        position: absolute;
        bottom: 0;
        left: 50%;
        width: 0;
        height: 1px;
        background-color: #000;
        transform: translateX(-50%);
        transition: width 0.3s ease;
    }
    .tab-bar-label.active span::after {
        width: 100%;
    }
</style>

<script>    
    app_content.component('tab-bar-component', {
        template: '#template-tab-bar',
        data() {
            return {
                loading: true,
                selected_tab_id: null,
                hosted_tab_component: null,
                hosted_page_components: [],
            }
        },
        props: {
            client_id: String,
            component: {
                type: Object,
                default: null,
            },
            last_update: Number,
        },
        mounted() {
            if(this.is_web_builder()){
                this.selected_tab_id = this.config_latest()?.tabs?.[0]?.id || null;
            }else{
                this.load_tab_bar( this.client_id );
            }
        },
        methods: {
            load_tab_bar( client_id, overrides = {} ){
                this.loading = true;
                var promise = Parse.Promise.as();
                var thisPromise = promise.then(() => {
                    var params = {};
                    params["client_id"] = client_id;
                    params["overrides"] = overrides;
                    params["request_url"] = window.location.href;
                    return Parse.Cloud.run('retrieve_data_for_component', params);
                }).then(response => {
                    this.hosted_tab_component = response.tab_component || null;
                    this.hosted_page_components = response.page_components || [];
                    this.selected_tab_id = this.hosted_config()?.tabs?.[0]?.id || null;
                }).catch(error => {
                    checkParseError(error);
                }).finally(() => {
                    this.loading = false;
                });
                return thisPromise;
            },
            return_page_component(id){
                return store.page_components_latest.find(c => c.id === id)
            },
            return_hosted_page_component(id){
                return this.hosted_page_components.find(c => c.id === id)
            },
            config_latest(){
                if(this.component && this.component.get('config_latest')){
                    return this.component.get('config_latest');
                }
            },
            hosted_config(){
                if(this.hosted_tab_component && this.hosted_tab_component.get('config')){
                    return this.hosted_tab_component.get('config');
                }
            },
            is_web_builder(){
                return window.location.href.includes('website-builder');
            },
        },
        watch: {
            last_update(newVal) {
                if (this.is_web_builder()) {
                    this.selected_tab_id = this.config_latest()?.tabs?.[0]?.id || null;
                }
            }
        }
    });
</script>    <script type="text/html" id="template-web-builder-components">
    <div
        :id="'componentPreview_' + component.get('client_id')"
        class="componentPreview"
        :data-client-id="component.get('client_id')"
        :style="return_preview_style(component)"
    >
        <template v-if="component.get('type') === 'iframe'">
            <iframe-component
                :class_string="return_attributes(component, 'classString')"
                :style_string="return_attributes(component, 'style_string')"
                :iframe_src="return_attributes(component, 'config_latest').iframe_src"
                :component="component"
                :formatting_string="return_attributes(component, 'formatting')"
                :last_update="return_last_update(component)"
            ></iframe-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'blog-list'">
            <blog-list-component
                :client_id="return_attributes(component, 'client_id')"
                :class_string="return_attributes(component, 'classString')"
                :style_string="return_attributes(component, 'style_string')"
                :element_style_string="return_attributes(component, 'element_style')"
                :formatting="return_attributes(component, 'formatting')"
                :component_type="return_attributes(component, 'component_type')"
                :is_larchmont="global.is_larchmont"
                :component="component"
                :last_update="return_last_update(component)"
            ></blog-list-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template> 
        <template v-if="component.get('type') === 'calendar'">
            <membership-calendar-component
                :class_string="return_attributes(component, 'classString')"
                :client_id="return_attributes(component, 'client_id')"
                :style_string="return_attributes(component, 'style_string')"
                :component="component" 
                :last_update="return_last_update(component)"
            ></membership-calendar-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'membership-directory'">
            <membership-directory-component
                :formatting="JSON.parse(return_attributes(component, 'formatting'))"
                :class_string="return_attributes(component, 'classString')"
                :client_id="return_attributes(component, 'client_id')"
                :style_string="return_attributes(component, 'style_string')"
                :element_style_string="return_attributes(component, 'element_style')"
                :component_type="return_attributes(component, 'component_type')"
                :last_update="return_last_update(component)"
            ></membership-directory-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'event-list'">
            <event-list-component
                :class_string="return_attributes(component, 'classString')"
                :style_string="return_attributes(component, 'style_string')"
                :element_style_string="return_attributes(component, 'element_style')"
                :formatting="return_attributes(component, 'formatting')"
                :filter_types="return_attributes(component, 'filter_types')"
                :event_dates="return_attributes(component, 'event_dates')"
                :component_type="return_attributes(component, 'component_type')"
                :client_id="return_attributes(component, 'client_id')"
                :component="component"
                :last_update="return_last_update(component)"
            ></event-list-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'image-grid'">
            <image-grid-component
                :client_id="return_attributes(component, 'client_id')"
                :class_string="return_attributes(component, 'classString')"
                :image_grid_layout="return_attributes(component, 'image_grid_layout')"
                :images_per_row="return_attributes(component, 'images_per_row')"
                :caption_size="return_attributes(component, 'caption_size')"
                :subtext_size="return_attributes(component, 'subtext_size')"
                :link_label_size="return_attributes(component, 'link_label_size')"
                :text_position="return_attributes(component, 'text_position')"
                :caption_font_weight="return_attributes(component, 'caption_font_weight')"
                :image_grid_opacity="return_attributes(component, 'image_grid_overlay_opacity')"
                :image_grid_border_radius="return_attributes(component, 'image_grid_border_radius')"
                :formatting="return_attributes(component, 'formatting')"
                :is_admin="preview_element"
                :data_source_type="return_attributes(component, 'data_source')['type']"
                :images_arr="return_attributes(component, 'images')"
                :images_string="JSON.stringify(return_attributes(component, 'images'))"
                :component="component"
                :last_update="return_last_update(component)"
            ></image-grid-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'photo-gallery'">
            <photo-gallery-component
                :client_id="return_attributes(component, 'client_id')"
                :component="component"
                :photo_album="return_attributes(component, 'photo_album')"
                :show_caption="return_attributes(component, 'show_caption')"
                :caption_size="return_attributes(component, 'caption_size')"
                :caption_font_weight="return_attributes(component, 'caption_font_weight')"
                :photos_per_row="return_attributes(component, 'photos_per_row')"
                :is_admin="preview_element"
                :last_update="return_last_update(component)"
            ></photo-gallery-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'form'">
            <form-component
                :client_id="return_attributes(component, 'client_id')"
                :component="component"
                :form="return_attributes(component, 'form')"
                :formatting="return_attributes(component, 'formatting')"
                :is_admin="preview_element"
                :last_update="return_last_update(component)"
            ></form-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'image-with-text'">
            <image-with-text-component
                :client_id="return_attributes(component, 'client_id')"
                :formatting="return_attributes(component, 'formatting')"
                :images_string="JSON.stringify(return_attributes(component, 'images'))"
                :class_string="return_attributes(component, 'classString')"
                :style_string="return_attributes(component, 'style_string')"
                :element_style_string="return_attributes(component, 'element_style')"	
                :image_mat="return_attributes(component, 'image_mat')"
                :elements_string="return_attributes(component, 'elements')"
                :left_right_orientation="return_attributes(component, 'left_right_orientation')" 
                :preview_element="preview_element"
                :component="component"
                :last_update="return_last_update(component)"
                :last_element_update="return_last_element_update( component )"
                :tab_element="tab_element"
            ></image-with-text-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'text' || component.get('type') === 'table'">
            <div 
                class="cs-text background flexWrap relative" 
                :class="return_attributes(component, 'classString')" 
                :style="return_attributes(component, 'style_string')"
            >
                <div 
                    v-if="return_attributes(component, 'columns').length > 0" 
                    class="element-wrapper flexNoWrap flexWrapOnMobile" 
                    :class="'element-wrapper_' + return_attributes(component, 'component_type')"
                    :style="return_attributes(component, 'element_style')"
                >
                    <template v-for="(elements, column_index) in return_attributes(component, 'columns')">
                        <text-component
                            :number_of_columns="return_attributes(component, 'number_of_columns')"	
                            :preview_element="preview_element"
                            :component="component"
                            :last_update="return_last_update(component)"
                            :last_element_update="return_last_element_update( component )"
                            :elements="elements"
                            :column_index="column_index"
                        ></text-component>	
                    </template>
                </div>
            </div>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'hero-banner'">
            <hero-banner-component
                :client_id="return_attributes(component, 'client_id')"
                :formatting="return_attributes(component, 'formatting')"
                :class_string="return_attributes(component, 'classString')"
                :style_string="return_attributes(component, 'style_string')"
                :element_style_string="return_attributes(component, 'element_style')"
                :component_type="return_attributes(component, 'component_type')"
                :elements_string="return_attributes(component, 'elements')"
                :images_string="JSON.stringify(return_attributes(component, 'images'))"
                :preview_element="preview_element"
                :component="component"
                :last_update="return_last_update(component)"
                :last_element_update="return_last_element_update( component )"
                :tab_element="tab_element"
            ></hero-banner-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'custom-code'">
            <custom-code-component	
                :class_string="return_attributes(component, 'classString')"
                :preview_element="preview_element"
                :component="component"
                :last_update="return_last_update(component)"
            ></custom-code-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'unlayer-component'">
            <unlayer-component
                :class_string="return_attributes(component, 'classString')"
                :preview_element="preview_element"
                :component="component"
                :last_update="return_last_update(component)"
            ></unlayer-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
        <template v-if="component.get('type') === 'tab-bar'">
            <tab-bar-component
                :client_id="return_attributes(component, 'client_id')"
                :preview_element="preview_element"
                :component="component"
                :last_update="return_last_update(component)"
            ></tab-bar-component>
            <toolbar-option-component
                @click.stop
                :component="component"
                :is_first="component_index === 0"
                :disable_options="disable_options(component)"
            ></toolbar-option-component>
        </template>
    </div>
</script>

<script>    
    app_content.component('web-builder-components', {
        template: '#template-web-builder-components',
        data() {
            return {
                global: store,
                is_admin: false,
            }
        },
        props: {
            component: Object,
            component_index: Number,
            tab_element: Boolean,
            preview_element: Boolean,
            last_update: Number,
        },
        methods: {
            disable_options( componentObject ){
                const component_is_under_tab_bar = store.page_components_latest?.some(c => {
                    return c.get('type') === 'tab-bar' && (c.get('config_latest')?.tabs || []).some(tab => tab.id === componentObject?.id);
                });
                return component_is_under_tab_bar;
            },
            return_last_element_update( componentObject ){
                return store.element_updates ? store.element_updates[ componentObject.id ] : 0;
            },
            return_last_update(componentObject){
                return store.component_updates ? store.component_updates[ componentObject.id ] : 0;
            },
            return_preview_style(componentObject){
                let type = componentObject.get('type');
                if ( type === 'hero-banner' || type === 'image-with-text' ){
                    return this.return_attributes(componentObject, 'background_image_style');
                }
            },
            return_attributes(componentObject, attribute){
                let attributes = {};
                if(componentObject){
                    var type = componentObject.get('type');
                    var config_latest = componentObject.get('config_latest') || returnDefaultConfigForComponent( type );
                    var images = config_latest.images;
                    if(!images){
                        // images = [];
                        images = [null, null, null, null, null]
                    }
                    var formatting = config_latest.formatting;
                    if( ! formatting ){
                        formatting = returnDefaultFormattingForComponent( type );
                    }
                    var color_scheme = config_latest.color_scheme;
                    if (store.is_larchmont && store.pageObject.id === 'QAcpSXHP5G'){
                        color_scheme = 'larchmont_secondary';
                    }
                    //start the class string up here
                    var classString = '';
                    classString += ' color_scheme_' + color_scheme;
                    //now generate markup
                    var background_image_style = "";
                    var style_string = "";
                    if( formatting.section_height ){
                        style_string += "min-height:" + ( formatting.section_height ).toString() + "vh;";
                    }
                    if( formatting.align_items ){
                        style_string += "align-items:" + formatting.align_items + ";" ;
                    }
                    if ( formatting.background_size === 'inset' ){
                        background_image_style += "padding: 30px;" ;
                    } else if ( formatting.background_size === 'cover' ){
                        background_image_style += "padding: 0px;" ;
                    }
                    //element wrapper
                    var element_style = "";
                    if( formatting.section_width ){
                        element_style += "max-width:" + (formatting.section_width).toString() + "%;";
                    }
                    //overlay opacity
                    var opacity = 0;
                    if( formatting.overlay_opacity ){
                        opacity = formatting.overlay_opacity;
                    }
                    //extra_columns
                    var extra_columns = config_latest.extra_columns;
                    if( extra_columns ){
                        for (var c = extra_columns.length - 1; c >= 0; c--) {
                            classString += ' show_' + extra_columns[c];
                        }   
                    }
                    //images per row (image grid)
                    var images_per_row = config_latest.images_per_row;
                    if( ! images_per_row ){
                        images_per_row = 3;
                    }
                    //photos per row (photo gallery)
                    var photos_per_row = config_latest.photos_per_row;
                    if( ! photos_per_row ){
                        photos_per_row = 4;
                    }
                    //left/right orientation (image with text)
                    var left_right_orientation = config_latest.left_right_orientation;
                    if( ! left_right_orientation ){
                        left_right_orientation = "left";
                    }
                    classString += " orientation-" + left_right_orientation;
                    //number of columns (text)
                    var number_of_columns = config_latest.number_of_columns;
                    if( ! number_of_columns ){
                        number_of_columns = 3;
                    }
                    classString += " number_of_columns-" + number_of_columns;
                    //photo album id
                    var photo_album = config_latest.photo_album;
                    if( ! photo_album ){
                        photo_album = {
                            id: null,
                            name: null,
                        };
                    }
                    //form id
                    var form = config_latest.form;
                    if( ! form ){
                        form = {
                            id: null,
                            name: null,
                        };
                    }
                    //image with text
                    var image_mat = config_latest.image_mat ? config_latest.image_mat : 'show';
                    //filter types (event list)
                    var filter_types = config_latest.filter_types ? JSON.stringify(config_latest.filter_types) : null;
                    //event_dates (event list)
                    var event_dates = config_latest.event_dates ? config_latest.event_dates : 'upcoming';
                    //caption style
                    if( formatting.caption_style ){
                        classString += " caption_style-" + formatting.caption_style;
                    }
                    //caption alignment
                    if( formatting.caption_align && ( formatting.caption_align == "top" || formatting.caption_align == "bottom" ||  formatting.caption_align == "under" ) ){
                        classString += ' ' + formatting.caption_align + '-align-image-caption';
                    }
                    var show_caption = formatting.show_caption;
                    if( ! show_caption ){
                        show_caption = false;
                    }
                    var caption_size = formatting.caption_size;
                    if( ! caption_size ){
                        caption_size = "24";
                    }
                    var subtext_size = formatting.subtext_size;
                    if( ! subtext_size ){
                        subtext_size = "24";
                    }
                    var link_label_size = formatting.link_label_size;
                    if( ! link_label_size ){
                        link_label_size = "24";
                    }
                    var text_position = formatting.text_position;
                    if( ! text_position ){
                        text_position = "center";
                    }
                    var caption_font_weight = formatting.caption_font_weight;
                    if( ! caption_font_weight ){
                        caption_font_weight = "400";
                    }
                    var image_grid_overlay_opacity = formatting.image_grid_overlay_opacity;
                    if( ! image_grid_overlay_opacity ){
                        image_grid_overlay_opacity = "40";
                    }
                    var image_grid_border_radius = formatting.image_grid_border_radius;
                    if ( ! image_grid_border_radius ){
                        image_grid_border_radius = "0"
                    }
                    var image_grid_layout = formatting.layout;
                    if ( ! image_grid_layout ){
                        image_grid_layout = "grid"
                    }
                    //add all variables to attribute object
                    attributes['client_id'] = componentObject.get('client_id');
                    attributes['component_type'] = componentObject.get('type');
                    if( componentObject.get('config') && componentObject.get('config').event_types ){
                        attributes['event_types'] = componentObject.get('config').event_types;
                    }
                    // attributes['images'] = componentObject.get('images');
                    attributes['type'] = type;
                    attributes['config_latest'] = config_latest;
                    attributes['data_source'] = config_latest['data_source'];
                    attributes['images'] = images;
                    attributes['formatting'] = JSON.stringify(formatting);
                    attributes['color_scheme'] = color_scheme;
                    attributes['classString'] = classString;
                    attributes['style_string'] = style_string;
                    attributes['elements'] = config_latest['elements'];
                    attributes['element_style'] = element_style;
                    attributes['opacity'] = opacity;
                    attributes['extra_columns'] = extra_columns;
                    attributes['images_per_row'] = images_per_row;
                    attributes['photos_per_row'] = photos_per_row;
                    attributes['left_right_orientation'] = left_right_orientation;
                    attributes['columns'] = config_latest.columns;
                    attributes['number_of_columns'] = number_of_columns;
                    attributes['show_caption'] = show_caption;
                    attributes['caption_size'] = caption_size;
                    attributes['subtext_size'] = subtext_size;
                    attributes['link_label_size'] = link_label_size;
                    attributes['text_position'] = text_position;
                    attributes['caption_font_weight'] = caption_font_weight;
                    attributes['image_grid_overlay_opacity'] = image_grid_overlay_opacity;
                    attributes['image_grid_border_radius'] = image_grid_border_radius;
                    attributes['image_grid_layout'] = image_grid_layout;
                    attributes['background_image_style'] = background_image_style;
                    attributes['photo_album'] = photo_album;
                    attributes['form'] = form;
                    attributes['filter_types'] = filter_types;
                    attributes['event_dates'] = event_dates;
                    attributes['image_mat'] = image_mat;
                    //return requested attribute
                    return attributes[attribute];
                }
            },
        },
        computed: {
            
        },
    });
</script>
    <!-- overlays  -->
    <script type="text/html" id="template-view-all-events">
    <bottom-sheet-overlay
        id="overlay_view_all_events" 
        @dismiss_overlay="dismiss_overlay()"
    >
        <template #header>
            <div class="sticky-wrap overflowHidden">
                <div class="posScrollbar table-tab-wrap noPaddingBottom">
                    <div class="flexNoWrap table-tab-inner">
                        <div class="table-tab-option" :class="{'active': this.me.active_filters.eventDates === 'all'}" @click="handleDatesFilter('all')" style="margin-left:22px;">All</div>
                        <div class="table-tab-option noMarginLeft" :class="{'active': this.me.active_filters.eventDates === 'upcoming'}" @click="handleDatesFilter('upcoming')">Upcoming</div>
                        <div class="table-tab-option noMarginLeft" :class="{'active': this.me.active_filters.eventDates === 'past'}" @click="handleDatesFilter('past')">Past</div>
                    </div>
                </div>
            </div>
            <div class="searchBarWrap inline-search relative noMargin overflowHidden">
                <div class="inputWrap searchBar searchBar_event-list flexGrowOne boxShadowBottom maxFourHundo">
                    <input 
                        class="easeFast" 
                        placeholder="Search events..."
                        v-model="this.me.search"
                    >
                </div>
            </div>
        </template>

        <!-- body content -->
        <template #body>
            <div 
                class="event-list-outer-contain lightBorderTop scrollable" 
                :class="this.me.class_string" 
                :style="this.me.style_string"
            >
                <div 
                    class="event-list-wrap centeredBlock centeredText event-list-inner-contain" 
                    :class="'event-list-wrap_' + client_id" 
                    :data-client_id="client_id" 
                >
                    
                    <div class="fff noPadding overflowHidden">
                        <div v-if="!loading && filtered_events.length >= 1" class="tableInsert hundop flexWrapEvent eventListContain">
                            <template v-for="(event, index) in filtered_events" :key="event.id">
                                <event-list-event-component
                                    :event="event"
                                ></event-list-event-component>
                            </template>
                        </div>
                        <div v-if="!this.me.loading && filtered_events.length == 0" class="tableInsert hundop eventListContain">
                            <div class="eventList eventRow" :style="{ 'background-color': '#fff' }">
                                <p class="noObjectsMSG withPadding textLeft" :style="{ 'font-size': '20px' }">No events found.</p>
                            </div>
                        </div>
                    </div>
                    <div v-if="this.me.loading" class="cardBodySpinnerWrap active relative">
                        <div class="cardBodySpinner centeredBlock"></div>
                    </div>
                </div>
            </div>
        </template>
    
    </bottom-sheet-overlay>
</script>
<script>
    //global store
    store.components["view_all_events"] = {
        allEvents: [],
        active_filters: {
            eventDates: 'upcoming',
        },
        search: '',
        loading: true,
        sortObject: {
            order: 'ascending',
            key: 'startDate'
        },
        //passed props
        class_string: '',
        style_string: '',
        element_style_string: '',
        component_type: '',
        client_id: '',
    };
    //define the component
    app_overlays.component("view-all-events-overlay", {
        template: "#template-view-all-events",
        data() {
            return {
                global: store,
                me: store.components.view_all_events
            }
        },
        mounted(){
            if ( this.me.allEvents.length > 0 ){
                this.me.loading = false;
            }
        },
        methods: {
            niceDate( eventObject ){
                let start_offset;
                let start_offset_time;
                if( eventObject.get('startDate') ){
                    start_offset = returnOffsetDateForUTCDate( eventObject.get('startDate') );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('startTime') ){
                        var start_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                        start_offset.setHours( start_offset.getHours() + start_data.hours );
                        start_offset.setMinutes( start_offset.getMinutes() + start_data.minutes );
                    }
                    start_offset_time = start_offset.getTime();
                }
                return `${dayjs(start_offset).format('MMM DD, YYYY')},  ${dayjs(start_offset_time).format('h:mm A')}`
            },
            sortEventList( events, sortObject ){
                if( ! sortObject ){
                    this.me.sortObject = {}
                }
                if( ! sortObject.key ){
                    this.me.sortObject.key = "startDate";
                }
                if( ! sortObject.order ){
                    this.me.sortObject.order = "ascending"
                }
                if( sortObject.key == "name" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByEventName_ascending );
                    }else{
                        events = events.sort( this.sortByEventName_descending );
                    }
                }else if( sortObject.key == "startDate" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByStartDate_event_ascending );
                    }else{
                        events = events.sort( this.sortByStartDate_event_descending );
                    }
                }else if( sortObject.key == "endDate" ){
                    if( sortObject.order == "ascending" ){
                        events = events.sort( this.sortByEndDate_event_ascending );
                    }else{
                        events = events.sort( this.sortByEndDate_event_descending );
                    }
                }
                return events;
            },
            sortByEventName_ascending( a, b ){
                var aName = '';
                if( a.get('name') ){
                    aName += a.get('name').trim().toLowerCase();
                }
                var bName = '';
                if( b.get('name') ){
                    bName += b.get('name').trim().toLowerCase();
                }
                if(aName < bName) { return -1; }
                if(aName > bName) { return 1; }
                //they had the same name
                return 0;
            },
            sortByEventName_descending( a, b ){
                var aName = '';
                if( a.get('name') ){
                    aName += a.get('name').trim().toLowerCase();
                }
                var bName = '';
                if( b.get('name') ){
                    bName += b.get('name').trim().toLowerCase();
                }
                if(aName > bName) { return -1; }
                if(aName < bName) { return 1; }
                //they had the same name
                return 0;
            },
            sortByStartDate_event_ascending( a, b ){
                var aStartDate =  a.get('startDate')
                if( ! aStartDate ){
                    aStartDate = a.createdAt;
                }
                var bStartDate =  b.get('startDate')
                if( ! bStartDate ){
                    bStartDate = b.createdAt;
                }
                if(aStartDate < bStartDate) { return -1; }
                if(aStartDate > bStartDate) { return 1; }
                return 0;
            },
            sortByStartDate_event_descending( a, b ){
                var aStartDate =  a.get('startDate')
                if( ! aStartDate ){
                    aStartDate = a.createdAt;
                }
                var bStartDate =  b.get('startDate')
                if( ! bStartDate ){
                    bStartDate = b.createdAt;
                }
                if(aStartDate > bStartDate) { return -1; }
                if(aStartDate < bStartDate) { return 1; }
                return 0;
            },
            sortByEndDate_event_ascending( a, b ){
                var aEndDate =  a.get('endDate')
                if( ! aEndDate ){
                    aEndDate = a.createdAt;
                }
                var bEndDate =  b.get('endDate')
                if( ! bEndDate ){
                    bEndDate = b.createdAt;
                }
                if(aEndDate < bEndDate) { return -1; }
                if(aEndDate > bEndDate) { return 1; }
                return 0;
            },
            sortByEndDate_event_ascending( a, b ){
                var aEndDate =  a.get('endDate')
                if( ! aEndDate ){
                    aEndDate = a.createdAt;
                }
                var bEndDate =  b.get('endDate')
                if( ! bEndDate ){
                    bEndDate = b.createdAt;
                }
                if(aEndDate > bEndDate) { return -1; }
                if(aEndDate < bEndDate) { return 1; }
                return 0;
            },
            return_markup( eventObject, type ){
                var href_base = '';
                var clubObject = eventObject.get('clubObject');
                var web_settings = clubObject.get('web_settings');
                if( web_settings ){
                    if( web_settings.get('event_links') == "use_clubspot_regatta_links" && ( eventObject.className == "regattas" || eventObject.className == "subevents" ) ){
                        //force clubspot urls for regattas
                        href_base += 'https://theclubspot.com';
                    }   
                }
                var start_offset, end_offset;
                var start_offset_time, end_offset_time;
                if( eventObject.get('startDate') ){
                    start_offset = returnOffsetDateForUTCDate( eventObject.get('startDate') );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('startTime') ){
                        var start_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('startTime') );
                        start_offset.setHours( start_offset.getHours() + start_data.hours );
                        start_offset.setMinutes( start_offset.getMinutes() + start_data.minutes );
                    }
                    start_offset_time = start_offset.getTime();
                }
                var endDate = eventObject.get('endDate');
                if( ! endDate && eventObject.get('startDate') ){
                    endDate = eventObject.get('startDate');
                }
                if( endDate ){
                    end_offset = returnOffsetDateForUTCDate( endDate );
                    //handle start/end times set explicitly on the event (for socials)
                    if( eventObject.get('endTime') ){
                        var end_data = returnHoursAndMinutesForMilitaryTime( eventObject.get('endTime') );
                        end_offset.setHours( end_offset.getHours() + end_data.hours );
                        end_offset.setMinutes( end_offset.getMinutes() + end_data.minutes );
                    }
                    end_offset_time = end_offset.getTime();
                }
                // returns here
                if ( type === 'check-header-callout' ) {
                    return start_offset && start_offset.getFullYear() !== new Date().getFullYear()
                } else if ( type === 'start_offset_time' ) {
                    return start_offset_time;
                } else if ( type === 'end_offset_time' ) {
                    return end_offset_time;
                } else if ( type === 'header-callout' ){
                    return start_offset.getFullYear();
                } else if ( type === 'date' ){
                    //date
                    var date = '';
                    if( start_offset ){
                        var style_string = '';
                        if( eventObject.get('imageURL') ){
                            //we always want white text for this
                            style_string = ' style="color:#fff !important;" ';
                        }
                        date += '<p class="cs-signups-date-month">' + returnShortMonth( start_offset.getMonth() ) + '</p>';
                        var days = start_offset.getDate();
                        if( end_offset && ! eventObject.get('all_day') ){
                            if( end_offset.getDate() != start_offset.getDate() ){
                                days += ' - ' + end_offset.getDate();
                            }
                        }
                        date += '<p class="cs-signups-date-day">' + days + '</p>';
                    }
                    return date;
                } else if ( type === 'event-host-1' ){
                    return $('body').data('club-name');
                } else if ( type === 'event-host-2' ){
                    var club_string = '';
                    var location_params = {
                        eventObject: eventObject,
                        hideCountry: true, 
                        hideZip: true,
                        hideStreet: true,
                    }
                    var club_location_params = {
                        eventObject: clubObject,
                        hideCountry: true, 
                        hideZip: true,
                        hideStreet: true,
                    }
                    if(formatLocation(location_params) ){
                        if( club_string.length >= 1 ){
                            club_string += ', ';
                        }
                        club_string += formatLocation(location_params);
                    }else if( clubObject && formatLocation(club_location_params) ){
                        if( club_string.length >= 1 ){
                            club_string += ', ';
                        }
                        club_string += formatLocation(club_location_params);
                    }
                    return club_string;
                }  else if ( type === 'links' ){
                    var content;
                    if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                        //check for external events
                        if( regattaObject.get('regatta_external') && regattaObject.get('external_regatta_url') ){
                            //it's an external event
                            content = '<p><a target="_blank" href="'+ regattaObject.get('external_regatta_url') +'">Event page</a></p>';
                        }else{
                            //event page
                            content = '<p><a href="'+href_base+'/regatta/'+ regattaObject.id +'">Event page</a></p>';
                            //entries
                            content = '<p><a href="'+href_base+'/regatta/'+ regattaObject.id +'">Entries</a></p>';
                            //race docs
                            content = '<p><a href="'+href_base+'/regatta/'+ regattaObject.id +'">Race docs</a></p>';
                        }
                    }else if( eventObject.className == "events" ){
                        //check for external events
                        if( ! eventObject.get('calendarOnly') ){
                            if( eventObject.get('external_event') && eventObject.get('external_event_url') ){
                                //it's an external event
                                content = '<p><a target="_blank" href="'+ eventObject.get('external_event_url') +'">Event page</a></p>';
                            }else{
                                //event page
                                content = '<p><a href="'+href_base+'/event/'+ eventObject.id +'">Event page</a></p>';
                            }
                        }
                    }else if( eventObject.className == "camps" ){
                        //it's a camp
                        content = '<p><a href="'+href_base+'/camp-registrations/'+ eventObject.id +'">Entry list</a></p>';
                    }
                    return content;
                } else if ( type === 'button' ){
                    var content;
                    var show_register_button = this.returnShowRegisterButtonForEvent( eventObject );
                    if( eventObject.className == "regattas" || eventObject.className == "subevents" ){
                        //check for external events
                        if( regattaObject.get('regatta_external') && regattaObject.get('external_regatta_url') ){
                            //it's an external event
                            content = '<button class="relative background"><a class="absoluteA" target="_blank" href="'+ regattaObject.get('external_regatta_url') +'">View event</a></button>';
                        }else{
                            //handle button status
                            if( show_register_button ){
                                //register
                                content = '<button class="relative background"><a class="absoluteA" href="'+href_base+'/register/regatta/'+ regattaObject.id +'/class">Register</a></button>';
                            }else{
                                //results
                                content = '<button class="relative background"><a class="absoluteA" href="'+href_base+'/regatta/'+ regattaObject.id +'/results">View Results</a></button>';
                            }
                        }
                    }else if( eventObject.className == "events" ){
                        var registration_link;
                        if( eventObject.get('events_v2') ){
                            registration_link = '/register/event/' + eventObject.id;
                        }else if( eventObject.get('external_event') && eventObject.get('external_register_link') ){
                            registration_link = eventObject.get('external_register_link');
                        }else if( eventObject.get('event_product') ){
                            if( eventObject.get('event_product').get('availability') && eventObject.get('event_product').get('availability').startDate ){
                                registration_link = "/reserve/" + eventObject.get('event_product').id + "?date=" + eventObject.get('event_product').get('availability').startDate;
                            }
                        } 
                        if( registration_link && show_register_button ){
                            content = '<button class="relative"><a href="'+href_base+''+registration_link+'">RSVP</a></button>';
                        } 
                    }else if( eventObject.className == "camps" ){
                        //handle button status
                        if( show_register_button ){
                            //register
                            content = '<button class="relative"><a href="'+href_base+'/register/camp/'+ eventObject.id +'/class">Register</a></button>';
                        }
                    }
                    return content;
                }
            },
            returnShowRegisterButtonForEvent( eventObject ){
                //set defaults
                var now = new Date();
                var ended = false;
                var registration_closed = eventObject.get('registration_closed');
                var startDate = eventObject.get('startDate');
                var lastChanceDate = eventObject.get('lastChanceDate');
                var endDate = eventObject.get('endDate');
                if( ! endDate && startDate ){
                    endDate = startDate;
                }
                var endDate_plus_one;
                if( endDate ){
                    endDate_plus_one = new Date( endDate.getTime() ); 
                    endDate_plus_one.setDate( endDate.getDate() + 1 );
                }
                if( now > endDate_plus_one && endDate_plus_one ){ 
                    ended = true; 
                }
                if( now > lastChanceDate && lastChanceDate ){ 
                    registration_closed = true; 
                }
                if( ended || registration_closed || eventObject.get('calendarOnly') ){ 
                    return false;
                } else {
                    return true;
                }
            },
            handleDatesFilter( option ){
                this.me.active_filters.eventDates = option;
                // handle sortObject["order"] here instead of in loadEventList post-retrieval for better UX
                if ( option === 'upcoming' ){
                    this.me.sortObject["order"] = "ascending";
                } else {
                    this.me.sortObject["order"] = "descending";
                }
            },
            dismiss_overlay(){
                store.overlays.view_all_events = false;
            }
        },
        computed: {
            filtered_events(){
                let val = this.me.search.toLowerCase();
                let filteredEvents = this.me.allEvents;
                // handle search results using all events
                if (this.me.search.length > 0){
                    filteredEvents = this.me.allEvents.filter(event => {
                        let name = event.get('name').toLowerCase();
                        if ( name.includes(val) ){
                            return event;
                        }
                    })
                }
                // handle tab selection using filteredEvents 
                var yesterday = new Date();
                yesterday.setDate( yesterday.getDate() - 1 );
                var timestamp = yesterday.getTime();

                if (this.me.active_filters.eventDates !== 'all'){
                    filteredEvents = filteredEvents.filter(event => {
                        let start = this.return_markup( event, 'start_offset_time' );
                        let end = this.return_markup( event, 'end_offset_time' );
                        if (this.me.active_filters.eventDates === 'past'){
                            if( start < timestamp && ( end < timestamp || ! end || end == "undefined" ) ){
                                return event;
                            }
                        } else if (this.me.active_filters.eventDates === 'upcoming'){
                            if ( start > timestamp || end > timestamp ){
                                return event;
                            }
                        }
                    })
                }
                return this.sortEventList( filteredEvents, this.me.sortObject );
            },
        }
    });

</script>

<!-- HTML !-->    <script type="text/html" id="template-view-photo-carousel">
    <div 
        id="overlay_view-photo-carousel"
        class="carousel-v-overlay"
    >
        <div 
            class="carousel-container"
            @touchstart.self="touched_overlay()"
            @mousedown.self="touched_overlay()"
            @click.self="clicked_overlay()"
        >
            <div class="actions-container">
                <!--
                <div class="event-page-callout" style="color: #fff;" @click.stop="tapped_download()">
                    <template v-if="! downloading">
                        <i class="fa-regular fa-arrow-down-to-line" style="color: #fff;"></i>
                        Download 
                    </template>
                    <template v-else>
                        <i class="fa-regular fa-check" style="color: #fff;"></i>
                        Downloaded
                    </template>
                </div>
                -->
                <div class="event-page-callout" style="color: #fff;" @click.stop="tapped_share()">
                    <template v-if="! sharing">
                        <i class="fa-regular fa-arrow-up-from-bracket" style="color: #fff;"></i>
                        Share 
                    </template>
                    <template v-else>
                        <i class="fa-regular fa-check" style="color: #fff;"></i>
                        Link copied 
                    </template>
                </div>
            </div>
            <i class="fa-light fa-chevron-left nav-arrow" @click.stop="prev()"></i>
            <div class="carousel-photo-container">
                <video 
                    v-if="returnIsVideo(json_photos[current_index].file_name) && json_photos[current_index].url"
                    class="carousel-photo" 
                    autoplay muted loop playsinline
                    :key="current_index"
                >
                    <source :src="json_photos[current_index].url" type="video/mp4">
                </video>
                <div class="carousel-photo-wrapper">
                    <div class="carousel-photo" :style="'background-image:url('+json_photos[current_index].url+')'"></div>
                </div>
                <template v-if="json_config.show_caption">
                    <p class="carousel-caption" v-if="json_photos[current_index].caption" :style="{ 'font-size': json_config.caption_size + 'px', 'font-weight': json_config.caption_font_weight }">{{ json_photos[current_index].caption }}</p>
                </template>
            </div>
            <i class="fa-light fa-chevron-right nav-arrow" @click.stop="next()"></i>
        </div>
    </div>
</script>

<style>
    .carousel-v-overlay{
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: auto;
        background-color: rgba(8,8,19,0.84);
        position: fixed;
        z-index: 1000 !important;
        left: 0px;
        top: 0px;
        width: 100vw;
        animation: overlay-animation 0.3s forwards;
    }
    @keyframes overlay-animation {
        0% {
            transform: scale(0.8);
        }
        100% {
            transform: scale(1);
        }
    }
    .carousel-container{
        display: flex;
        justify-content: space-between;
        align-items: center;
        height: 100vh;
        width: 98vw;
        position: relative;
        overflow: hidden;
        cursor: auto;
    }
    .carousel-container > .nav-arrow {
        font-size: 28px;
        padding: 1em;
        color: #fff;
        z-index: 1;
        opacity: 0.6;
        transition: opacity 0.3s ease;
        cursor: pointer;
    }
    .carousel-container > .nav-arrow:hover {
        opacity: 1;
    }
    .carousel-photo-container {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 70%;
        min-width: 200px;
        min-height: 200px;
    }
    .carousel-photo-wrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 100%;
        height: 100%;
    }
    .carousel-photo {
        width: 100%;
        height: 100%;
        object-fit: contain;
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
    }
    .carousel-caption{
        margin: 10px 0 0 0;
        text-transform: uppercase;
        letter-spacing: 2px;
        color: #fff;
        padding: 5px;
        border-radius: 2px;
        background-color: rgba(0, 0 ,0, 0.1);
    }
    .actions-container{
        position: absolute;
        top: 5px;
        right: 5px;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .actions-container > .event-page-callout{
        padding-left: 10px;
        padding-right: 10px;
        border-radius: 5px;
        border: 1px solid #e4ebf1;
        font-size: 13px;
        margin: 6px;
        color: #6a7482;
        padding-bottom: 8px;
        padding-top: 8px;
        cursor: pointer;
    }
    .actions-container > .event-page-callout i{
        padding-right:3px;
    }
    .actions-container > .event-page-callout:hover{
        color: #081333;
    }
</style>

<script>

    function downloadImage( url, filename ) {
        return fetch(url, { mode: 'cors' })
            .then(response => {
                if (!response.ok) {
                    throw new Error(`Network response was not ok: ${response.statusText}`);
                }
                return response.blob();
            })
            .then(blob => {
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.style.display = 'none';
                a.href = url;
                a.download = filename;
                // Append the anchor to the body
                document.body.appendChild(a);
                a.click();
                // Remove the anchor from the body
                document.body.removeChild(a);
                window.URL.revokeObjectURL(url);
            })
            .catch(err => console.error('Error downloading the image:', err));
    }

    store.components.view_photo_carousel = {
        json_photos: [],
        current_index: 0,
        downloading: false,
        sharing: false,
        json_config: null,
    }
    
    app_overlays.component("view-photo-carousel", {
        template: "#template-view-photo-carousel",
        data() {
            return store.components.view_photo_carousel;
        },
        methods: {
            async tapped_download(){
                let url = this.json_photos[this.current_index].url;
                let file_name = this.json_photos[this.current_index].file_name;
                this.downloading = true;
                try {
                    downloadImage( url, file_name )
                        .then(() => {
                            displayMessage("File downloaded.", false, 6000);
                            this.downloading = false;
                        })
                        .catch(() => {
                            displayMessage("Sorry, something went wrong with your download. Please try again, or contact support if the problem persists.", true, 8000);
                            this.downloading = false;
                        })
                } catch (error) {
                    displayMessage("Sorry, something went wrong with your download. Please try again, or contact support if the problem persists.", true, 8000);
                }
            },
            returnIsVideo(filename) {
                var ext = this.getExtension(filename);
                switch (ext.toLowerCase()) {
                    case 'm4v':
                    case 'avi':
                    case 'mpg':
                    case 'mp4':
                    case 'mp3':
                    case 'mov':
                    // etc
                    return true;
                }
                return false;
            },
            getExtension(filename) {
                var parts = filename.split('.');
                return parts[parts.length - 1];
            },
            tapped_share(){
                copyToClipboard( window.location.href );
                displayMessage("Link copied.", false, 6000);
                this.sharing = true;
                setTimeout(() => {
                    this.sharing = false;
                }, 3000);
            },
            prev(){
                if ( this.current_index === 0 ){
                    this.current_index = this.json_photos.length - 1;
                } else {
                    this.current_index -= 1;
                }
            },
            next(){
                if ( this.current_index === this.json_photos.length - 1 ){
                    this.current_index = 0;
                } else {
                    this.current_index += 1;
                }
            },
            dismiss_overlay(){
                store.overlays.view_photo_carousel = false;
            },
            clicked_overlay(){
                if( ! should_close_overlay( this.last_touch ) ){
                    return
                }
                this.dismiss_overlay();
            },
            touched_overlay(){
                this.last_touch = new Date().getTime();
            },
        },
        computed: {

        }
    });
    
</script>    <script type="text/html" id="template-bottom-sheet-overlay">

    <div 
        class="v-overlay scrollable hugePaddingBottom active" 
        @touchstart.self="touched_overlay()"
        @mousedown.self="touched_overlay()"
        @click.self="clicked_overlay()"
    >
        <div 
            class="standardOverlayCard centeredBlock bottom-sheet"
            :class="{'short': height == 'short'}"
        >

            <!-- generic header content -->
            <div class="bottom-sheet-overlay-header">
                <div 
                    class="relative"
                >
                    <div 
                        class="overlay-header-handle-wrap centeredBlock"
                        @click.stop="toggle_height()" 
                    >
                        <div class="overlay-header-handle"></div>
                    </div>
                    <i 
                        class="overlay-x-button fa-regular fa-xmark pointer"
                        @click.stop="dismiss_overlay()"
                    ></i>
                </div>

                <!-- header content injected here -->
                <slot name="header"></slot>

            </div>

            <!-- body content injected here -->
            <slot name="body"></slot>

            <!-- footer content injected here -->
            <slot name="footer"></slot>

        </div>
    </div>

</script>

<style>

    .standardOverlayCard.bottom-sheet{
        position: fixed;
        bottom: 0px;
        top: 50px;
        left: 0px;
        right: 0px;
        z-index: 1001;
        /*
        background-color: rgba(249, 251, 251, 1);
        */
        background-color: #fff;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        transition: bottom 0.3s cubic-bezier(0.25, 0.1, 0.25, 1);
        border-top-left-radius: 10px;
        border-top-right-radius: 10px;
        padding-bottom: 10px;
        padding-top: 10px;
        max-width: 1100px;
        margin-top: 0px;
        border-bottom-left-radius: 0px;
        border-bottom-right-radius: 0px;
    }

    .standardOverlayCard.bottom-sheet.short{
        top: 50%;
    }

    @media (max-height: 600px) {

        .standardOverlayCard.bottom-sheet.short{
            top: 150px;
        }

    }

    .standardOverlayCard.bottom-sheet h3{
        padding-top:0px;
    }

    .standardOverlayCard.bottom-sheet{
        display: flex;
        flex-direction: column;
        padding-bottom:0px;
        padding-top: 0px;
    }

    .standardOverlayCard.bottom-sheet .bottom-sheet-overlay-card-header
    {
        flex: 0 0 auto; /* Fixed height, doesn't grow or shrink */
    }

    .standardOverlayCard.bottom-sheet .standardCardFooter{
        position: absolute;
        bottom: 0px;
        left: 0px;
        right: 0px;
        background-color: #fff;
        border-top: 1px solid #e4ebf1;
        z-index: 10;
    }

    .standardOverlayCard.bottom-sheet .standardCardBody{
        flex: 1 1 auto; /* Flexible height, can grow and shrink */
        padding-bottom: 90px !important;
    }

    .overlay-header-handle-wrap{
        padding: 10px;
        cursor: pointer;
        max-width: 120px;
    }
    .overlay-header-handle{
        width: 70px;
        height: 3px;
        border-radius: 10px;
        background-color: #acb3ba;
        margin-left: auto;
        margin-right: auto;
        margin-top: 8px;
        margin-bottom: 8px;
    }
    .overlay-x-button{
        position: absolute;
        right: 14px;
        color: #535e6c;
        font-size: 20px;
        top: 14px;
    }

</style>

<script>

    //define the component
    app_overlays.component("bottom-sheet-overlay", {
        template: "#template-bottom-sheet-overlay",
        data() {
            return {
                height: "tall"
            }
        },
        mounted(){
            const universalEditOverlay = document.getElementById('overlay_universal-edit');
            if (universalEditOverlay) {
                universalEditOverlay.style.zIndex = "1000000";
            }
            const membershipValidationOverlay = document.getElementById('overlay_verifyMembership');
            if (membershipValidationOverlay) {
                membershipValidationOverlay.style.zIndex = "1000000";
            }
        },
        beforeUnmount() {
            //reset the z-index
            const universalEditOverlay = document.getElementById('overlay_universal-edit');
            if (universalEditOverlay) {
                universalEditOverlay.style.zIndex = ""; // Revert to default
            }
            const membershipValidationOverlay = document.getElementById('overlay_verifyMembership');
            if (membershipValidationOverlay) {
                membershipValidationOverlay.style.zIndex = ""; // Revert to default
            }
        },
        methods: {
            dismiss_overlay(){
                this.$emit('dismiss_overlay');
            },
            toggle_height(){
                if( this.height == "tall" ){
                    this.height = "short";
                }else{
                    this.height = "tall";
                }
            },
            clicked_overlay(){
                if (should_close_overlay(this.last_touch)) {
                    this.dismiss_overlay();
                }
            },
            touched_overlay(){
                this.last_touch = new Date().getTime();
            },
        },
    });
    
</script>
    <!-- define/register shared vue components  -->
    
    <script type="text/html" id="template-calendar-date-picker">
    <vue-date-picker
        v-model="selected_date" 
        :mode="mode"
        :modes="['year', 'month']" 
        :monthPicker="true" 
        :yearPicker="true"
        @update:modelValue="date_changed()"
        :clearable="false"
        format="MMM-d-yyyy"
        auto-apply
        :teleport="true"
        menu-class-name="cs-calendar-date-picker-menu"
        input-class-name="cs-calendar-date-picker-input"
    >
        <template #input-icon>
            <i class="fa-regular fa-calendar-arrow-down"></i>
        </template>
        <template #calendar-icon>
            <i class="fa-regular fa-arrow-turn-down-left"></i>
        </template>
        <template #arrow-left>
            <i class="fa-regular fa-chevron-left"></i>
        </template>
        <template #arrow-right>
            <i class="fa-regular fa-chevron-right"></i>
        </template>
    </vue-date-picker>
 </script>
 
 <style>

    .cs-calendar-date-picker-menu .dp__btn{
        color: #000000 !important;
        background: none !important; 
        font: inherit !important;
        line-height: normal !important;
     }

     .cs-calendar-date-picker-input{
        width: 0px;
        padding-left: 26px;
        padding-right: 22px;
        text-align: center;
        margin-right: 8px;
        overflow: hidden;
        padding-top: 7px;
        padding-bottom: 7px;
        border: 1px solid #e4ebf1;
     }

     .cs-calendar-menu-wrap .dp__input_icon i{
        font-size: 16px !important;
        transform: none;
     }

 </style>
 
 <script>
 
     app_content.component("calendar-date-picker-component", {
         template: "#template-calendar-date-picker",
         data() {
            return {
                selected_date: new Date(),
                mode: 'month',
            }
         },
         props: {
            handle_button_click: Function,
         },
         methods: {
            date_changed(){
                this.handle_button_click( 'date-picker', this.selected_date );
            },
         },
     });
 
 </script>
 
 <script>
     app_content.component('VueDatePicker', VueDatePicker);
 </script>
     <script type="text/html" id="template-calendar-grid">
    <div class="centeredOnMobile smallMarginTop" :class="{'ninetyPercent': !is_membership_cal, 'standardCard': !is_membership_cal}">
        <!-- main options header // stays consistent across all views -->
        <div class="standardCardBody noBorderTop calendar noPadding fff" style="overflow: none;">
            <!-- options for non-membership cal -->
            <div v-if="filterOptions?.length >= 1 && !is_membership_cal" class="cal-filter-option-wrap scrollable paddingLeftRight tinyPaddingTop smallPaddingBottom">
                <div class="flexNoWrap">
                    <template v-for="option in filterOptions">
                        <div
                            class="cs-cal-filter-option" 
                            :class="[
                                'cs-cal-filter-option_' + option.data_option,
                                { 'active': selectedFilterOptions.indexOf(option.data_option) !== -1 }
                            ]"
                            :data-option="option.data_option"
                            @click="$emit('handleFilterSelection', option)"
                        >
                            {{ option.name }}
                        </div>
                    </template>
                </div>
            </div>
            <!-- main calendar header // stays consistent across all views -->
            <!-- options for membership cal -->
            <div class="cs-calendar-wrap overflowHidden" :class="[{ 'wrapBorderBottom': is_membership_cal }, 'cs-calendar-wrap_' + client_id, class_string]" :style="generateWrapStyle('cs-calendar-wrap')" :data-client-id="client_id">
                <div v-if="filterOptions?.length >= 1 && is_membership_cal" class="scrollable posScrollbar lightBorderTop noPaddingBottom">
                    <div class="flexNoWrap" :style="generateWrapStyle('options')">
                        <template v-for="option in filterOptions">
                            <div
                                class="cs-cal-filter-option" 
                                :class="{
                                    ['cs-cal-filter-option_' + option.data_option]: true,
                                    'active': selectedFilterOptions.indexOf(option.data_option) !== -1
                                  }"
                                :data-option="option.data_option"
                                @click="$emit('handleFilterSelection', option)"
                            >
                                {{ option.name }}
                            </div>
                        </template>
                    </div>
                </div>
                <div class="cs-calendar-menu-wrap flexNoWrap" :style="generateWrapStyle('cs-calendar-menu-wrap')">
                    <div class="flexWrapLeftAlign">
                        <div class="flexNoWrap">
                            <div class="cs-calendar-button roboto hideOnMobile" data-option="today" @click="handleButtonClick('today')">Today</div>
                            <div class="cs-calendar-button cs-calendar-button-previous roboto" data-option="previous" @click="handleButtonClick('previous')"></div>
                            <div class="cs-calendar-button cs-calendar-button-next roboto" data-option="next" @click="handleButtonClick('next')"></div>
                        </div>
                        <p v-if="calendarTitle" class="cs-calendar-date-range-title roboto">{{ calendarTitle }}</p>
                    </div>
                    <div class="flexGrowOne roboto"></div>
                    <!-- calendar date picker -->
                    <calendar-date-picker-component
                        :handle_button_click="handleButtonClick"
                    ></calendar-date-picker-component>
                    <div class="vue-cs-calendar-select-wrap onWhite roboto">
                        <select 
                            class="vue-cs-calendar-view-select roboto" 
                            v-model="view_preference" 
                            @change="changeViewPreference"
                        >
                            <option value="Month">Month</option>
                            <option value="Week">Week</option>
                            <option value="Day">Day</option>
                        </select>
                    </div>
                </div>
                <!-- inject month view -->
                <div v-if="view_preference === 'Month' && !loading" class="flexGrid">
                    <!-- header -->
                    <div class="daysOfWeek-grid">
                        <template v-for="day in daysOfWeek">
                            <calendar-cell-component
                                class="grid-cell dayOfWeek"
                                :class="{ 'borderClose': day === 'Sat' }"
                                :day="day.toUpperCase()"
                                cellType="dayOfWeek"
                                :view_preference="view_preference"
                            ></calendar-cell-component>
                        </template>
                    </div>
                    <!-- events -->
                    <div class="calendar-grid">
                        <template v-for="(calendarObj, i) in calendar">
                            <calendar-cell-component
                                class="grid-cell"
                                :client_id="client_id"
                                :date="calendarObj.date"
                                :class="{
                                    'notCurrentMonth': calendarObj.class === 'prevMonthDate' || calendarObj.class === 'nextMonthDate',
                                    'currentMonth': calendarObj.class === 'currentMonthDate',
                                    'borderClose': calendarObj.date.day() === 6,
                                    'borderTopRightBottomClose': i >= 35 && i <= 40,
                                    'borderTopBottomClose': i === calendar.length - 1
                                }"
                                :month_class="calendarObj.class"
                                :day="calendarObj.day"
                                :events="calendarObj.events"
                                cellType="calendarObj"
                                :view_preference="view_preference"
                                :defaultDate="calendarObj.defaultDate"
                                :monthIndex="i"
                                @createSchedule_emitted="createSchedule_emitted"
                                @clickSchedule_emitted="clickSchedule_emitted"
                                :is_membership_cal="is_membership_cal"
                            ></calendar-cell-component>
                        </template>
                    </div>
                </div>
                <!-- inject week view -->
                <div v-if="view_preference === 'Week' && !loading" class="flexGrid">
                    <!-- header -->
                    <div class="placeholder-daysOfWeek-grid">
                        <template v-for="day in placeholder_daysOfWeek">
                            <calendar-cell-component v-if="day.dayOfWeek === null"
                                class="grid-cell-week dayOfWeek hide"
                                :day="day"
                                cellType="dayOfWeek"
                                :view_preference="view_preference"
                            ></calendar-cell-component> 
                            <calendar-cell-component v-if="day.dayOfWeek !== null"
                                class="grid-cell-week dayOfWeek"
                                :day="day"
                                cellType="dayOfWeek"
                                :view_preference="view_preference"
                                :defaultDate="day.defaultDate"
                            ></calendar-cell-component>
                        </template>
                        <!-- all day events -->
                        <template v-for="allDay in placeholder_daysOfWeek">
                            <calendar-cell-component v-if="allDay.dayOfWeek === null"
                                class="grid-cell-week allDay"
                                :allDay="allDay"
                                cellType="allDay_events"
                                :view_preference="view_preference"
                                :is_membership_cal="is_membership_cal"
                            ></calendar-cell-component> 
                            <calendar-cell-component v-if="allDay.dayOfWeek !== null"
                                class="grid-cell-week allDay"
                                :allDay="allDay"
                                cellType="allDay_events"
                                :view_preference="view_preference"
                                @createSchedule_emitted="createSchedule_emitted"
                                @clickSchedule_emitted="clickSchedule_emitted"
                                :is_membership_cal="is_membership_cal"
                            ></calendar-cell-component>
                        </template>
                    </div>
                    <!-- timestamps and events -->
                    <div class="placeholder-calendar-grid">
                        <template v-for="(timestamp, i) in timestamps">
                            <template v-for="(calendarObj, j) in calendar">
                                <calendar-cell-component 
                                    v-if="j === 0"
                                    class="grid-cell-week timestamp"
                                    :date="calendarObj.date"
                                    :timestamp="i % 4 === 0 ? formatShortTime( timestamp.customFormat ) : null"
                                    :events="[]"
                                    cellType="timestamp"
                                    :view_preference="view_preference"
                                    :is_membership_cal="is_membership_cal"
                                    :class="{ 'borderBottomClose': i === timestamps.length - 1 }"
                                ></calendar-cell-component>
                                <calendar-cell-component 
                                    v-else
                                    class="grid-cell-week"
                                    :style="calendarObj.defaultDate ? { 'background-color': 'rgba( 175, 213, 240, 0.1)' } : null"
                                    :class="{
                                        'showBorder': i % 4 === 0,
                                        'hideBorder': i === 0 || i % 4 !== 0
                                    }"
                                    :date="calendarObj.date"
                                    :events="generateEventForTimestamp( timestamp.customFormat, calendarObj.events, calendarObj.date )"
                                    cellType="calendarObj"
                                    :view_preference="view_preference"
                                    @createSchedule_emitted="createSchedule_emitted"
                                    @clickSchedule_emitted="clickSchedule_emitted"
                                ></calendar-cell-component>
                            </template>
                        </template>
                    </div>
                </div>
                <!-- inject day view -->
                <div v-if="view_preference === 'Day' && !loading" class="flexGrid">
                    <!-- header -->
                    <div class="day-daysOfWeek-grid">
                        <template v-for="day in today_daysOfWeek">
                            <calendar-cell-component v-if="day.dayOfWeek === null"
                                class="grid-cell-week dayOfWeek hide"
                                :day="day"
                                cellType="dayOfWeek"
                                :view_preference="view_preference"
                            ></calendar-cell-component> 
                            <calendar-cell-component v-if="day.dayOfWeek !== null"
                                class="grid-cell-week day"
                                :day="day"
                                cellType="dayOfWeek"
                                :view_preference="view_preference"
                                :defaultDate="day.defaultDate"
                            ></calendar-cell-component>
                        </template>
                        <!-- all day events -->
                        <template v-for="allDay in today_daysOfWeek">
                            <calendar-cell-component v-if="allDay.dayOfWeek === null"
                                class="grid-cell-week allDay"
                                :allDay="allDay"
                                cellType="allDay_events"
                                :view_preference="view_preference"
                                :is_membership_cal="is_membership_cal"
                            ></calendar-cell-component> 
                            <calendar-cell-component v-if="allDay.dayOfWeek !== null"
                                class="grid-cell-week allDay"
                                :allDay="allDay"
                                cellType="allDay_events"
                                :view_preference="view_preference"
                                @createSchedule_emitted="createSchedule_emitted"
                                @clickSchedule_emitted="clickSchedule_emitted"
                                :is_membership_cal="is_membership_cal"
                            ></calendar-cell-component>
                        </template>
                    </div>
                    <!-- timestamps and events -->
                    <div class="day-calendar-grid">
                        <template v-for="(timestamp, i) in timestamps">
                            <template v-for="(calendarObj, j) in calendar">
                                <calendar-cell-component v-if="j === 0"
                                    class="grid-cell-week timestamp"
                                    :date="calendarObj.date"
                                    :timestamp="i % 4 === 0 ? formatShortTime( timestamp.customFormat ) : null"
                                    :events="[]"
                                    cellType="timestamp"
                                    :view_preference="view_preference"
                                    :is_membership_cal="is_membership_cal"
                                    :class="{ 'borderBottomClose': i === timestamps.length - 1 }"
                                ></calendar-cell-component>
                                <calendar-cell-component v-if="j !== 0"
                                    class="grid-cell-week"
                                    :style="calendarObj.defaultDate ? { 'background-color': 'rgba( 175, 213, 240, 0.1)' } : null"
                                    :class="{
                                        'showBorder': i % 4 === 0,
                                        'hideBorder': i === 0 || i % 4 !== 0
                                    }"
                                    :date="calendarObj.date"
                                    :events="generateEventForTimestamp( timestamp.customFormat, calendarObj.events, calendarObj.date )"
                                    cellType="calendarObj"
                                    :view_preference="view_preference"
                                    @createSchedule_emitted="createSchedule_emitted"
                                    @clickSchedule_emitted="clickSchedule_emitted"
                                ></calendar-cell-component>
                            </template>
                        </template>
                    </div>
                </div>
                <!-- spinner while loading -->
                <div v-if="loading" class="cardBodySpinnerWrap relative active">
                    <div class="cardBodySpinner centeredBlock"></div>
                </div>
            </div>
        </div>
    </div>
</script>
<script>
    /* ----- STORE ----- */
    store.components["calendar_grid"] = {
        calendar: [],
        loading: true,
        view_preference: 'Month',
        dropdownOpen: false,
        daysOfWeek: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
        placeholder_daysOfWeek: [],
        today_daysOfWeek: [],
        view_options: [ 'Month', 'Week', 'Day' ],
        calendarTitle: null,
        //dates and times
        currentDate: dayjs() || new Date(),
        defaultDate: dayjs() || new Date(),
        currentMonth: dayjs().format('MMMM'),
        startOfWeek: dayjs().startOf('week'), 
        endOfWeek: dayjs().endOf('week'),
        currentYear: dayjs().year(),
        timestamps: [],
        currentTime: dayjs().format('HH:mm:ss'),
    };

    /* ----- COMPONENT ----- */
    app_content.component("calendar-grid-component", {
        template: "#template-calendar-grid",
        data() {
            return store.components['calendar_grid']
        },
        created(){
            if (this.timestamps.length === 0){
                this.generateTimestamps();  
            }
        },
        props: {
            client_id: String,
            class_string: String,
            style_string: String,
            filterOptions: Array,
            selectedFilterOptions: Array,
            schedules: Array,
            is_membership_cal: Boolean,
            load_cal: Function,
            handleFilterSelection: Function,
            createSchedule: Function,
            clickSchedule: Function,
        },
        methods: {
            createSchedule_emitted( date ){
                this.$emit('createSchedule', date)
            },
            clickSchedule_emitted( event ){
                this.$emit('clickSchedule', event )
            },
            formatShortTime( timeString ){
                if (!timeString){
                    return '' // placeholder for 11:45-12:00 block
                }
                // if (timeString === '12:00 AM'){
                //     return Intl.DateTimeFormat().resolvedOptions().timeZone;
                // }
                const [hours, minutes] = timeString.split(':');
                const AM_PM = minutes.split(' ')[1]
                return `${hours} ${AM_PM}`;
            },
            generateWrapStyle( type ){
                if (type === 'cs-calendar-wrap'){
                    return this.style_string === undefined ? {'width': '100%'} : this.style_string;
                } else if (type === 'options' && this.is_membership_cal){
                    return { 
                        'padding-top': '15px', 
                        'padding-right': '15px', 
                        'padding-left': '15px', 
                        'padding-bottom': '5px', 
                        'border-width': '0 1.5px 0 1.5px', 
                        'border-color': '#e2e8e8', 
                        'border-style': 'solid',
                        'overflow': 'auto',
                    }
                } else if (type === 'cs-calendar-menu-wrap' && this.is_membership_cal){
                    return { 
                        'border-width': '0 1.5px 0 1.5px', 
                        'border-color': '#e2e8e8', 
                        'border-style': 'solid' 
                    }
                }
            },
            generateEventForTimestamp( timestamp, events, date ){
                // do not want to display all day or multiple day events -- being handled separately
                let eventsArr = [];
                if (events.length > 0){
                    for (let i = 0; i < events.length; i++){
                        let event = events[i];
                        // normal event
                        if ((event.hours_mins_start && event.hours_mins_end) && !event.isAllDay && event.calendarOnly) {
                            let startTime = dayjs().set('hour', event.hours_mins_start.hours).set('minute', event.hours_mins_start.minutes);
                            let endTime = dayjs().set('hour', event.hours_mins_end.hours).set('minute', event.hours_mins_end.minutes).subtract(15, 'minutes');

                            let formattedStartTime = startTime.format('h:mm A');
                            let formattedEndTime = endTime.format('h:mm A');

                            let timesArray = [formattedStartTime];
                            while (startTime.isBefore(endTime)) {
                                startTime = startTime.add(15, 'minutes');
                                timesArray.push(startTime.format('h:mm A'));
                            }
                            if ( formattedStartTime === timestamp ){    
                                eventsArr.push({ event, numOfTimeBlocks: timesArray.length });
                            }
                        // recurring event
                        } else if ( (event.start && event.end) && (event.start !== event.end) && !event.isAllDay && !event.isMultipleDay && event.calendarOnly ){
                            let startTime = dayjs(event.start);
                            let endTime = dayjs(event.end).subtract(15, 'minutes');

                            let formattedStartTime = startTime.format('h:mm A');
                            let formattedEndTime = endTime.format('h:mm A');

                            let timesArray = [formattedStartTime];

                            while (startTime.isBefore(endTime)) {
                                startTime = startTime.add(15, 'minutes');
                                timesArray.push(startTime.format('h:mm A'));
                            }
                            if ( formattedStartTime === timestamp ){    
                                eventsArr.push({ event, numOfTimeBlocks: timesArray.length });
                            }
                        // non-calendarOnly events
                        } else if ( (event.start && event.end) && (event.start !== event.end) && !event.calendarOnly ){
                            let startTime;
                            let endTime;

                            if (dayjs(event.start).startOf('day').$d.toString() === dayjs(date).startOf('day').$d.toString()){
                                startTime = dayjs(event.start);
                                endTime = dayjs(event.end).subtract(15, 'minutes');
                            } else if (dayjs(event.end).startOf('day').$d.toString() === dayjs(date).startOf('day').$d.toString()) {
                                startTime = dayjs(event.end).startOf('day');
                                endTime = dayjs(event.end).subtract(15, 'minutes');
                            } else {
                                startTime = dayjs().startOf('day');
                                endTime = dayjs().endOf('day');
                            }

                            let formattedStartTime = startTime.format('h:mm A');
                            let formattedEndTime = endTime.format('h:mm A');

                            let timesArray = [formattedStartTime];

                            while (startTime.isBefore(endTime)) {
                                startTime = startTime.add(15, 'minutes');
                                timesArray.push(startTime.format('h:mm A'));
                            }
                            if ( formattedStartTime === timestamp ){    
                                eventsArr.push({ event, numOfTimeBlocks: timesArray.length });
                            }
                        }
                    } 
                }
                if (eventsArr.length > 0){
                    return eventsArr;
                } else {
                    return [];
                }
            },
            changeViewPreference(){
                this.loading = true;
                //and re-load data
                this.$emit('load_cal', this.client_id);
            },
            calculateTitleRange(){
                if ( this.view_preference === 'Month' ){
                    this.calendarTitle = `${this.currentMonth} ${this.currentYear.toString()}`;
                } else if ( this.view_preference === 'Week' ){
                    this.calendarTitle = `${this.startOfWeek.format('MMMM')} ${this.startOfWeek.$D} - ${this.endOfWeek.format('MMMM')} ${this.endOfWeek.$D}`;
                } else if ( this.view_preference === 'Day' ){
                    this.calendarTitle = `${this.currentMonth} ${this.currentDate.$D}, ${this.currentYear}`;
                }
            },
            handleButtonClick( option, selectedDate ){
                this.loading = true;
                if (this.view_preference === 'Month'){
                    if( option === "today" ){
                        this.currentDate = dayjs();
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if( option === "next" ){
                        this.currentDate = this.currentDate.add(1, 'month').startOf('month');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');

                    }else if( option === "previous" ){
                        this.currentDate = this.currentDate.subtract(1, 'month').startOf('month');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if ( option === "date-picker" ){
                        let { month, year } = selectedDate;
                        this.currentDate = dayjs(new Date(year, month, 1));
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }
                } else if (this.view_preference === 'Week'){
                    if( option === "today" ){
                        this.currentDate = dayjs();
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if( option === "next" ){
                        this.currentDate = this.currentDate.add(1, 'week');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if( option === "previous" ){
                        this.currentDate = this.currentDate.subtract(1, 'week');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if ( option === "date-picker" ){
                        let { month, year } = selectedDate;
                        this.currentDate = dayjs(new Date(year, month, 1));
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }
                } else if (this.view_preference === 'Day'){
                    if( option === "today" ){
                        this.currentDate = dayjs();
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if( option === "next" ){
                        this.currentDate = this.currentDate.add(1, 'day');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if( option === "previous" ){
                        this.currentDate = this.currentDate.subtract(1, 'day');
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }else if ( option === "date-picker" ){
                        let { month, year } = selectedDate;
                        this.currentDate = dayjs(new Date(year, month, 1));
                        this.currentMonth = this.currentDate.format('MMMM')
                        this.currentYear = this.currentDate.$y
                        this.startOfWeek = this.currentDate.startOf('week');
                        this.endOfWeek = this.currentDate.endOf('week');
                    }
                }
                //and re-load data
                this.$emit('load_cal', this.client_id);
            },
            /* ----- date methods ----- */
            generateTimestamps(){
                const startTime = dayjs().startOf('day');
                const endTime = dayjs().endOf('day');
                let currentTime = startTime;
                while (currentTime.isBefore(endTime)) {
                    this.timestamps.push({
                        customFormat: currentTime.format('h:mm A'),
                        militaryFormat: currentTime.format('HH:mm:ss'),
                    });
                    currentTime = currentTime.add(15, 'minutes');
                }
                this.timestamps.push({
                    customFormat: null,
                    militaryFormat: null,
                })
            },
            generateCalendar( ){
                console.log("generate calendar")
                this.loading = true;
                if ( this.view_preference === 'Month'){
                    // current month start date, end date, total days calculation
                    const start = this.currentDate.startOf('month');
                    const end = start.endOf('month');
                    const totalDays = end.diff(start, 'day') + 1;
                    // number of calendar days to add before and after current month days
                    const spaceBefore = start.day();
                    const spaceAfter = 42 - (spaceBefore + totalDays);
                    // generate number of days for grid cell of 42
                    this.calendar = [...Array(spaceBefore)].map((_, i) => {
                        const prevMonthDate = start.subtract(spaceBefore - i, 'day');
                        return {
                            date: prevMonthDate,
                            day: prevMonthDate.$D,
                            class: 'prevMonthDate',
                            events: [],
                            defaultDate: false,
                        }
                    }).concat([...Array(totalDays)].map((_, i) => {
                        const currentMonthDate = start.add(i, 'day');
                        if (this.defaultDate.startOf('day').$d.toString() === currentMonthDate.$d.toString()){
                            return {
                                date: currentMonthDate,
                                day: currentMonthDate.$D === 1 ? `${currentMonthDate.format('MMM')} ${currentMonthDate.$D}` : currentMonthDate.$D,
                                class: 'currentMonthDate',
                                events: [],
                                defaultDate: true,
                            }
                        }else {
                            return {
                                date: currentMonthDate,
                                day: currentMonthDate.$D === 1 ? `${currentMonthDate.format('MMM')} ${currentMonthDate.$D}` : currentMonthDate.$D,
                                class: 'currentMonthDate',
                                events: [],
                                defaultDate: false,
                            }
                        }
                    })).concat([...Array(spaceAfter)].map((_, i) => {
                        const nextMonthDate = end.add(i + 1, 'day');
                        return {
                            date: nextMonthDate,
                            day: nextMonthDate.$D === 1 ? `${nextMonthDate.format('MMM')} ${nextMonthDate.$D}` : nextMonthDate.$D,
                            class: 'nextMonthDate',
                            events: [],
                            defaultDate: false,
                        }
                    }))
                } else if ( this.view_preference === 'Week' ){
                    console.log("generate week A")
                    // start and end of current week
                    const startOfWeek = this.currentDate.startOf('week');
                    const endOfWeek = this.currentDate.endOf('week');

                    const weekDays = [{ date: null, day: null, events: [] }];
                    let currentDay = startOfWeek;
                    while (currentDay.isBefore(endOfWeek) || currentDay.isSame(endOfWeek, 'day')) {
                        weekDays.push(currentDay);
                        currentDay = currentDay.add(1, 'day');
                    }
                    this.placeholder_daysOfWeek = [null, 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
                    this.placeholder_daysOfWeek = this.placeholder_daysOfWeek.map((dayOfTheWeek, i) => {
                        if (JSON.stringify(this.defaultDate.startOf('day').$d) === JSON.stringify(weekDays[i].$d)){
                            return {
                                dayOfWeek: dayOfTheWeek,
                                day: weekDays[i].$D,
                                date: weekDays[i],
                                events: [],
                                defaultDate: true,
                            }
                        } else {
                            return {
                                dayOfWeek: dayOfTheWeek,
                                day: weekDays[i].$D,
                                date: weekDays[i],
                                events: [],
                                defaultDate: false,
                            }
                        }
                    })
                    console.log("generate week B")
                    this.mapAllDayEvents();
                    this.calendar = weekDays.map(date => {
                        if(JSON.stringify(this.defaultDate.startOf('day').$d) === JSON.stringify(date.$d)){
                            return {
                                date: date,
                                events: [],
                                defaultDate: true,
                            }
                        } else {
                            return {
                                date: date,
                                events: [],
                                defaultDate: false,
                            }   
                        }
                    })
                    console.log("generate week C")
                } else if ( this.view_preference === 'Day' ){
                    this.today_daysOfWeek = [null, this.daysOfWeek[this.currentDate.day()]]
                    this.today_daysOfWeek = this.today_daysOfWeek.map((dayOfTheWeek, i) => {
                        if (i === 1 && this.defaultDate.startOf('day').$d.toString() === this.currentDate.startOf('day').$d.toString()){
                            return {
                                dayOfWeek: dayOfTheWeek,
                                day: dayOfTheWeek !== null ? this.currentDate.$D : null,
                                date: dayOfTheWeek !== null ? this.currentDate : null,
                                events: [],
                                defaultDate: true,
                            }
                        } else {
                            return {
                                dayOfWeek: dayOfTheWeek,
                                day: dayOfTheWeek !== null ? this.currentDate.$D : null,
                                date: dayOfTheWeek !== null ? this.currentDate : null,
                                events: [],
                                defaultDate: false,
                            }
                        }
                    })
                    this.mapAllDayEvents();
                    this.calendar = [{ date: null, day: null, events: [] }, this.currentDate ].map((date, i) => {
                        if(i === 1 && this.defaultDate.startOf('day').$d.toString() === date.startOf('day').$d.toString()){
                            return {
                                date: date,
                                events: [],
                                defaultDate: true,
                            }
                        } else {
                            return {
                                date: date,
                                events: [],
                                defaultDate: false,
                            }
                        }
                    })
                }
                // map events onto calendar days
                this.mapCalendarEvents_v2();
            },
            // mapCalendarEvents(){
            //     let multipleDaySchedules = [];
            //     this.calendar.map(day => {
            //         let calendarDay;
            //         if ( day.date !== null ){
            //             calendarDay = dayjs(day.date.$d).format('MMMM DD, YYYY');
            //         }
            //         this.schedules.forEach(schedule => {
            //             let scheduleStart = dayjs( schedule.start ).format('MMMM DD, YYYY');
            //             let scheduleEnd = dayjs( schedule.end ).format('MMMM DD, YYYY');
            //             let scheduleOnDay = scheduleStart === calendarDay && scheduleStart === scheduleEnd;
            //             let scheduleOnDay_isAllDay = scheduleStart === calendarDay && schedule.isAllDay;
            //             // check to see if there are any multiple event days
            //             if ( multipleDaySchedules.length > 0 ){
            //                 multipleDaySchedules.forEach((multipleDaySchedule, i) => {
            //                     if ( multipleDaySchedule.daysRemaining > 0 && calendarDay === multipleDaySchedule.scheduleStart.format('MMMM DD, YYYY')){
            //                         day.events.push(multipleDaySchedule.schedule)
            //                         multipleDaySchedule.scheduleStart = multipleDaySchedule.scheduleStart.add(1, 'day')
            //                         multipleDaySchedule.daysRemaining--;
            //                     } else if ( multipleDaySchedule.daysRemaining === 0 ){
            //                         multipleDaySchedules.splice(i, 1)
            //                     }
            //                 })
            //             }
            //             // there is an event or all day event on this day
            //             if ( scheduleOnDay || scheduleOnDay_isAllDay ){
            //                 day.events.push(schedule)
            //             // there is a multiple day event that starts on this day
            //             } else if ( scheduleStart === calendarDay && scheduleStart !== scheduleEnd && !schedule.isAllDay ){
            //                 multipleDaySchedules.push({
            //                     schedule: schedule,
            //                     scheduleStart: dayjs(scheduleStart, { format: 'MMMM DD, YYYY' }).add(1, 'day'),
            //                     daysRemaining: dayjs(scheduleEnd, { format: 'MMMM DD, YYYY' }).diff(dayjs(scheduleStart, { format: 'MMMM DD, YYYY' }), 'day') - 1
            //                 })
            //                 schedule.isMultipleDay = true;
            //                 day.events.push(schedule);
            //             }
            //         })
            //         return day;
            //     })
            //     console.log('this is final mapping: ', this.calendar)
            //     this.loading = false;
            // },
            mapCalendarEvents_v2(){
                console.log("map calendar events v2");
                let previousDayEventOrder = [];
                this.calendar.map((day, dayIndex) => {
                    let calendarDay;
                    if ( day.date !== null ){
                        calendarDay = dayjs(day.date.$d)
                    }
                    this.schedules.forEach(schedule => {
                        let scheduleStart = dayjs( schedule.start )
                        let scheduleEnd = dayjs( schedule.end )
                        let scheduleOnDay = scheduleStart.format('MMMM DD, YYYY') === calendarDay.format('MMMM DD, YYYY') && scheduleStart.format('MMMM DD, YYYY') === scheduleEnd.format('MMMM DD, YYYY');
                        let scheduleOnDay_isAllDay = scheduleStart.format('MMMM DD, YYYY') === calendarDay.format('MMMM DD, YYYY') && schedule.isAllDay;
                        // event falls on current day OR it's an all day event
                        // added scheduleOnDay && scheduleOnDay_isAllDay 1/25/24 for regatta subevents start start and end on the same day
                        if ( scheduleOnDay && !scheduleOnDay_isAllDay || scheduleOnDay && scheduleOnDay_isAllDay ){
                            day.events.push(schedule)
                        } 
                        // it's the first day of a multiple day event
                        // these checks are not thorough enough
                        else if (scheduleStart.format('MMMM DD, YYYY') === calendarDay.format('MMMM DD, YYYY') && scheduleStart.format('MMMM DD, YYYY') !== scheduleEnd.format('MMMM DD, YYYY')){
                            schedule.isMultipleDay = true;
                            day.events.push(schedule)
                        }
                        // it's a multiple day event and the current date falls between the start and end date
                        else if ( scheduleStart.format('MMMM DD, YYYY') !== calendarDay.format('MMMM DD, YYYY') && (calendarDay.isAfter(scheduleStart) && calendarDay.isBefore(scheduleEnd)) ){
                            schedule.isMultipleDay = true;
                            day.events.push(schedule)
                        }  
                    })

                    /* ui stacking logic for month view */
                    if (this.view_preference === 'Month'){
                        if ( dayIndex !== 0 ){
                            let currentDayEventOrder;
                            let currentDayIndexOrder = {};
                            let notMatchingEvents = [];
                            let matchingEvents = [];
                            for (let i = 0; i < day.events.length; i++){
                                let currentDayEventId = day.events[i].id;
                                let previousDayIndex = previousDayEventOrder?.indexOf(currentDayEventId);
                                if (previousDayIndex === -1){
                                    notMatchingEvents.push(day.events[i])
                                } else if (previousDayIndex !== -1) {
                                    currentDayIndexOrder[previousDayIndex] = day.events[i];
                                    matchingEvents.push(day.events[i]);
                                }
                            }

                            let missingIndexes = [];
                            for (let j = 0; j < 3; j++ ){
                                if (Object.keys(currentDayIndexOrder).indexOf(j.toString()) === -1 ){
                                    missingIndexes.push(j)
                                }
                            }
                   
                            let placeholder = { 
                                bgColor: '',
                                calendarId: '',
                                calendarOnly: '',
                                category: '',
                                className: '',
                                color: '',
                                end: '',
                                id: 'placeholder',
                                raw: {dot_color: ''},
                                start: '',
                                title: 'placeholder',
                            };

                            for (let k = 0; k < missingIndexes.length; k++){
                                let missingIndexValue = missingIndexes[k];
                                currentDayIndexOrder[missingIndexValue] = notMatchingEvents[k] || placeholder;
                            }

                            let remainingIndexes = day.events.length - 3;
                            let calculateRemainingEvents = matchingEvents.length > 3 ? matchingEvents.concat(notMatchingEvents).splice(3) : [...notMatchingEvents].splice(missingIndexes.length);

                            if (remainingIndexes > 0){
                                for (let l = 3; l < 3 + remainingIndexes; l++){
                                    let targetIndex = matchingEvents.length > 3 ? l - 3 : l - 3;
                                    //added placeholder for white lake yacht club bugs
                                    currentDayIndexOrder[l] = calculateRemainingEvents[targetIndex] || placeholder;
                                }
                            }

                            const sortedObj = Object.fromEntries(
                                Object.entries(currentDayIndexOrder).sort(([keyA], [keyB]) => parseInt(keyA) - parseInt(keyB))
                            );
                            currentDayEventOrder = Object.values(sortedObj);
                            //set order of previous day events using event ids
                            previousDayEventOrder = currentDayEventOrder.map(event => { return event.id });
                            //set current day events to newly sorted order
                            day.events = currentDayEventOrder.filter((event, i, self) => event.id === 'placeholder' || (event.id !== 'placeholder' && i === self.findIndex(e => e.id === event.id)));
                        }
                    }

                    return day;
                })
                this.loading = false;
            },
            mapAllDayEvents(){
                let daysOfWeekArr;
                if (this.view_preference === 'Week'){
                    daysOfWeekArr = this.placeholder_daysOfWeek;
                } else if (this.view_preference === 'Day'){
                    daysOfWeekArr = this.today_daysOfWeek;
                }
                let multipleDaySchedules = [];
                daysOfWeekArr = daysOfWeekArr.map((day, i) => {
                    this.schedules.forEach((schedule, i) => {
                        if ( (i !== 0 && this.view_preference === 'Day' || i !== 0 && this.view_preference === 'Week') && ( schedule.calendarOnly || schedule.category === 'allday') ){
                            let calendarDay = dayjs(day.date)
                            let scheduleStart = dayjs( schedule.start )
                            let scheduleEnd = dayjs( schedule.end )
                            let scheduleOnDay_isAllDay = scheduleStart.format('MMMM DD, YYYY') === calendarDay.format('MMMM DD, YYYY') && schedule.isAllDay;
                            // it's an all day event
                            if ( scheduleOnDay_isAllDay ){
                                day.events.push(schedule)
                            } 
                            // it's the first day of a multiple day event
                            else if (scheduleStart.format('MMMM DD, YYYY') === calendarDay.format('MMMM DD, YYYY') && scheduleStart.format('MMMM DD, YYYY') !== scheduleEnd.format('MMMM DD, YYYY')){
                                schedule.isMultipleDay = true;
                                day.events.push(schedule)
                            }
                            // it's a multiple day event and the current date falls between the start and end date
                            else if ( scheduleStart.format('MMMM DD, YYYY') !== calendarDay.format('MMMM DD, YYYY') && (calendarDay.isAfter(scheduleStart) && calendarDay.isBefore(scheduleEnd)) ){
                                schedule.isMultipleDay = true;
                                day.events.push(schedule)
                            }
                        } 
                    })
                    return day;
                })
                if (this.view_preference === 'Week'){
                    this.placeholder_daysOfWeek = daysOfWeekArr;
                } else if (this.view_preference === 'Day'){
                    this.today_daysOfWeek = daysOfWeekArr;
                }
            },
        },
    })
</script>    <script type="text/html" id="template-calendar-cell">
    <div @click="$emit('createSchedule_emitted', date)">
        <!-- cell for month view -->
        <template v-if="view_preference === 'Month'">
            <div class="cell-content" :class="cellType">
                <div v-if="day" class="cell-day" :class="cellType" :style="checkDefaultDate( day, defaultDate, 'month' )">{{ day }}</div>
                <!-- all events -->
                <div v-if="cellType === 'calendarObj' && events.length > 0" class="cell-events-month" ref="cell" @click.stop>
                    <template v-for="(event, index) in events">
                        <span
                            v-if="index <= 2"
                            :class="{
                                'cell-event-month': event.id !== 'placeholder',
                                'transparent-event': event.id === 'placeholder'
                            }"
                            :style="generateEventStyleForMonth( event, 'event_body', date, monthIndex )"
                            @click="handleScheduleClickForMonth( event )"
                        ><div :style="generateEventStyleForMonth( event, 'status_dot', '', '', month_class )"></div><div class="event-title" :style="generateFontSize('eventTitle', event)">{{ generateEventTitle( event ) }}</div></span>
                        <span v-if="index >= 3 && index === events.length - 1" class="overflow-cell-events" ref="overflow-cell" @click="toggleOverflowView( date, events, $event )">
                            <div :style="[ { display: 'flex' }, generateFontSize('eventTitle') ]" class="event-title">{{ index - 2 }} more</div>
                        </span>
                    </template>
                </div>
            </div>
        </template>
        <!-- cell for week view -->
        <template v-if="view_preference === 'Week'">
            <div class="cell-content-week" :class="cellType">
                <div v-if="day" :class="{ 'week-cellDay-container' : day.dayOfWeek !== null }">
                    <div class="cell-day numberHeader" :class="cellType" :style="[{ 'font-size': '25px', 'font-weight': '400' }, checkDefaultDate(day, defaultDate, 'week_header')]">{{ day.day }}</div>
                    <div class="cell-day dayHeader" :class="cellType">{{ day.dayOfWeek !== null ? day.dayOfWeek.toUpperCase() : null }}</div>
                </div>
                <div v-if="timestamp" class="cell-day" :class="cellType">
                    <div class="timestamp"  :style="generateFontSize('timestamp')">{{ timestamp }}</div>
                </div>
                <!-- all day events -->
                <div v-if="allDay">
                    <div v-if="allDay.dayOfWeek === null" class="allDay_events" :class="cellType" :style="generateFontSize('allDay')">All Day</div>
                    <div class="cell-events-month">
                        <template v-if="allDay.dayOfWeek !== null" v-for="event in allDay.events">
                            <span
                                :style="generateEventStyleForWeek( event, 'allDay_event_body' )"
                                class="allDay-cell-event"
                                @click="$emit('clickSchedule_emitted', event)"
                            >{{ generateEventTitle( event ) }}</span>
                        </template>
                    </div>
                </div>
                 <!-- all events -->
                <div v-if="cellType === 'calendarObj' && events.length > 0" class="cell-events-week" @click.stop>
                    <template v-for="(event, index) in events">
                        <span
                            class="cell-event-week"
                            :style="generateEventStyleForWeek( event, 'event_body' )"
                            @click="$emit('clickSchedule_emitted', event.event)"
                        ><div></div>{{ generateEventTitle( event.event ) }}</span>
                    </template>
                </div>
            </div>
        </template>
        <!-- cell for day view -->
        <template v-if="view_preference === 'Day'">
            <div class="cell-content-week" :class="cellType">
                <div v-if="day" :class="{ 'day-cellDay-container' : day.dayOfWeek !== null }">
                    <div class="cell-day numberHeader" :class="cellType" :style="[{ 'font-size': '25px', 'font-weight': '400' }, checkDefaultDate(day, defaultDate, 'day_header')]">{{ day.day }}</div>
                    <div class="cell-day dayHeader" :class="cellType">{{ day.dayOfWeek !== null ? day.dayOfWeek.toUpperCase() : null }}</div>
                </div>
                <div v-if="timestamp" class="cell-day" :class="cellType">
                    <div class="timestamp" :style="generateFontSize('timestamp')">{{ timestamp }}</div>
                </div>
                <!-- all day events -->
                <div v-if="allDay">
                    <div v-if="allDay.dayOfWeek === null" class="allDay_events" :class="cellType" :style="generateFontSize('allDay')">All Day</div>
                    <div class="cell-events-month">
                        <template v-if="allDay.dayOfWeek !== null" v-for="event in allDay.events">
                            <span
                                :style="generateEventStyleForWeek( event, 'allDay_event_body' )"
                                class="allDay-cell-event"
                                @click="$emit('clickSchedule_emitted', event)"
                            >{{ generateEventTitle( event ) }}</span>
                        </template>
                    </div>
                </div>
                <!-- all events -->
                <div v-if="cellType === 'calendarObj' && events.length > 0" class="cell-events-week" @click.stop>
                    <template v-for="(event, index) in events">
                        <span
                            class="cell-event-week"
                            :style="generateEventStyleForWeek( event, 'event_body' )"
                            @click="$emit('clickSchedule_emitted', event.event )"
                        ><div></div>{{ generateEventTitle( event.event ) }}</span>
                    </template>
                </div>
            </div>
        </template>
    </div>
</script>

<script>
    /* ----- STORE ----- */
    store.components["calendar_cell"] = {
        cellWidth: this.getCellWidth,
        foo: null,
    };
    /* ----- COMPONENT ----- */
    app_content.component("calendar-cell-component", {
        template: "#template-calendar-cell",
        data() {
            return store.components['calendar_cell']
        },
        mounted(){
            window.addEventListener('resize', this.handleResize);
            this.$nextTick(() => {
                this.handleResize();
            });
        },
        beforeDestroy(){
            window.removeEventListener('resize', this.handleResize);
        },
        props: {
            client_id: String,
            date: Object,
            defaultDate: Boolean,
            day: {
                type: [String, Number, Object],
                required: false,
            },
            allDay: Object,
            timestamp: String,
            currentTime: String,
            events: Array,
            cellType: String,
            view_preference: String,
            monthIndex: Number,
            month_class: String,
            is_membership_cal: Boolean,
            cell_emitted: Function,
            createSchedule_emitted: Function,
            clickSchedule_emitted: Function,
        },
        methods: {
            handleResize(){
                this.cellWidth = this.getCellWidth();
            },
            getCellWidth(){
                const cell = this.$refs.cell;
                // Get the computed width of the cell
                if (cell){
                    this.cellWidth = cell.getBoundingClientRect().width;
                    return cell.getBoundingClientRect().width;
                }
            },
            checkDefaultDate( day, defaultDate, type ){
                if( defaultDate ){
                    if ( type === 'month' ){
                        if ( day.length > 2){
                            return {
                                'padding': '2.5px',
                                'background-color': '#2d59d5',
                                'color': '#fff',
                                'min-width': 'fit-content',
                                'max-width': 'fit-content',
                                'min-height': 'fit-content',
                                'max-height': 'fit-content',
                            }
                        } else {
                            return {
                                'background-color': '#2d59d5',
                                'color': '#fff',
                                'min-width': '22px',
                                'max-width': '22px',
                                'min-height': '22px',
                                'max-height': '22px',
                            }
                        }
                    } else if ( type === 'week_header' || type === 'day_header' ){
                        return {
                            'font-weight': '575',
                            // 'color': '#2d59d5',
                        }
                    }
                } else if ( !defaultDate ){
                    if ( type === 'month' ){
                        if ( day.length > 2){
                            return {
                                'padding': '2.5px',
                                'min-width': 'fit-content',
                                'max-width': 'fit-content',
                                'min-height': 'fit-content',
                                'max-height': 'fit-content',
                            }
                        } else {
                            return {
                                'min-width': '22px',
                                'max-width': '22px',
                                'min-height': '22px',
                                'max-height': '22px',
                            }
                        }
                    }
                }
            },
            generateEventTitle( eventObject ){
                if ( !eventObject.isAllDay && !eventObject.isMultipleDay ) {
                    return eventObject.raw.nice_time !== undefined ? `${eventObject.raw.nice_time} ${eventObject.title}` : `${eventObject.title}`;
                } else if ( eventObject.isAllDay || eventObject.isMultipleDay ) {
                    return eventObject.title || 'Not Provided';
                }
            },
            generateFontSize( type, eventObject ){
                if (this.is_membership_cal){
                    if (type === 'timestamp') {
                        return {
                            'font-size': '12px', 
                            'font-weight': '300',
                        }
                    } else if (type === 'allDay'){
                        return {
                            'font-size': '13px',
                        }
                    } else if (type === 'eventTitle'){
                        if (eventObject?.id === 'placeholder'){
                            return {
                                'color': 'transparent',
                                'font-size': '13px',
                            }
                        } 
                        return {
                            'font-size': '13px',
                        }
                    }
                } else {
                    if (type === 'timestamp') {
                        return {
                            'font-size': '10px', 
                            'font-weight': '300',
                        }
                    } else if (type === 'allDay'){
                        return {
                            'font-size': '11px',
                        }
                    }else if (type === 'eventTitle'){
                        if (eventObject?.id === 'placeholder'){
                            return {
                                'color': 'transparent',
                                'font-size': '12.5px',
                            }
                        } 
                        return {
                            'font-size': '12.5px',
                        }
                    }
                }
            },
            generateEventStyleForMonth( eventObject, type, date = null, monthIndex = null, month_class = null ){
                let styleObject = {};
                const dotColor = eventObject.raw.dot_color;
                const bgColor = eventObject.bgColor || '#e8edf1';
                const color = /* eventObject.color || */ this.get_contrast_color( bgColor ) || 'inherit';
                if ( type === 'status_dot' ){
                    if ( eventObject.id === 'placeholder' ){
                        styleObject = {
                            'color': 'trasparent',
                        }
                    } else if ( !eventObject.isAllDay && !eventObject.isMultipleDay ) {
                        if ( month_class === 'currentMonthDate' ){
                            styleObject = {
                                'min-width': '2.2px',
                                'max-width': '2.2px',
                                'min-height': '2.2px',
                                'max-height': '2.2px',
                                'border': `2.2px solid ${dotColor || '#333'}`,
                                'border-radius': '50%',
                                'background-color': `${dotColor || '#333'}`,
                                'margin': '0 5px 0 5px',
                            }
                        } else if ( month_class === 'prevMonthDate' || month_class === 'nextMonthDate' ){
                            styleObject = {
                                'min-width': '2.2px',
                                'max-width': '2.2px',
                                'min-height': '2.2px',
                                'max-height': '2.2px',
                                'border': `2.2px solid rgb(232, 237, 241)`,
                                'border-radius': '50%',
                                'background-color': `rgb(232, 237, 241)`,
                                'margin': '0 5px 0 5px',
                            }
                        }
                    } else if ( eventObject.isAllDay || eventObject.isMultipleDay ){
                        styleObject = {
                            'margin-right': '3.5px',
                        }
                    }
                } else if ( type === 'event_body' ){
                    if ( eventObject.isAllDay && !eventObject.isMultipleDay ) {
                        styleObject = {
                            'background-color': bgColor,
                            'color': color,
                        };
                    } else if ( eventObject.isMultipleDay ){
                        let calendarDay = dayjs(date.$d).format('MMMM DD, YYYY');
                        let scheduleStart = dayjs( eventObject.start ).format('MMMM DD, YYYY');
                        let scheduleEnd = dayjs( eventObject.end ).format('MMMM DD, YYYY');
                        let isOneDay = ((dayjs( eventObject.start ).format('HH:mm:ss') === dayjs( eventObject.end ).format('HH:mm:ss')) && (dayjs( eventObject.start ).format('HH:mm:ss') === dayjs( eventObject.start ).startOf('day').format('HH:mm:ss'))) && dayjs( eventObject.start ).add(1, 'day').format('MMMM DD, YYYY') === scheduleEnd;
                        let endsAtMidnight = dayjs( eventObject.end ).format('HH:mm:ss') === dayjs().startOf('day').format('HH:mm:ss');
                        if (calendarDay === scheduleStart || monthIndex % 7 === 0 ){
                            let remainingDays = dayjs(scheduleEnd, { format: 'MMMM DD, YYYY' }).diff(dayjs(calendarDay, { format: 'MMMM DD, YYYY' }), 'day');
                            //handle non-calendarOnly events since end time is different than calendarOnly events
                            if (!eventObject.calendarOnly && !isOneDay && !endsAtMidnight ){
                                remainingDays += 1;
                            }
                            if (this.cellWidth === undefined){
                                styleObject = {
                                    'background-color': bgColor,
                                    'color': color,
                                    'z-index': '5',
                                    'width' : `${remainingDays*this.getCellWidth()}px`
                                };
                            } else {
                                styleObject = {
                                    'background-color': bgColor,
                                    'color': color,
                                    'z-index': '5',
                                    'width': `${remainingDays*this.cellWidth}px`
                                };
                            }
                        }
                    }
                }
                return styleObject
            },
            generateEventStyleForWeek( eventObject, type ){
                const event = eventObject.event || eventObject;
                const numOfTimeBlocks = eventObject.numOfTimeBlocks;

                let styleObject = {};
                const dotColor = event?.raw.dot_color;
                const bgColor = event?.bgColor || '#e8edf1';
                const color = /* event?.color */ this.get_contrast_color( bgColor ) || 'inherit';

                if ( type === 'event_body' ){
                    if ( event ) {
                        styleObject = {
                            'background-color': dotColor || bgColor,
                            'color': color,
                            'width': '50%',
                            'border-width': '1px 1px 1px 1.5px',
                            'border-left-color': 'black',
                            'border-top-color':'white',
                            'border-right-color':'transparent',
                            'border-bottom-color': 'white',
                            'border-style': 'solid',
                            'border-radius': '2px',
                            'opacity': '85%',
                            'z-index': '5',
                            'height': `${(numOfTimeBlocks*12) - 5}px`, /* (number of 15 min increments * .placeholder-calendar-grid > grid-auto-rows) - .cell-event-week > padding(top) */
                        };
                    }
                } else if ( type === 'allDay_event_body' ){
                    if ( event ) {
                        styleObject = {
                            'background-color': dotColor || bgColor,
                            'color': color,
                        };
                    }
                }
                return styleObject
            },
            toggleOverflowView( date, eventsArr, event ){
                if (store.overlays.overflow_overlay){
                    store.overlays.overflow_overlay = false;
                } else {
                    store.components.overflow_overlay.cellPosition = {
                        top: (event.clientY + window.scrollY)-(230/2), //230 overlay height
                        left: (event.clientX + window.scrollX)-(230/2), //230 overlay width
                    }
                    if (this.is_membership_cal){
                        store.components.overflow_overlay.is_membership_cal = true;
                    }
                    store.components.overflow_overlay.client_id = this.client_id;
                    store.components.overflow_overlay.date = date;
                    store.components.overflow_overlay.events = eventsArr;
                    store.overlays.overflow_overlay = true;
                }
            },
            handleScheduleClickForMonth( event ){
                if (event.id !== 'placeholder') {
                    this.$emit('clickSchedule_emitted', event);
                } else {
                    this.$emit('createSchedule_emitted', this.date);
                }
            },
            //methods to determine font color in contrast to bg color
            calculate_luminance(color) {
                const hex = color.substring(1); //remove #
                const rgb = parseInt(hex, 16); //convert to RGB
                const r = (rgb >> 16) & 0xff; //extract the red channel
                const g = (rgb >>  8) & 0xff; //extract the green channel
                const b = (rgb >>  0) & 0xff; //extract the blue channel
                //convert RGB to linear values
                const sR = r / 255;
                const sG = g / 255;
                const sB = b / 255;
                //calculate luminance
                const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
                return luminance;
            },
            get_contrast_color(background) {
                const backgroundLuminance = this.calculate_luminance(background);
                const fontColor = backgroundLuminance > 0.5 ? '#000000' : '#ffffff';
                return fontColor;
            }
        },
    })
</script>    <script type="text/html" id="template-overflow-overlay">
    <div v-if="global.overlays.overflow_overlay" id="overlay_overflow_overlay" :style="generateStyle()" class="calendar-overlay active" @click.self="global.overlays.overflow_overlay=false;">
        <div class="calendarOverlayCard">
            <div class="overlay-events-contain">
                <div v-if="me.date" class="overflow-date-contain">
                    <span class="overflow-dateOfWeek">{{ me.date.format('ddd') }}</span>
                    <span class="overflow-day">{{ me.date.$D }}</span>
                </div>
                </div>
                <template v-for="event in me.events">
                    <template v-if="event.id !== 'placeholder'">
                        <span 
                            class="cell-event-overlay" 
                            :style="generateEventStyleForMonth( event, 'event_body' )"
                            @click="clickSchedule( event )"
                        ><div :style="generateEventStyleForMonth( event, 'status_dot' )"></div><div class="event-title">{{ generateEventTitle( event ) }}</div></span>
                    </template>
                </template>
            </div>
            <div class="xButton-calendarOverlay" @click.self="global.overlays.overflow_overlay=false;"></div>
        </div>
    </div>
</script>

<script>
    //global store
    store.components["overflow_overlay"] = {
        client_id: null,
        date: null,
        events: [],
        cellPosition: {},
        loading: false,
        is_membership_cal: false,
    };
    //define the component
    app_overlays.component("overflow-overlay", {
        template: "#template-overflow-overlay",
        data() {
            return {
            	global: store,
                me: store.components.overflow_overlay
            }
        },
        methods: {
            generateStyle(){
                const cellPosition = this.me.cellPosition;
                const viewportHeight = window.innerHeight;
                const viewportWidth = window.innerWidth;
                const overlayHeight = 230;
                const overlayWidth = 230;

                let top = cellPosition.top;
                let left = cellPosition.left;

                // Adjust top position if overlay goes off-screen
                // if ( top + overlayHeight > viewportHeight) {
                // }

                // Adjust left position if overlay goes off-screen
                if ( left + overlayWidth > viewportWidth) {
                    let difference = left + overlayWidth;
                    left -= difference - viewportWidth; // 20px margin from right
                }
                return {
                    'top': `${top}px`,
                    'left': `${left}px`
                };
            },
            generateEventTitle( eventObject ){
                if ( !eventObject.isAllDay && !eventObject.isMultipleDay ) {
                    return eventObject.raw.nice_time !== undefined ? `${eventObject.raw.nice_time} ${eventObject.title}` : `${eventObject.title}`;
                } else if ( eventObject.isAllDay || eventObject.isMultipleDay ) {
                    return eventObject.title || 'Not Provided';
                }
            },
            generateEventStyleForMonth( eventObject, type ){
                let styleObject = {};                
                const dotColor = eventObject.raw.dot_color;
                const bgColor = eventObject.bgColor || '#e8edf1';
                const color = /* eventObject.color */ this.get_contrast_color( bgColor ) || 'inherit';
                if ( type === 'status_dot' ){
                    if ( !eventObject.isAllDay && !eventObject.isMultipleDay ) {
                        styleObject = {
                            'min-width': '2.2px',
                            'max-width': '2.2px',
                            'min-height': '2.2px',
                            'max-height': '2.2px',
                            'border': `2.2px solid ${dotColor || '#333'}`,
                            'border-radius': '50%',
                            'background-color': `${dotColor || '#333'}`,
                            'margin': '0 5px 0 5px',
                        }
                    } else if ( eventObject.isAllDay || eventObject.isMultipleDay ){
                        styleObject = {
                            'margin-right': '3.5px',
                        }
                    }
                } else if ( type === 'event_body' ){
                    if ( eventObject.isAllDay || eventObject.isMultipleDay ) {
                        styleObject = {
                            'background-color': bgColor,
                            'color': color,
                            'height': '22px',
                        };  
                    } 
                }
                return styleObject
            },
            clickSchedule(event){
                if ( this.me.client_id === 'primary' ){
                    store.eventBus.$emit('clickSchedule_events_cal', event)
                    store.overlays.overflow_overlay = false;
                } else if ( this.me.client_id === 'banquets' ){
                    store.eventBus.$emit('clickSchedule_banquets_cal', event)
                    store.overlays.overflow_overlay = false;
                } else if ( this.me.client_id === 'bookings' ){
                    store.eventBus.$emit('clickSchedule_reservations_cal', event)
                    store.overlays.overflow_overlay = false;
                } else if ( this.me.client_id === 'time_blocks' ){
                    store.eventBus.$emit('clickSchedule_time_blocks_cal', event)
                    store.overlays.overflow_overlay = false;
                } else if (this.me.is_membership_cal ){
                    store.eventBus.$emit('clickSchedule_membership_cal', event)
                    store.overlays.overflow_overlay = false;
                }
            },
            //methods to determine font color in contrast to bg color
            calculate_luminance(color) {
                const hex = color.substring(1); //remove #
                const rgb = parseInt(hex, 16); //convert to RGB
                const r = (rgb >> 16) & 0xff; //extract the red channel
                const g = (rgb >>  8) & 0xff; //extract the green channel
                const b = (rgb >>  0) & 0xff; //extract the blue channel
                //convert RGB to linear values
                const sR = r / 255;
                const sG = g / 255;
                const sB = b / 255;
                //calculate luminance
                const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
                return luminance;
            },
            get_contrast_color(background) {
                const backgroundLuminance = this.calculate_luminance(background);
                const fontColor = backgroundLuminance > 0.5 ? '#000000' : '#ffffff';
                return fontColor;
            }
        },
    });

    
</script>    <script type="text/html" id="template-custom-field-wb">
    <div class="custom-field-wrapper tinyMarginTop" :id="custom_field.id">
        <div class="flex-row-start" style="width: 100%;">
            <!-- question -->
            <div class="flex-column-start tinyMarginRight" style="width: 100%;">
                <div class="custom-field flex-row-start">
                    <p v-if="custom_field && custom_field.name" class="default-font-body">{{ custom_field.name }}</p>
                    <span v-if="custom_field && custom_field.required" class="flex-row-start">
                        <p style="color: rgba(255, 0, 0, 0.885); margin: 0 5.5px 0 3px;">*</p>
                        <p class="default-font-body" style="font-size: 14px; color: rgb(150, 152, 154); font-style: italic;">(required)</p>
                    </span>
                </div>
            </div>
        </div>
        <!-- response options -->
        <div class="tinyMarginTop" style="width: 100%;">
            <!-- short response -->
            <template v-if="custom_field && custom_field.type === 'text'">
                <span class="flex-row-start tinyMarginBottom">
                    <input
                        type="text" 
                        placeholder="Your answer"
                        class="border-bottom-grey-2 default-font-body"
                        style="width: 50%; line-height: 24px;"
                        v-model="input_value"
                        :disabled="is_admin"
                    >
                </span>
            </template>
            <!-- paragraph -->
            <template v-if="custom_field && custom_field.type === 'textarea'">
                <span class="flex-row-start tinyMarginBottom">
                    <input
                        type="text" 
                        placeholder="Your answer"
                        class="border-bottom-grey-2 default-font-body"
                        style="width: 100%; line-height: 24px;"
                        v-model="input_value"
                        :disabled="is_admin"
                    >
                </span>
            </template>
            <!-- multiple choice, checkbox -->
            <div v-if="custom_field.type === 'radio' || custom_field.type === 'checkbox'" class="flex-column-start">
                <template v-for="(option, index) in custom_field_options" :id="index">
                    <span class="flex-row-start" style="position: relative; width: 100%; left: -5px;">
                        <!-- multiple choice -->
                        <template v-if="custom_field.type === 'radio'">
                            <span v-if="!option.selected" @click="select_mc_option( true, option )" class="flex-row-start">
                                <i class="fa-light fa-circle options-icon"></i>
                                <p v-if="option && option.name" class="default-font-body">{{ option.name }}</p>
                            </span>
                            <span v-if="option.selected" @click="select_mc_option( false, option )" class="flex-row-start">
                                <i class="fa-solid fa-circle-dot options-icon"></i>
                                <p v-if="option && option.name" class="default-font-body">{{ option.name }}</p>
                            </span>
                        </template>
                        <!-- checkbox -->
                        <template  v-if="custom_field.type === 'checkbox'">
                            <span v-if="!option.selected" @click="option.selected = true;" class="flex-row-start">
                                <i class="fa-light fa-square options-icon"></i>
                                <p v-if="option && option.name" class="default-font-body">{{ option.name }}</p>
                            </span>
                            <span v-if="option.selected" @click="option.selected = false;" class="flex-row-start">
                                <i class="fa-solid fa-square-check options-icon"></i>
                                <p v-if="option && option.name" class="default-font-body">{{ option.name }}</p>
                            </span>
                        </template>
                    </span>
                </template>
            </div>
            <!-- dropdown -->
            <template  v-if="custom_field.type === 'select' && custom_field_options">
                <div id="response-dropdown" :style="{ 
                    borderBottomLeftRadius: dropdown_open ? '0' : '4px', 
                    borderBottomRightRadius: dropdown_open ? '0' : '4px' 
                }">
                    <!-- dropdown closed -->
                    <div id="selected-response" @click="dropdown_open = !dropdown_open;">
                        <p v-if="selected_dropdown_index < 0" class="response-option default-font-body">Choose</p>
                        <p v-if="selected_dropdown_index >= 0 && custom_field_options && custom_field_options[selected_dropdown_index]" class="response-option default-font-body">
                            {{ custom_field_options[selected_dropdown_index].name }}
                        </p>
                        <i v-if="!dropdown_open" class="fa-solid fa-sort-down" style="color: rgb(95, 95, 95)"></i>
                        <i v-if="dropdown_open" class="fa-solid fa-sort-up" style="color: rgba(95, 95, 95)"></i>
                    </div>
                    <!-- dropdown open -->
                    <div v-if="dropdown_open" id="response-options">
                        <div 
                            class="response-option border-bottom-grey-2"
                            @click="select_dropdown_option( null, -1 )"
                            :style="[ return_selected_style( -1 ) ]"
                        >
                            <p class="default-font-body" style="color: rgb(150, 152, 154);">Choose</p>
                        </div>
                        <div 
                            v-for="(option, index) in custom_field_options" 
                            class="response-option"
                            :key="option.value" 
                            @click="select_dropdown_option( option, index )"
                            :style="[ return_selected_style( index ) ]"
                        >
                            <p class="default-font-body">{{ option.name }}</p>
                        </div>
                    </div>
                </div>
            </template>
            <!-- numeric value -->
            <template v-if="custom_field && custom_field.type === 'number'">
                <span class="flex-row-start tinyMarginBottom">
                    <input
                        type="text" 
                        placeholder="Number"
                        class="border-bottom-grey-2 inherit-font-css"
                        style="width: 20%; line-height: 24px;"
                        v-model="input_value"
                        @input="check_input_is_num()"
                        :disabled="is_admin"
                    >
                    <span v-if="display_num_warning" class="flex-row-start" @mouseover="display_popup = true;" @mouseleave="display_popup = false;">
                        <i class="fa-solid fa-triangle-exclamation" style="color: rgba(255, 0, 0, 0.885); font-size: 1em; cursor: pointer;"></i>
                    </span>
                    <div v-if="display_popup" class="display-popup" style="font-size: 12px;">This value must be a number.</div>
                </span>
            </template>
            <!-- file upload -->
            <template v-if="custom_field && custom_field.type === 'file_upload'">
                <div class="file-upload-wrapper flex-column-center" :style="{ 'color': 'var(--custom-field-grey-3)' }">
                    <label for="file-upload-input" style="display: flex; flex-direction: column; align-items: center; cursor: pointer;">
                        <i class="fa-light fa-folder-arrow-up" style="font-size: 1.5em; color: inherit;"></i>
                        <span class="tinyMarginTop" :style="{ 'color': 'var(--custom-field-primary)', 'font-size': '15px' }">Upload File</span>
                    </label>
                    <input
                        :id="file-upload-input + custom_field.id"
                        type="file"
                        style="opacity: 0; position: absolute; width: 30%; height: 90px; overflow: hidden;"
                        @change="handle_file_upload($event)"
                        :disabled="is_admin"
                    >
                </div>
                <span v-if="input_value" class="flex-row-start tinyMarginTop" :style="{ 'color': 'var(--custom-field-grey-3)' }">
                    <i class="fa-regular fa-check" style="font-size: 1em; color: inherit; margin-right: 8px;"></i>
                    <p class="default-font-body">{{ input_value ?  input_value.name : '' }}</p>
                </span>
            </template>
        </div>
    </div>
</script>

<style scoped>
    :root {
        --custom-field-grey-1: rgba(180, 180, 180, 0.8);
        --custom-field-grey-2: rgba(195, 195, 195, 0.7);
        --custom-field-grey-3: rgb(154, 160, 166);
        --custom-field-primary: #202124;
    }
    .custom-field-wrapper{
        width: 100%;
        border: 1px solid rgba(195, 195, 195, 0.7);
        border-radius: 8px;
        padding: 1.45em;
        background-color: #fff;
        box-sizing: border-box;
    }
    .custom-field-wrapper .options-icon{
        color: var(--custom-field-grey-3);
        margin-right: 8px;
        padding: 7.5px;
        cursor: pointer;
        border-radius: 50%;
        font-size: 1.1em;
    }
    .custom-field-wrapper .options-icon:hover{
        background-color: rgba(150, 150, 150, 0.1);
    }
    .custom-field-wrapper .default-font-body{
        font-family: Roboto, Arial, Helvetica, sans-serif;
        font-size: 15px; 
        font-weight: 400;
        text-align: left;
    }
    .custom-field-wrapper .file-upload-wrapper{
        height: 90px;
        width: 50%;
        border: 1px dashed var(--custom-field-grey-1);
    }
    .custom-field-wrapper  .inherit-font-css{
        font-family: inherit;
        font-size: inherit;
        font-weight: inherit;
    }
    .custom-field-wrapper .flex-row-center{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }
    .custom-field-wrapper .flex-column-center{
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
    .custom-field-wrapper .flex-row-start{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
    }
    .custom-field-wrapper .flex-column-start{
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
    }
    .custom-field-wrapper .custom-field{
        color: rgb(32, 33, 36);
        box-sizing: border-box;
        font-weight: 400;
        font-size: 14px;
        width: 100%;
        line-height: 2.5;
        letter-spacing: 0;
    }
    .custom-field-wrapper .custom-field > .custom-field-input{
        font-family: inherit;
        font-size: inherit;
        font-weight: inherit;
        width: inherit;
        line-height: inherit;
        background-color: rgb(248, 249, 250);
        padding: 5px 0 5px 15px;
    }
    .custom-field-wrapper .border-bottom-grey-2, .custom-field-wrapper .input-is-focused{
        border-bottom: 1.25px solid var(--custom-field-grey-2);
    }
    .custom-field-wrapper input {
        transition: border-color 0.2s;
    }
    #response-dropdown{
        position: relative;
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
        font-size: 14px; 
        color: var(--custom-field-primary);
        background-color: #fff;
        width: 33%;
        padding: 12px;
        border: 1px solid var(--custom-field-grey-1);
        border-top-left-radius: 4px;
        border-top-right-radius: 4px;
    }
    #response-dropdown > #selected-response{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        cursor: pointer;
    }
    #response-options{
        position: absolute;
        top: 100%;
        left: -1px;
        z-index: 10;
        background-color: #fff;
        border: 1px solid var(--custom-field-grey-1);
        border-bottom-left-radius: 4px;
        border-bottom-right-radius: 4px;
        width: 100%;
    }
    #response-options > .response-option{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
        padding: 12px;
        font-family: Roboto;
        cursor: pointer;
    }
    #response-options > .response-option:hover{
        background-color: rgba(150, 150, 150, 0.2);
    }
    .display-popup{
        background-color: rgb(245, 245, 245);
        padding: 5px;
        border-radius: 6px;
        position: relative;
        left: -100px;
        bottom: 30px;
        z-index: 10;
        width: fit-content;
    }
</style>

<script>
    app_content.component("custom-field-component-wb", {
        template: "#template-custom-field-wb",
        data() {
            return {
                selected_dropdown_index: -1, //default
                dropdown_open: false,
                custom_field_name: '',
                custom_field_required: false,
                display_num_warning: false,
                display_popup: false,
                input_value: '',
            }
        },
        props: {
            form: Object,
            is_admin: Boolean,
            custom_field: Object,
            last_update: Number,
        },
        methods: {
            return_selected_style( index ){
                if ( index === this.selected_dropdown_index ){
                    return {
                        'background-color': 'rgba(26, 115, 232, .09)',
                    }
                }
            },
            clear_dropdown_index(){
                this.selected_dropdown_index = -1;
            },
            select_dropdown_option( option, index ){
                this.selected_dropdown_index = index;
                this.dropdown_open = false;
                if ( option ){
                    option.selected = true;
                    this.unselect_other_options( option, false );
                } else if ( !option ){
                    this.unselect_other_options( option, true );
                }
            },
            select_mc_option( select, option ){
                if ( select ){
                    option.selected = true;
                    this.unselect_other_options( option, false );
                } else if ( !select ){
                    option.selected = false;
                }
            },
            unselect_other_options( option, clear_all = false ){
                if ( clear_all ){
                    this.custom_field_options.forEach( custom_field_option => {
                        custom_field_option.selected = false;
                    })
                } else if ( !clear_all ){
                    this.custom_field_options.forEach( custom_field_option => {
                        if ( custom_field_option.id !== option.id ){
                            custom_field_option.selected = false;
                        }
                    })
                }
            },
            check_input_is_num(){
                let number = Number(this.input_value);
                if ( isNaN(number) || !this.input_value ){
                    this.display_num_warning = true;
                } else {
                    this.input_value = number;
                    this.display_num_warning = false;
                }
            },
            handle_file_upload( event ){
                let file = event.target.files[0];
                if ( file ){
                    this.input_value = file;
                } else {
                    displayMessage('There was an issue uploading your file. Please try again or contact support.', true, 6000);
                }
            },
        },
        computed: {
            custom_field_options(){
                if ( this.custom_field && this.custom_field.custom_field_options ){
                    return this.custom_field.custom_field_options;
                }
                return [];
            },
        },
        watch: {
            input_value( newValue ){
                this.$emit('field-updated', {
                    id: this.custom_field.id,
                    value: newValue
                });
            }
        }
    })
</script>
    <script type="text/html" id="template-default-field-wb">
    <div class="default-field-wrapper tinyMarginTop">
        <span class="flex-row-start">
            <p style="color: rgba(255, 0, 0, 0.885); margin: 0 5.5px 0 3px;">*</p>
            <p class="default-font-body" style="font-size: 14px; color: rgb(150, 152, 154); font-style: italic;">(required)</p>
        </span>
        <!-- default fields -->
        <div class="flex-row-start" style="width: 100%;">
            <div class="flex-column-start" style="width: 100%;">
                <template v-if="default_configuration === 'list'" v-for="(field, index) in default_fields" :id="index">
                    <div class="flex-row-start smallMarginTop" style="width: 100%;">
                        <input
                            type="text"
                            :placeholder="field.label"
                            class="default-field-input border-bottom-grey-2 default-font-body"
                            style="width: 100%;"
                            v-model="field.input_value"
                            :disabled="is_admin"
                        >
                    </div>
                </template>
                <template v-if="default_configuration === 'grid'" v-for="(row, i) in default_fields" :id="i">
                    <div class="flex-row-start smallMarginTop" style="width: 100%;">
                        <template v-for="(field, j) in row" :id="j">
                            <input
                                type="text"
                                :placeholder="field.label"
                                class="default-field-input border-bottom-grey-2  default-font-body marginRight"
                                style="width: 100%;"
                                v-model="field.input_value"
                                :disabled="is_admin"
                            >
                        </template>
                    </div>
                </template>
            </div>
        </div>
    </div>
</script>

<style scoped>
    :root {
        --default-field-grey-1: rgba(180, 180, 180, 0.8);
        --default-field-grey-2: rgba(195, 195, 195, 0.7);
        --default-field-grey-3: rgb(154, 160, 166);
        --default-field-primary: #202124;
    }
    .default-field-wrapper{
        width: 100%;
        border: 1px solid rgba(195, 195, 195, 0.7);
        border-radius: 8px;
        padding: 1.45em;
        background-color: #fff;
        box-sizing: border-box;
    }
    .default-field-wrapper .default-font-body{
        font-family: Roboto, Arial, Helvetica, sans-serif;
        font-size: 15px; 
        font-weight: 400;
    }
    .default-field-wrapper .configuration-icon{
        font-size: 1em;
        cursor: pointer;
        padding: 5px;
        border-radius: 50%;
        color: rgba(95, 95, 95);
        background-color: #fff;
        transition: color 0.2s, background-color 0.2s;
    }
    .default-field-wrapper .configuration-icon:hover{
        color: var(--default-field-primary);
        background-color: rgba(180, 180, 180, 0.15);
    }
    .default-field-wrapper .file-upload-wrapper{
        height: 90px;
        width: 50%;
        border: 1px dashed var(--default-field-grey-1);
    }
    .default-field-wrapper  .inherit-font-css{
        font-family: inherit;
        font-size: inherit;
        font-weight: inherit;
    }
    .default-field-wrapper .flex-row-center{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }
    .default-field-wrapper .flex-column-center{
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
    .default-field-wrapper .flex-row-start{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-start;
    }
    .default-field-wrapper .flex-row-end{
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-end;
    }
    .default-field-wrapper .flex-column-start{
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        justify-content: center;
    }
    .default-field-wrapper .default-field{
        color: rgb(32, 33, 36);
        box-sizing: border-box;
        font-weight: 400;
        font-size: 14px;
        width: 100%;
        line-height: 2.5;
        letter-spacing: 0;
    }
    .default-field-wrapper .default-field > .default-field-input{
        font-family: inherit;
        font-size: inherit;
        font-weight: inherit;
        width: inherit;
        line-height: inherit;
        background-color: rgb(248, 249, 250);
        padding: 5px 0 5px 15px;
    }
    .default-field-wrapper .border-bottom-grey-2, .default-field-wrapper .input-is-focused{
        border-bottom: 1.25px solid var(--default-field-grey-2);
    }
    .default-field-wrapper input {
        transition: border-color 0.2s;
    }
</style>

<script>
    app_content.component("default-field-component-wb", {
        template: "#template-default-field-wb",
        data() {
            return {

            }
        },
        props: {
            form: Object, //json
            is_admin: Boolean,
            default_fields: Array,
            rerender_key: String,
        },
        mounted() {

        },
        methods: {

        },
        computed: {
            default_configuration(){
                if ( this.form && this.form.default_configuration ){
                    return this.form.default_configuration;
                }
                return 'list';
            },
        }
    })
</script>

    <!-- native tab bar -->
    <script type="text/html" id="template-native-tab-bar">

    <!-- first, make sure we're in the react native member app -->
    <template v-if="is_react_native_member_app">
            
        <div 
            v-if="show_tab_bar"
            class="native-tab-bar-outer flexNoWrap"
        >
            <!-- tab bar (only for the member portal) -->
            <template v-if="visible_tabs">
                <div 
                    v-for="tab in visible_tabs"
                    :key="tab.key"
                    class="native-tab-bar-item"
                    :class="{ active : tab.key == primary_view }"
                    @touchstart.prevent="tapped_tab_bar_item( tab )"
                    @click="tapped_tab_bar_item( tab )"
                >
                    <div class="centeredText centeredBlock">
                        <p><i class="native-tab-bar-icon" :class="tab.icon_class"></i></p>
                        <p class="native-tab-bar-label">{{ tab.label }}</p>
                    </div>
                </div>
                <div 
                    class="native-tab-bar-item"
                    @touchstart.prevent="tapped_more()"
                    @click="tapped_more()"
                >
                    <div class="centeredText centeredBlock">
                        <p><i class="fa-regular fa-grid native-tab-bar-icon"></i></p>
                        <p class="native-tab-bar-label">More</p>
                    </div>
                </div>
            </template>
        </div>

        <!-- back button (global) -->
        <div v-else-if="! loading && show_back_button">

            <!-- overlay -->
            <div 
                class="native-tab-bar-back-button-overlay pointer"
                @touchstart.self.prevent="back_button_expanded = false"
                @click.self="back_button_expanded = false"
                :class="{ 'active': back_button_expanded }"
            ></div>

            <!-- home button -->
            <div 
                class="native-tab-bar-floating-home-button boxShadowBottom moreBlur pointer easeFast"
                @click="tapped_home()"
                :class="{ 'active': back_button_expanded }"
            >
                <div class="centeredText centeredBlock">
                    <p><i class="fa-regular fa-house native-tab-bar-icon" style="font-size:20px;"></i><span v-if="back_button_expanded" style="padding-left:6px;font-size:18px;">Home</span></p>
                </div>
            </div>

            <!-- back button -->
            <div 
                class="native-tab-bar-floating-back-button boxShadowBottom moreBlur pointer easeFast"
                @click="tapped_back()"
                :class="{ 'expanded': back_button_expanded }"
            >
                <div class="centeredText centeredBlock">
                    <p><i class="fa-regular fa-chevron-left native-tab-bar-icon" style="font-size:20px;"></i><span v-if="back_button_expanded" style="padding-left:6px;font-size:18px;">Back</span></p>
                </div>
            </div>

            <!--
            <div 
                class="native-tab-bar-item"
                @click="tapped_home()"
                style="max-width:60px;"
            >
                <div class="centeredText centeredBlock">
                    <p><i class="fa-regular fa-house native-tab-bar-icon"></i></p>
                    <p class="native-tab-bar-label">Home</p>
                </div>
            </div>
            -->
        </div>

        <!-- full menu sheet -->
        <div 
            v-if="tabs"
            class="native-tab-bar-menu-sheet"
            :class="{'active': show_full_menu}"
        >
            <!-- overlay -->
            <div 
                class="native-tab-bar-menu-sheet-overlay pointer"
                @touchstart.self.prevent="show_full_menu = false"
                @click.self="show_full_menu = false"
            ></div>
            <!-- actual menu sheet -->
            <div class="native-tab-bar-menu-sheet-inner scrollable">
                <div 
                    class="flexWrap"
                    style="padding-top: 10px"
                >
                    <!-- loop through tabs-->
                    <div 
                        v-for="tab in tabs"
                        class="quick-action-wrap noMaxWidth relative"
                        @click="selected_full_menu_option( tab )"
                    >
                        <div 
                            class="quick-action-icon-wrap overflowHidden"
                        >
                            <div>
                                <i v-if="tab.icon_class" :class="tab.icon_class"></i>
                            </div>
                        </div>
                        <p class="quick-action-title">{{ tab.label }}</p>
                    </div>
                </div>
            </div>
        </div>

    </template>
    
</script>


<style>

    .native-tab-bar-outer{
        position: fixed;
        bottom: 0px;   
        left: 0px;
        right: 0px;
        background-color: rgba(249, 251, 251, 1);
        border-top: 1px solid #e4ebf1;
        z-index: 1000;
        transition: 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
    }
    .native-tab-bar-item{
        padding: 11px;
        display: flex;
        flex: 1 1 0; /* flex-grow: 1; flex-shrink: 1; flex-basis: 0; */
        color: #697684;
        cursor: pointer;
    }
    .native-tab-bar-item.active{
        color: #4a56f8;
    }
    .native-tab-bar-label{
        font-size: 12px;
        padding-top: 4px;
        white-space: nowrap;
    }
    .native-tab-bar-icon{
        font-size: 22px;
    }

    /* ------  menu sheet (full menu)  ------- */

    .native-tab-bar-menu-sheet-overlay{
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background-color: rgba(8,8,19,0.64);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.15s ease;
        z-index: 1000;
    }

    .native-tab-bar-menu-sheet.active .native-tab-bar-menu-sheet-overlay{
        opacity: 1;
        visibility: visible;
    }

    .native-tab-bar-menu-sheet.active .native-tab-bar-menu-sheet-inner{
        bottom: 0px;
    }

    .native-tab-bar-menu-sheet-inner .quick-action-wrap{
        padding-left: 10px;
        padding-right:10px;
    }

    .native-tab-bar-menu-sheet-inner{
        position: fixed;
        bottom: -100%;
        max-height: 90%;
        left: 0px;
        right: 0px;
        z-index: 1001;
        background-color: rgba(249, 251, 251, 1);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        transition: bottom 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
        border-top-left-radius: 10px;
        border-top-right-radius: 10px;
        padding-bottom: 10px;
        padding-top: 10px;
    }

    /*------  back button  -------*/

    .native-tab-bar-back-button-overlay{
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        /*
        background-color: rgba(111,117,122,0.5);
        */
        background-color: rgba(249, 251, 251, 0.8);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.15s ease;
        z-index: 999;
    }

    .native-tab-bar-back-button-overlay.active{
        opacity: 1;
        visibility: visible;
    }

    .native-tab-bar-floating-back-button{
        position: fixed;
        bottom: 15px;
        left: 22px;
        right: auto;
        background-color: rgba(249, 251, 251, 1);
        /* border-top: 1px solid #e4ebf1; */
        z-index: 1000;
        transition: 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
        border-radius: 100%;
        width: 50px;
        height: 50px;
        background-color: #fff;
        line-height: 50px;
        font-size: 16px;
        white-space: nowrap;
        min-width: 50px;
    }

    .native-tab-bar-floating-back-button.expanded{
        border-radius: 25px;
        padding-left: 16px;
        padding-right: 16px;
        width: auto;
    }

    /*------  home button  -------*/

    .native-tab-bar-floating-home-button.active{
        border-radius: 25px;
        padding-left: 16px;
        padding-right: 16px;
        width: auto;
        visibility: visible;
        opacity: 1;
        animation: expand 0.15s cubic-bezier(0.25, 0.1, 0.25, 1) forwards;
        background-color: #4a56f8;
        color: #fff;
    }

    .native-tab-bar-floating-home-button{
        position: fixed;
        bottom: 75px;
        left: 22px;
        right: auto;
        visibility: hidden;
        opacity: 0;
        background-color: rgba(249, 251, 251, 1);
        /* border-top: 1px solid #e4ebf1; */
        z-index: 1000;
        transition: 0.15s cubic-bezier(0.25, 0.1, 0.25, 1);
        border-radius: 20px;
        width: auto;
        height: 50px;
        background-color: #fff;
        line-height: 50px;
        font-size: 16px;
        white-space: nowrap;

        /* Initial state for animation */
        transform: scale(0);
        animation: none;
    }

    /* Keyframes for the expansion effect */
    @keyframes expand {
        from {
            transform: scale(0);
            opacity: 0;
        }
        to {
            transform: scale(1);
            opacity: 1;
        }
    }

</style>

<script>

    app_content.component("native-tab-bar-component", {
        template: "#template-native-tab-bar",
        data() {
            return {
                loading: true,
                last_scroll_top: 0, 
                slide_down: false,
                ticking: false,
                show_full_menu: false,
                back_button_expanded: false
            }
        },
        props: {
            primary_view: String,
            tabs: Array, 
        },
        mounted(){
            if( this.is_react_native_member_app ){
                this.last_scroll_top = this.return_scroll_top();
                window.addEventListener('scroll', this.handle_scroll);
                setTimeout(() => {
                    this.loading = false;
                }, 100);
            }
        },
        unmounted(){
            if( this.is_react_native_member_app ){
                window.removeEventListener('scroll', this.handle_scroll);
            }
        },
        methods: {
            tapped_home(){
                window.location.href = "/account/home";
            },
            tapped_more(){
                this.show_full_menu = true;
            },
            selected_full_menu_option( option ){
                this.show_full_menu = false;
                this.tapped_tab_bar_item( option );
            },
            return_scroll_top(){
                let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
                return scrollTop <= 0 ? 0 : scrollTop; // For Mobile or negative scrolling
            },
            handle_scroll(){
                if ( ! this.ticking ) {
                    window.requestAnimationFrame(() => {
                        let scrollTop = this.return_scroll_top();
                        let windowHeight = window.innerHeight;
                        let documentHeight = document.documentElement.scrollHeight;

                        // Prevent action if bouncing past the bottom of the page
                        if (scrollTop + windowHeight >= documentHeight) {
                            // We're at or past the bottom, so we ignore this scroll event
                            this.ticking = false;
                            return;
                        }
                        
                        if (scrollTop > this.last_scroll_top) {
                            //hide tab bar
                            this.slide_down = true;
                        } else if (scrollTop < this.last_scroll_top && scrollTop >= 0) {
                            //show tab bar
                            this.slide_down = false;
                        }
                        this.last_scroll_top = scrollTop;
                        this.ticking = false;
                    });
                    this.ticking = true;
                }
            },
            tapped_tab_bar_item( tab ){
                updateURL( tab.key );
                displayViewForUrlPath();
            },
            tapped_back(){
                if( this.back_button_expanded ){
                    this.back_button_expanded = false;
                    window.history.back();
                } else {
                    this.back_button_expanded = true;
                }
            },
        },
        computed: {
            //we only show it when we're on one of the relevant primary views (contained in the tab bar)
            //.. otherwise we should display the back button bar
            tab_bar_keys(){
                var keys = [];
                if( this.tabs ){
                    this.tabs.forEach(tab => {
                        keys.push( tab.key );
                    });
                }
                return keys;
            },
            show_tab_bar(){
                for (let t = 0; t < this.tab_bar_keys.length; t++) {
                    if( this.tab_bar_keys[t] == this.primary_view ){
                        return true
                    }   
                }
                return false;
            },
            visible_tabs(){
                if( this.tabs ){
                    return this.tabs.slice(0,4)
                }
                return [];
            },
            show_back_button(){
                if( ! this.show_tab_bar && window.history.length >= 1 ){
                    return true;
                }
                return false;
            },
            is_react_native_member_app(){
                return store.is_react_native_member_app;
            }
        },
    })

</script>    
    <script>
        //after we've included all the relevant views, mount the vue apps
        app_content.mount('#v-content');
        app_overlays.mount('#v-overlays');

    </script>


</html>                               

Whois info of domain

Domain Name: DLYC.COM
Registry Domain ID: 236211_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.godaddy.com
Registrar URL: http://www.godaddy.com
Updated Date: 2024-08-11T11:11:24Z
Creation Date: 1997-05-01T04:00:00Z
Registry Expiry Date: 2026-05-02T04:00:00Z
Registrar: GoDaddy.com, LLC
Registrar IANA ID: 146
Registrar Abuse Contact Email: [email protected]
Registrar Abuse Contact Phone: 480-624-2505
Domain Status: clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited
Domain Status: clientRenewProhibited https://icann.org/epp#clientRenewProhibited
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Domain Status: clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited
Name Server: NS09.DOMAINCONTROL.COM
Name Server: NS10.DOMAINCONTROL.COM
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
>>> Last update of whois database: 2025-05-10T17:00:28Z <<<
For more information on Whois status codes, please visit https://icann.org/epp
NOTICE: The expiration date displayed in this record is the date the
TERMS OF USE: You are not authorized to access or query our Whois
by the following terms of use: You agree that you may use this Data only
to: (1) allow, enable, or otherwise support the transmission of mass