Pronails Profit

13 februari 2023 in Salon Business Tips

5 min reading time

What determines your profit?

1. YOUR PRICE PER TREATMENT

You always provide each client with a professional, top quality result. Your work and expertise therefore deserves a decent price. This may sound pretty simple, but many beauty entrepreneurs often set their prices too low, which means they don't make the profits they need to be successful. Your prices should also rise in line with the cost of living. You must have faith that your customers will appreciate your expertise.

For a BFLEX Natural Nail Treatment, you can definitely charge €65.
For BSTRONG Natural Nail Extensions, €90 for a new set and €65 for a touch-up.

Error executing template "Designs/ProNails_generated/Paragraph/Carousel.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at Bluedesk.DynamicWeb.ItemTypes.CTAButton.GetLink(PageView pv, String navigationtag)
   at CompiledRazorTemplates.Dynamic.RazorEngine_d483915588c94da2be519ff6aecbd8e5.<>c__DisplayClass9_0.<RenderContentArea>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Bluedesk\pronails.cloud.dynamicweb-cms.com\files\Templates\Designs\ProNails_generated\Paragraph\Carousel.cshtml:line 545
   at CompiledRazorTemplates.Dynamic.RazorEngine_d483915588c94da2be519ff6aecbd8e5.Execute() in D:\dynamicweb.net\Solutions\Bluedesk\pronails.cloud.dynamicweb-cms.com\files\Templates\Designs\ProNails_generated\Paragraph\Carousel.cshtml:line 447
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 3 @using Dynamicweb; 4 @using Bluedesk.DynamicWeb.ItemTypes; 5 6 <!-- FIX NEEDED: behaviour when all the items are full height images (for instance logo slider)?? --> 7 @{ 8 Carousel _data = Dynamicweb.Services.Items.GetItem("Carousel", Pageview.CurrentParagraph.ItemId).ToCodeFirstItem<Carousel>() ?? new Carousel(); 9 10 var paragraphID = Pageview.CurrentParagraph.ID; 11 int amountColumns = _data.CarouselItems.Count; // Amount of the columns in backend, filled by user 12 var classFullWidth = !_data.Fullwidth ? "container" : "w-full"; // If slider or multicolumn has to be in container or full width of the page 13 } 14 15 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 16 @using Dynamicweb; 17 @using Dynamicweb.Content.Items; 18 @using Bluedesk.DynamicWeb.ItemTypes; 19 20 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 21 @using Dynamicweb; 22 @using Dynamicweb.Content.Items; 23 @using Bluedesk.DynamicWeb.ItemTypes; 24 25 @functions { 26 27 Dictionary<string, string> GetFontConfiguration(string TextColor, FontConfigurationItemTab FontConfiguration) 28 { 29 var colorService = new ColorSwatchService(); 30 TextColor = !string.IsNullOrWhiteSpace(TextColor) ? TextColor : "" ; 31 TextColor = !TextColor.Contains("#") ? colorService.GetHexColor(Pageview.AreaID, TextColor) : TextColor; 32 Dictionary<string, string> FontConfig = new Dictionary<string, string>() { 33 { "textColor" , TextColor }, 34 { "fontSize" , FontConfiguration.FontSize }, 35 { "lineHeight", FontConfiguration.LineHeight}, 36 { "fontFamily" , FontConfiguration.FontConfiguration.FontFamily }, 37 { "fontWeight" , FontConfiguration.FontWeight }, 38 { "fontStyle" , FontConfiguration.FontStyle } 39 }; 40 return FontConfig; 41 } 42 43 public string GenerateButtonConfigVariables(ButtonConfiguration BC, MasterConfig mc, int areaId) 44 { 45 string ButtonLabelAlignment = BC.ButtonLabelAlignment; 46 switch (ButtonLabelAlignment) 47 { 48 case "align-left": 49 ButtonLabelAlignment = "flex-start"; 50 break; 51 case "align-center": 52 ButtonLabelAlignment = "center"; 53 break; 54 case "align-right": 55 ButtonLabelAlignment = "flex-end"; 56 break; 57 case "align-full": 58 ButtonLabelAlignment = "space-between"; 59 break; 60 default: 61 ButtonLabelAlignment = "flex-start"; 62 break; 63 } 64 65 var btnStyleBlock = new System.Text.StringBuilder(); 66 67 // General Config 68 btnStyleBlock.Append(GenerateCssVar("btn-min-height", $"{mc.GeneralConfiguration.ButtonHeight}px")); 69 btnStyleBlock.Append(GenerateCssVar("btn-border-radius", $"{mc.GeneralConfiguration.RoundedCornerValue}px")); 70 71 // Button Config 72 btnStyleBlock.Append(GenerateCssVar("btn-border-width", $"{BC.BorderSize.ToString()}px")); 73 btnStyleBlock.Append(GenerateCssVar("btn-label-alignment", ButtonLabelAlignment)); 74 75 // Button Config Tab 76 btnStyleBlock.Append(GenerateCssVar("btn-bg-color", BC.ButtonColorConfiguration.BackgroundColor.GetColorCode(areaId))); 77 btnStyleBlock.Append(GenerateCssVar("btn-font-color", BC.ButtonColorConfiguration.FontColor.GetColorCode(areaId))); 78 btnStyleBlock.Append(GenerateCssVar("btn-border-color", BC.ButtonColorConfiguration.BorderColor.GetColorCode(areaId))); 79 80 // Button Config Hover tab 81 btnStyleBlock.Append(GenerateCssVar("btn-bg-color-hover", BC.ButtonHoverColorConfiguration.BackgroundColor.GetColorCode(areaId))); 82 btnStyleBlock.Append(GenerateCssVar("btn-font-color-hover", BC.ButtonHoverColorConfiguration.FontColor.GetColorCode(areaId))); 83 btnStyleBlock.Append(GenerateCssVar("btn-border-color-hover", BC.ButtonHoverColorConfiguration.BorderColor.GetColorCode(areaId))); 84 85 // Button Config Font Config 86 btnStyleBlock.Append(GenerateCssVar("btn-font-size", BC.FontConfiguration.FontSize)); 87 btnStyleBlock.Append(GenerateCssVar("btn-font-config-color", BC.FontConfiguration.Color.GetColorCode(areaId))); 88 btnStyleBlock.Append(GenerateCssVar("btn-font-line-height", BC.FontConfiguration.LineHeight)); 89 btnStyleBlock.Append(GenerateCssVar("btn-font-family", BC.FontConfiguration.FontConfiguration.FontFamily)); 90 btnStyleBlock.Append(GenerateCssVar("btn-font-weight", BC.FontConfiguration.FontWeight)); 91 btnStyleBlock.Append(GenerateCssVar("btn-font-transform", BC.FontConfiguration.FontStyle)); 92 93 return btnStyleBlock.ToString(); 94 } 95 96 public string GenerateCssVar(string name, string value) 97 { 98 if (!string.IsNullOrWhiteSpace(value)) { 99 return $"--{name}: {value};"; 100 } else { 101 return ""; 102 } 103 } 104 } 105 106 107 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 108 @using Dynamicweb; 109 @using Dynamicweb.Content.Items; 110 @using Bluedesk.DynamicWeb.ItemTypes; 111 @using Bluedesk.DynamicWeb.ItemTypes.Configuration; 112 113 114 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 115 @using Dynamicweb; 116 @using Dynamicweb.Content.Items; 117 @using Bluedesk.DynamicWeb.ItemTypes; 118 @using Bluedesk.DynamicWeb.ItemTypes.Extensions; 119 @using Bluedesk.DynamicWeb.ItemTypes.Configuration; 120 @using Bluedesk.DynamicWeb.ItemTypes.Settings.Configuration; 121 @using Dynamicweb; 122 @using Dynamicweb.Frontend 123 @using Bluedesk.DynamicWeb.ItemTypes.BaseSolution; 124 125 @helper RenderButton(CTAButton button, PageView Pageview) 126 { 127 128 if (!string.IsNullOrWhiteSpace(button.GetLink(Pageview))) 129 { 130 string Template = button.GetButtonTemplate().Replace("{{ ButtonLink }}", button.GetLink(Pageview)); 131 @Template; 132 } 133 } 134 135 136 @{ 137 138 var colorService = new ColorSwatchService(); 139 140 string fullWidthContainerClass = _data.Fullwidth ? "" : "container"; 141 142 string backgroundClass = !string.IsNullOrWhiteSpace(_data.BackgroundConfiguration.BackgroundClass) ? string.Format("bg-{0}", _data.BackgroundConfiguration.BackgroundClass) : ""; 143 string backgroundStyle = !string.IsNullOrWhiteSpace(_data.BackgroundConfiguration.BackgroundColor) ? $"background-color: {_data.BackgroundConfiguration.BackgroundColor}; " : ""; 144 backgroundStyle += !string.IsNullOrWhiteSpace(_data.BackgroundConfiguration.BackgroundImage) ? $"background-image: url({_data.BackgroundConfiguration.BackgroundImage}); " : ""; 145 146 // string backgroundClass = "null"; 147 // string backgroundStyle = ""; 148 } 149 150 151 @functions { 152 //string getbackgroundclass(string backgroundClass) 153 //{ 154 // return !string.IsNullOrWhiteSpace(backgroundClass) ? string.Format("bg-{0}", backgroundClass) : ""; 155 //} 156 } 157 158 @helper CTAParagraphImage( 159 ParagraphImageResizable Image, 160 bool hasContent, 161 bool ImageAsBackground, 162 string ImagePosition, 163 bool ParallaxImage, 164 bool Fullwidth, 165 string imagesHeight, 166 double ColumnWidthSize, 167 int AnimationDuration = 300, 168 bool AnimateHalfBlock = false 169 ) 170 { 171 if (!string.IsNullOrWhiteSpace(Image.Image)) 172 { 173 174 string image = !string.IsNullOrWhiteSpace(Image.Image) ? Image.Image : null; 175 imagesHeight = hasContent ? imagesHeight : "100%"; 176 imagesHeight = !string.IsNullOrWhiteSpace(imagesHeight) ? "height: " + imagesHeight + ";" : ""; 177 178 string imageParrallax = ParallaxImage ? "rellax" : ""; 179 string imageAsBackground = ImageAsBackground ? "cta-paragraph__image--is-background" : ""; 180 double imageWidth = 2000; 181 182 imageWidth = Fullwidth ? imageWidth : 1200; 183 imageWidth = !ImageAsBackground ? imageWidth * ColumnWidthSize : imageWidth; 184 185 string strImageWidth = imageWidth + "px"; 186 string strImageWidthSize = imageWidth + "w"; 187 188 string ImageUrl; 189 if (image.EndsWith(".gif")) 190 { 191 ImageUrl = image; 192 } 193 else 194 { 195 ImageUrl = "/Admin/Public/GetImage.ashx?Image=" + image + "&Crop=7&Format=webp&Quality=90&Compression=80"; 196 ImageUrl = ImageUrl.Replace("?x", "&x"); 197 } 198 199 string animationDirection = AnimateHalfBlock ? ImagePosition.Equals("right") ? "fade-left" : "fade-right" : ""; 200 201 if (!string.IsNullOrWhiteSpace(Image.Image)) 202 { 203 204 <figure class="cta-paragraph__image-container @imageAsBackground @Image.PositionY @Image.PositionX" style="@imagesHeight" data-aos="@animationDirection" data-aos-duration="@AnimationDuration"> 205 206 <picture class="cta-paragraph__image @Image.BackgroundSize @imageParrallax"> 207 @if (ImageUrl.EndsWith(".gif")) 208 { 209 <source media="(max-width: 400px)" srcset="@ImageUrl&Width=400"> 210 <source media="(max-width: 994px)" srcset="@ImageUrl&Width=994"> 211 <img src="@ImageUrl" loading="lazy" alt="@Image.ImageAlt" class="cta-paragraph__image @Image.BackgroundSize @imageParrallax" width="1980" height="500"> 212 } 213 else 214 { 215 <source media="(max-width: 400px)" srcset="@ImageUrl&Width=400"> 216 <source media="(max-width: 994px)" srcset="@ImageUrl&Width=994"> 217 <img src="@ImageUrl&Width=@imageWidth" loading="lazy" alt="@Image.ImageAlt" class="cta-paragraph__image @Image.BackgroundSize @imageParrallax" width="1980" height="500"> 218 } 219 </picture> 220 221 </figure> 222 } 223 } 224 } 225 226 @helper CTAParagraphContent( 227 int paragraphID, 228 ParagraphHeader Header, 229 ParagraphHeader SubHeader, 230 ParagraphContent Content, 231 CTAButton Button, 232 CTAButton ExtraButton, 233 ParagraphImage Image, 234 bool strCenterVertical, 235 string ImagePosition = "", 236 int AnimationDuration = 300, 237 bool AnimateHalfBlock = false 238 ) 239 { 240 241 bool hasImage = !string.IsNullOrWhiteSpace(Image.Image) ? true : false; 242 string noImageClass = hasImage ? "" : "no-image"; 243 244 string centerTextClass = strCenterVertical ? "text-center" : ""; 245 string centerContent = !string.IsNullOrWhiteSpace(Image.Image) ? "" : "cta-paragraph__content--center"; 246 247 string paragraphInstanceClass = "cta-paragraph__content--" + paragraphID; 248 249 string animationDirection = (AnimateHalfBlock && hasImage) ? ImagePosition.Equals("right") ? "fade-right" : "fade-left" : ""; 250 251 if (!string.IsNullOrWhiteSpace(Button.ButtonText) || !string.IsNullOrWhiteSpace(Content.Text) || !string.IsNullOrWhiteSpace(Header.HeaderFormatted("cta-paragraph__header"))) 252 { 253 254 <section class="cta-paragraph__content @paragraphInstanceClass @centerContent @noImageClass" data-aos="@animationDirection" data-aos-duration="@AnimationDuration"> 255 256 <article class="cta-paragraph__content-container @noImageClass"> 257 258 @if (!string.IsNullOrWhiteSpace(Header.HeaderFormatted("cta-paragraph__header"))) 259 { 260 <header class="cta-paragraph__header @centerTextClass"> 261 @if (SubHeader != null) 262 { 263 @SubHeader.HeaderFormatted("cta-paragraph__subheader") 264 } 265 @Header.HeaderFormatted("cta-paragraph__header") 266 </header> 267 } 268 269 @if (!string.IsNullOrWhiteSpace(Content.Text)) 270 { 271 <div class="cta-paragraph__text @centerTextClass">@Content.Text</div> 272 } 273 274 @if (!string.IsNullOrWhiteSpace(Button.GetLink(Pageview)) && !string.IsNullOrWhiteSpace(Button.ButtonText)) 275 { 276 <nav class="cta-paragraph__btn-navigation @centerTextClass"> 277 @RenderButton(Button, Pageview) 278 @RenderButton(ExtraButton, Pageview) 279 </nav> 280 } 281 282 </article> 283 </section> 284 285 } 286 287 } 288 289 @helper CTAParagraphVideo(ParagraphVideo Video, string imagesHeight) 290 { 291 if (!string.IsNullOrWhiteSpace(Video.YoutubeLink) || !string.IsNullOrWhiteSpace(Video.VimeoLink)) 292 { 293 string YoutubeID = Video.YoutubeId; 294 string YoutubeLink = Video.YoutubeLink; 295 296 string VimeoID = Video.VimeoId; 297 string VimeoLink = Video.VimeoLink; 298 299 int CleanVideo = Video.Clean ? 1 : 0; 300 int ShowControls = Video.ShowControls ? 1 : 0; 301 int AutoPlay = Video.AutoPlay ? 1 : 0; 302 int LoopVideo = Video.LoopVideo ? 1 : 0; 303 int MuteAudio = Video.MuteAudio ? 1 : 0; 304 string hideControlsClass = Video.ShowControls ? "video-player-wrapper--hidecontrols" : ""; 305 string origin = Dynamicweb.Environment.Helpers.LinkHelper.GetHttpDomain(); 306 imagesHeight = !string.IsNullOrWhiteSpace(imagesHeight) ? "height: " + imagesHeight + ";" : ""; 307 308 if (!string.IsNullOrWhiteSpace(YoutubeLink)) 309 { 310 if(AutoPlay == 1) 311 { 312 <section class="cta-paragraph__video-container" style="@imagesHeight"> 313 <div class=""> 314 <div class="video-player-wrapper @hideControlsClass"> 315 <iframe class="video-player" loading="lazy" data-video="@YoutubeID" frameborder="0" allowfullscreen allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="YouTube video player" src="https://www.youtube-nocookie.com/embed/@YoutubeID?autoplay=@AutoPlay&controls=@ShowControls&loop=@LoopVideo&playlist=@YoutubeID&playsinline=1&modestbranding=@CleanVideo&mute=@MuteAudio&rel=0&enablejsapi=1&origin=@origin&disablekb=0"></iframe> 316 </div> 317 </div> 318 </section> 319 } 320 else 321 { 322 <lite-youtube videoid="@YoutubeID" params="controls=@ShowControls&loop=@LoopVideo&playlist=@YoutubeID&playsinline=1&modestbranding=@CleanVideo&mute=@MuteAudio&rel=0&enablejsapi=1&origin=@origin&disablekb=0"></lite-youtube> 323 } 324 } 325 if (!string.IsNullOrWhiteSpace(VimeoLink)) 326 { 327 <section class="cta-paragraph__video-container" style="@imagesHeight"> 328 <div class=""> 329 <div class="video-player-wrapper"> 330 <iframe class="video-player" loading="lazy" data-video="@VimeoID" frameborder="0" allowfullscreen allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" title="Vimeo video player" src="https://player.vimeo.com/video/@VimeoID?title=0&byline=0&portrait=0&autoplay=@AutoPlay&controls=@ShowControls&loop=@LoopVideo&muted=@MuteAudio"></iframe> 331 </div> 332 </div> 333 </section> 334 } 335 } 336 } 337 338 @helper CTAParagraphIcon(ParagraphIcon Icon, bool strCenterVertical) 339 { 340 if (!string.IsNullOrWhiteSpace(Icon.FaIcon)) 341 { 342 string centerIconClass = strCenterVertical ? "justify-center" : "justify-start"; 343 string iconSizeClass = string.Format("cta-paragraph__icon--{0}", Icon.FaIconSize); 344 345 <div class="cta-paragraph__icon-container"> 346 <div class="cta-paragraph__icon-inner-container @centerIconClass"> 347 <span class="cta-paragraph__icon @iconSizeClass">@Icon.FaIcon</span> 348 </div> 349 </div> 350 } 351 } 352 353 @helper RenderContentAlignment(BackgroundConfiguration data) 354 { 355 356 switch (data.ContentElementAlign) 357 { 358 case "align-left": 359 <text> 360 align-items: flex-start; 361 text-align: left; 362 </text> 363 break; 364 case "align-center": 365 <text> 366 align-items: center; 367 text-align: center; 368 </text> 369 break; 370 case "align-right": 371 <text> 372 align-items: flex-end; 373 text-align: right; 374 </text> 375 break; 376 case "align-full": 377 <text> 378 align-items: flex-start; 379 text-align: justify; 380 </text> 381 break; 382 } 383 384 } 385 386 387 @{ 388 389 string backgroundImageRepeatClass = _data.BackgroundConfiguration.BackgroundImageRepeat; 390 string backgroundImageSizeClass = ""; 391 392 string BackgroundImagePositionX = _data.BackgroundConfiguration.BackgroundImagePositionX; 393 string BackgroundImagePositionY = _data.BackgroundConfiguration.BackgroundImagePositionY; 394 395 string BackgroundImagePositionClass = ""; 396 397 if (backgroundImageRepeatClass == "no-repeat") 398 { 399 BackgroundImagePositionClass = BackgroundImagePositionY + "-" + BackgroundImagePositionX; 400 backgroundImageSizeClass = _data.BackgroundConfiguration.BackgroundImageSize; 401 } 402 403 string ctaBackgroundColor = _data.BackgroundConfiguration.BackgroundColor; 404 string contentBorderColor = _data.BackgroundConfiguration.contentBorderColor; 405 406 string contentBorderSize = _data.BackgroundConfiguration.contentBorderSize + "px"; 407 408 ctaBackgroundColor = colorService.GetHexColor(Pageview.AreaID, ctaBackgroundColor); 409 contentBorderColor = colorService.GetHexColor(Pageview.AreaID, contentBorderColor); 410 411 string contentBackgroundColor = _data.BackgroundConfiguration.contentBackgroundColor; 412 413 string contentGutterClass = _data.BackgroundConfiguration.contentGutter; 414 string BackgroundPadding = _data.BackgroundConfiguration.backgroundPadding; 415 416 contentBackgroundColor = colorService.GetHexColor(Pageview.AreaID, contentBackgroundColor); 417 418 } 419 420 <style> 421 422 @@media screen and (min-width: 991px) { 423 .multicolumn--@paragraphID { 424 background-color: @ctaBackgroundColor; 425 } 426 427 .multicolumn--@paragraphID .cta-paragraph { 428 background-color: @contentBackgroundColor; 429 border: @contentBorderSize @contentBorderColor solid; 430 } 431 } 432 433 .flickity-viewport{ 434 width: 100%; 435 } 436 437 .header__cta{ 438 display: flex; 439 align-items: center; 440 } 441 442 </style> 443 444 @if (amountColumns > 0) 445 { 446 <div class="multicolumn overflow-hidden multicolumn--@paragraphID @backgroundClass @_data.CssClass @backgroundImageRepeatClass @BackgroundImagePositionClass @backgroundImageSizeClass @contentGutterClass @BackgroundPadding" data-paragraphid="@paragraphID" id="@paragraphID" style="@backgroundStyle"> 447 <div class="@classFullWidth">@RenderContentArea(_data, paragraphID)</div> 448 </div> 449 } 450 451 @helper RenderContentArea(Carousel _data, int paragraphID) 452 { 453 454 //var subheaderFontConfig = GetFontConfiguration(_data.BackgroundConfiguration.CTASubheaderTextColor, _data.BackgroundConfiguration.FontConfigurationSubheader); 455 //var headerFontConfig = GetFontConfiguration(_data.BackgroundConfiguration.CTAHeaderTextColor, _data.BackgroundConfiguration.FontConfigurationHeader); 456 //var contentFontConfig = GetFontConfiguration(_data.BackgroundConfiguration.CTAContentTextColor, _data.BackgroundConfiguration.FontConfigurationContent); 457 458 //var colorService = new ColorSwatchService(); 459 460 int amountColumns = _data.CarouselItems.Count; // Amount of the columns in backend, filled by user 461 462 string centerTextClass = _data.CenterText ? "items-center text-center" : "items-start text-left"; 463 464 /* Specific for Carousel */ 465 466 int colDisplay = _data.ColumnsDisplay; // Amount of displayed column within one screen 467 468 bool fullWidth = _data.Fullwidth; // If slider or multicolumn has to be in container or full widthof the page 469 bool infiniteLoop = _data.Infinite; 470 bool autoPlay = _data.AutoPlay; 471 bool controls = _data.AddControls; 472 int duration = _data.Duration; 473 bool showDots = _data.ShowDots; // If slider or multicolumn has to be in container or full widthof the page 474 int colAmount = 1; 475 476 bool imagesOnlyBool = checkOnlyImages(_data); // Check if this carousel contains only images (logo slider) 477 478 //subheaderFontConfig["textColor"] = colorService.GetHexColor(Pageview.AreaID, subheaderFontConfig["textColor"]); 479 //headerFontConfig["textColor"] = colorService.GetHexColor(Pageview.AreaID, headerFontConfig["textColor"]); 480 //contentFontConfig["textColor"] = colorService.GetHexColor(Pageview.AreaID, contentFontConfig["textColor"]); 481 482 bool Shadow = _data.BackgroundConfiguration.contentShadow; 483 string shadowClass = Shadow ? "contentShadow" : ""; 484 485 if (!string.IsNullOrWhiteSpace(@_data.Header.HeaderFormatted())) 486 { 487 <header class="multicolumn__header-wrapper"> 488 @_data.Header.HeaderFormatted("multicolumn__header") 489 </header> 490 } 491 492 string carouselHeight = "auto"; 493 494 if (imagesOnlyBool && _data.ImageHeight != 0) 495 { 496 carouselHeight = _data.ImageHeight.ToString() + "px"; 497 } 498 499 if ((colDisplay <= amountColumns) && (colDisplay != 0)) 500 { 501 string flexBasis = 100 / @colDisplay + "%"; 502 503 <section class="carousel multicolumn" 504 data-columns="@colAmount" 505 data-dots="@showDots" 506 data-loop="@infiniteLoop" 507 data-autoplay="@autoPlay" 508 data-controls="@controls" 509 data-duration="@duration" 510 style="height: @carouselHeight;"> 511 512 @foreach (var column in _data.CarouselItems) 513 { 514 515 bool hasContent = !string.IsNullOrWhiteSpace(column.Button.ButtonText) || !string.IsNullOrWhiteSpace(column.Content.Text) || !string.IsNullOrWhiteSpace(column.Header.HeaderFormatted()); 516 517 string image = column.Image.Image; 518 string imagesHeight = _data.ImageHeight == 0 ? "auto" : _data.ImageHeight.ToString() + "px"; 519 string ImageContainerFixed = hasContent ? "cta-paragraph__image-container--fixed" : ""; 520 string ImageAsBackground = (column.BackgroundConfiguration.ConfigurationName == "Image as Background") ? "cta-paragraph__image--is-background" : ""; 521 522 string coverImage = ""; 523 524 string figureHeight = !hasContent ? "flex-grow:1" : "height:" + imagesHeight; 525 string TempClass = imagesOnlyBool ? "imageOnly" : "hasContent"; 526 string ImageOnlyImageHeight = imagesOnlyBool ? "height:" + imagesHeight + ";" : "height:auto;"; 527 528 if (!imagesOnlyBool) 529 { 530 imagesHeight = hasContent ? imagesHeight : imagesHeight = "100%"; 531 } 532 533 /*This is work around created by Alla to enable cover mode for stand alone pictures*/ 534 if (!hasContent && column.Image.BackgroundSize == "bg-cover") 535 { 536 coverImage = "height:100%;"; 537 } 538 539 <div class="multicolumn__item carousel-cell-wrap" style="display: flex; min-height:100%; @ImageOnlyImageHeight width: @flexBasis; @coverImage"> 540 541 <section class="cta-paragraph carousel-cell" style="min-height: @imagesHeight; @ImageOnlyImageHeight"> 542 @{ 543 string newWindow = column.Button.NewWindow ? "target='_blank'" : ""; 544 string ariaLabel = !string.IsNullOrWhiteSpace(column.Button.ButtonAriaLabel) ? "aria-label='" + column.Button.ButtonAriaLabel + "'" : ""; 545 bool clickableBlock = !string.IsNullOrWhiteSpace(column.Button.GetLink(Pageview)) && _data.Clickable; 546 string clickableClass = clickableBlock ? "cta-paragraph__container--clickable" : ""; 547 548 double ColumnAmount = colDisplay; 549 double ColumnWidthSize = 1 / ColumnAmount; 550 } 551 552 @CTAParagraphImage( 553 column.Image, 554 hasContent, 555 false, 556 null, 557 false, 558 _data.Fullwidth, 559 imagesHeight, 560 ColumnWidthSize 561 ) 562 563 @CTAParagraphContent( 564 paragraphID, 565 column.Header, 566 column.Subheader, 567 column.Content, 568 column.Button, 569 column.ExtraButton, 570 column.Image, 571 false 572 ) 573 574 @if (clickableBlock) 575 { 576 <a href="@column.Button.GetLink(Pageview)" class="cta-paragraph__clickable" @newWindow @ariaLabel></a> 577 } 578 </section> 579 580 </div> 581 } 582 </section> 583 } 584 else if (colDisplay > amountColumns) 585 { 586 <div>Error: you cant display columns more than you filled in the backend</div> 587 } 588 } 589 590 @functions{ 591 // Check if this carousel contains only images (logo slider) 592 bool checkOnlyImages(Carousel _data) 593 { 594 595 int amountColumns = _data.CarouselItems.Count; // Amount of the columns in backend, filled by user 596 int emptyColumn = 0; 597 598 // Loop through all the columns 599 foreach (var column in _data.CarouselItems) 600 { 601 // If button is empty AND content is empty AND header is empty => this is img only 602 if (string.IsNullOrWhiteSpace(column.Button.ButtonText) && string.IsNullOrWhiteSpace(column.Content.Text) && string.IsNullOrWhiteSpace(column.Header.HeaderFormatted())) 603 { 604 emptyColumn++; 605 } 606 } 607 608 bool emptyColumnResult = emptyColumn == amountColumns ? true : false; 609 610 return emptyColumnResult; 611 612 } 613 } 614

2. YOUR TREATMENT TIME

How quickly you can complete one treatment has a direct impact on your sales and hence your profits. You only have a limited number of hours in a day but if you work faster, you can do more treatments per day and thus earn more. Salon clients pay for the result, not for the time spent. Also, most clients have very little time to spare themselves and so appreciate it if you can offer them the same or better results in a shorter time.

With the BFLEX and BSTRONG time-saving gels, you can provide a premium gel service in half the time because you apply them more easily, these gels require fewer steps, cure faster and require less filing. This allows you to earn twice as much.

3. ADDITIONAL SALES

Every day, you see a limited number of customers. They come in for a treatment with a predetermined price. However, you can achieve extra sales with every customer by providing personal advice on how they could extend the results of their manicure or pedicure with the right home care products.

With ProNails Hand, Nail & Foot Care products, you can offer your clients the same professional quality at home, as in the salon. Also, your customer knows the quality of your products, so they are also ideal as gifts for family and friends.

4. CUSTOMER SATISFACTION

A satisfied customer with nails that remain perfect until the next touch-up will not only be sure to come back, she will also recommend you to others. If customers encounter loose gels, fractions, discolouration or other issues, they will need to come back in and you will have to touch up their nails for free, wasting time and messing up your schedule. Or, worst case scenario, you never see your customer again.

When you work with 1 professional system, the products and working method are so coordinated that you can always guarantee a perfect result for every customer. So don't take risks by mixing products; your customer satisfaction is worth much more!

5. FULL DIARY

Good turnover and profits for your beauty business always start with a decent client base and a packed schedule. So you need to offer the right trendy gel services that are in high demand AND keep your customer satisfaction high with your excellent service. However, full is full; if your diary is already crammed you will have to turn down additional clients and will not be able to increase your sales. Switch to innovative and time-saving gels, such as BFLEX and BSTRONG, to create extra space in your schedule and extra sales!

6. FIXED COSTS

Your profit is determined by your turnover on the one hand and your costs on the other. A salon always has a series of costs that have to be taken into account. These include costs for the location, maintenance, energy consumption and also staff costs, which must always be tightly controlled. Given that you are often powerless to change these fixed costs, it is important to do everything you can to increase your turnover. These fixed costs may also increase (e.g. more expensive rent, energy prices and insurances) and, if this is the case, you will need to look at innovations and solutions to increase your sales.

7. COSTS PER TREATMENT

Even though this is the smallest part of your costs in percentage terms, the professional products you use are also a cost that needs to be closely monitored. The key here is to always look at the total consumption cost per treatment as well as the time the products offer you, because that determines your profit. If you use many different cheap products for 1 treatment and thus take longer, you will always end up more expensive than if you use 1 innovative all-in-one product that allows you to work twice as fast.

A BFLEX Natural Nail Treatment will cost you just €1.50 worth of product. BSTRONG Natural Nail Extensions will cost you just €1.90 worth of product for a touch-up and €2.65 worth of product for a new set. Add to that the time savings, which allow you to work twice as fast and earn twice as much, and you have the cheapest and most profitable solution in your salon!

Tags

  • Salon
To Top