Feat: Home and Contact pages setup with Altcha bot protection and saving to database using alterntive layout.

This commit is contained in:
2025-07-25 19:22:17 +01:00
parent fad5336cc4
commit b76a999d01
95 changed files with 10274 additions and 2115 deletions

View File

@@ -4,17 +4,17 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<title>{{ model.title }} - DOG</title>
<meta name="description" content="Professional dog training management software for UK trainers. Manage clients, track training sessions, monitor progress, and engage dog owners with our comprehensive SaaS platform. Starting from £15/month." />
<meta name="keywords" content="fetch metrics, fetchmetrics, dog training software, dog trainer management, pet training app, canine training system, dog training business software, professional dog training, UK dog trainers, training session management, dog training records, client management for dog trainers, dog training progress tracking, pet training business tools, dog training scheduling, canine behavior tracking, dog trainer CRM, training appointment booking, dog training client portal, canine training documentation, dog obedience training, puppy training programs, behavioral modification, training milestones, dog training certificates, trainer scheduling, client communication, training homework assignments, progress reports, dog training analytics, British dog training, dog training software UK, professional dog training tools" />
<meta name="description" content="Explore our wide range of software engineering services. We specialize in various tech stacks including MySQL, Python, Microsoft SQL Server, C#, Firebase, Node.js, Java, HTML5, React, CSS3, Flask, JavaScript, MVC, and REST." />
<meta name="keywords" content="software engineering, software development, software design, software testing, software maintenance, software support, software consultancy, software training, software documentation, software project management, software quality assurance, software process improvement, software configuration management, software requirements engineering, software architecture, software design patterns, software design principles, software testing principles, software testing techniques, software testing tools, software testing automation, software testing manual, software testing exploratory, software testing regression, software testing performance, software testing security, software testing usability, software testing accessibility, software testing compatibility, software testing reliability, software testing maintainability, software testing portability, software testing scalability, software testing test-driven development, software testing behaviour-driven development, software testing acceptance test-driven development, software testing continuous integration, software testing continuous deployment, software testing continuous delivery, software testing continuous monitoring, software testing continuous feedback, software testing continuous improvement, software testing agile, software testing scrum, software testing kanban, software testing lean, software testing waterfall, software testing v-model, software testing spiral, software testing incremental, software testing iterative, software testing adaptive, software testing predictive, software testing hybrid, software testing manual, software testing automated, software testing exploratory, software testing regression, software testing performance, software testing security, software testing usability, software testing accessibility, software testing compatibility, software testing reliability, software testing maintainability, software testing portability, software testing scalability, software testing test-driven development, software testing behaviour-driven development, software testing acceptance test-driven development, software testing continuous integration, software testing continuous deployment, software testing continuous delivery, software testing continuous monitoring, software testing continuous feedback, software testing continuous improvement, software testing agile, software testing scrum, software testing kanban, software testing lean, software testing waterfall, software testing v-model, software testing spiral, software testing incremental, software testing iterative, software testing adaptive, software testing predictive, software testing hybrid, software testing manual, software testing automated, software testing exploratory, software testing regression, software testing performance, software testing security, software testing usability, software testing accessibility, software testing compatibility, software testing reliability, software testing maintainability, software testing portability, software testing scalability, software testing test-driven development, software testing behaviour-driven development, software testing acceptance test-driven development, software testing continuous integration, software testing continuous deployment, software testing continuous delivery, software testing continuous monitoring, software testing continuous feedback, software testing continuous improvement, software testing agile, software testing, MySQL, Python, Microsoft SQL Server, MS SQL Server, C#, Firebase, Node.js, Java, HTML5, React, CSS3, Flask, JavaScript, MVC, REST" />
<link rel="canonical" href="{{ model.get_url_host() }}" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "Dog Training",
"name": "{{ model.NAME_COMPANY_SHORT }}",
"url": "{{ model.get_url_host() }}",
"logo": "{{ model.get_url_host() }}{{ url_for('static', filename='images/Wisp_LQ.webp') }}",
"description": "Fetch Metrics - Professional dog training management software for UK trainers. Manage clients, track training sessions, monitor progress, and engage dog owners with our comprehensive SaaS platform. Starting from £15/month.",
"logo": "{{ model.get_url_host() }}{{ url_for('static', filename='images/Logo.png') }}",
"description": "Explore our wide range of software engineering services. We specialize in various tech stacks including MySQL, Python, Microsoft SQL Server, C#, Firebase, Node.js, Java, HTML5, React, CSS3, Flask, JavaScript, MVC, and REST.",
"address": {
"@type": "PostalAddress",
"streetAddress": "53 Alfred Green Close",
@@ -29,15 +29,141 @@
"longitude": "1.16"
},
"openingHours": "Mo,Tu,We,Th,Fr 09:00-17:00",
"priceRange": "$",
"priceRange": "$$",
}
</script>
<meta name="yandex-verification" content="e8c84f13a578a656" /> <!-- fetch-metrics.co.uk -->
<meta name="yandex-verification" content="054b13bc60fb1625" /> <!-- fetch-metrics.com -->
<meta name="yandex-verification" content="f3c1a9bc28976419" /> <!-- fetchmetrics.co.uk -->
<meta name="yandex-verification" content="4693a824cfda082a" />
<meta id="{{ model.ID_CSRF_TOKEN }}" name="{{ model.FLAG_CSRF_TOKEN }}" content="{{ csrf_token() }}" />
<script>
{#
var attrIdAccessLevel = "{{ model.ATTR_ID_ACCESS_LEVEL }}";
var attrIdCurrency = "{{ model.ATTR_ID_CURRENCY }}";
var attrIdAddress = "{{ model.ATTR_ID_ADDRESS }}";
var attrIdPlant = "{{ model.ATTR_ID_PLANT }}";
var attrIdRegion = "{{ model.ATTR_ID_REGION }}";
var attrIdStorageLocation = "{{ model.ATTR_ID_STORAGE_LOCATION }}";
var attrTextCollapsed = "{{ model.ATTR_TEXT_COLLAPSED }}";
var attrTextExpanded = "{{ model.ATTR_TEXT_EXPANDED }}";
var attrValueCurrent = "{{ model.ATTR_VALUE_CURRENT }}";
var attrValuePrevious = "{{ model.ATTR_VALUE_PREVIOUS }}";
var attrValueNew = "{{ model.ATTR_VALUE_NEW }}";
var environment = {
"name": "{{ model.app.app_config.FLASK_ENV }}",
"is_production": "{{ model.app.app_config.is_production }}",
"is_development": "{{ model.app.app_config.is_development }}",
};
var flagAccessLevel = "{{ model.FLAG_ACCESS_LEVEL }}";
var flagAccessLevelRequired = "{{ model.FLAG_ACCESS_LEVEL_REQUIRED }}";
var flagActive = "{{ model.FLAG_ACTIVE }}";
var flagAdd = "{{ model.FLAG_ADD }}";
var flagAddress = "{{ model.FLAG_ADDRESS }}";
var flagAddressLine1 = "{{ model.FLAG_ADDRESS_LINE_1 }}";
var flagAddressLine2 = "{{ model.FLAG_ADDRESS_LINE_2 }}";
var flagButton = "{{ model.FLAG_BUTTON }}";
var flagButtonPrimary = "{{ model.FLAG_BUTTON_PRIMARY }}";
var flagCallback = "{{ model.FLAG_CALLBACK }}";
var flagCancel = "{{ model.FLAG_CANCEL }}";
var flagCard = "{{ model.FLAG_CARD }}";
var flagCity = "{{ model.FLAG_CITY }}";
var flagCloseTemporaryElement = "{{ model.FLAG_CLOSE_TEMPORARY_ELEMENT }}";
var flagCode = "{{ model.FLAG_CODE }}";
var flagCollapsed = "{{ model.FLAG_COLLAPSED }}";
var flagCollapsible = "{{ model.FLAG_COLLAPSIBLE }}";
var flagColumn = "{{ model.FLAG_COLUMN }}";
var flagComment = "{{ model.FLAG_COMMENT }}";
// var flagContactUs = "{{ model.FLAG_CONTACT_US }}";
var flagContainer = "{{ model.FLAG_CONTAINER }}";
var flagContainerCheckbox = "{{ model.FLAG_CONTAINER_CHECKBOX }}";
var flagContainerInput = "{{ model.FLAG_CONTAINER_INPUT }}";
var flagCounty = "{{ model.FLAG_COUNTY }}";
var flagCsrfToken = "{{ model.FLAG_CSRF_TOKEN }}";
var flagCurrency = "{{ model.FLAG_CURRENCY }}";
var flagDelete = "{{ model.FLAG_DELETE }}";
var flagDescription = "{{ model.FLAG_DESCRIPTION }}";
var flagDetail = "{{ model.FLAG_DETAIL }}";
var flagDialog = "{{ model.FLAG_DIALOG }}";
var flagDirty = "{{ model.FLAG_DIRTY }}";
var flagDisplayOrder = "{{ model.FLAG_DISPLAY_ORDER }}";
var flagDragging = "dragging";
var flagDragOver = "drag-over";
var flagEdit = "{{ model.FLAG_EDIT }}";
var flagEmail = "{{ model.FLAG_EMAIL }}";
var flagError = "{{ model.FLAG_ERROR }}";
var flagExpanded = "{{ model.FLAG_EXPANDED }}";
var flagFailure = "{{ model.FLAG_FAILURE }}";
var flagFax = "{{ model.FLAG_FAX }}";
var flagFilter = "{{ model.FLAG_FILTER }}";
var flagForm = "{{ model.FLAG_FORM }}";
var flagFormFilters = "{{ model.FLAG_FORM_FILTERS }}";
var flagImageLogo = "{{ model.FLAG_IMAGE_LOGO }}";
var flagInitialised = "{{ model.FLAG_INITIALISED }}";
// var flagItems = "{{ model.FLAG_ITEMS }}";
// var flagKeyPrimary = "{{ model.FLAG_KEY_PRIMARY }}";
var flagLeftHandStub = "{{ model.FLAG_LEFT_HAND_STUB }}";
var flagLogo = "{{ model.FLAG_LOGO }}";
var flagMessage = "{{ model.FLAG_MESSAGE }}";
var flagModal = "{{ model.FLAG_MODAL }}";
var flagMove = "move";
var flagName = "{{ model.FLAG_NAME }}";
var flagNameAttrOptionText = "{{ model.FLAG_NAME_ATTR_OPTION_TEXT}}";
var flagNameAttrOptionValue = "{{ model.FLAG_NAME_ATTR_OPTION_VALUE }}";
var flagNamePlural = "{{ model.FLAG_NAME_PLURAL }}";
var flagNavAdminHome = "{{ model.FLAG_NAV_ADMIN_HOME }}";
var flagNavContact = "{{ model.FLAG_NAV_CONTACT }}";
var flagNavHome = "{{ model.FLAG_NAV_HOME }}";
var flagNavServices = "{{ model.FLAG_NAV_SERVICES }}";
var flagNavUserAccount = "{{ model.FLAG_NAV_USER_ACCOUNT }}";
var flagNavUserAdmin = "{{ model.FLAG_NAV_USER_ADMIN }}";
var flagNavUserLogin = "{{ model.FLAG_NAV_USER_LOGIN }}";
var flagNavUserLogout = "{{ model.FLAG_NAV_USER_LOGOUT }}";
var flagOverlay = "{{ model.FLAG_OVERLAY }}";
var flagOverlayClose = "{{ model.FLAG_OVERLAY_CLOSE }}";
var flagPageBody = "{{ model.FLAG_PAGE_BODY }}";
var flagPhoneNumber = "{{ model.FLAG_PHONE_NUMBER }}";
var flagPostcode = "{{ model.FLAG_POSTCODE }}";
var flagCaptcha = "{{ model.FLAG_CAPTCHA }}";
var flagRightHandSide = "{{ model.FLAG_RIGHT_HAND_SIDE }}";
var flagRow = "{{ model.FLAG_ROW }}";
var flagRowNew = "{{ model.FLAG_ROW_NEW }}";
var flagRows = "{{ model.FLAG_ROWS }}";
var flagSave = "{{ model.FLAG_SAVE }}";
var flagScrollable = "{{ model.FLAG_SCROLLABLE }}";
var flagSlider = "{{ model.FLAG_SLIDER }}";
var flagStatus = "{{ model.FLAG_STATUS }}";
var flagSubmit = "{{ model.FLAG_SUBMIT }}";
var flagSubmitted = "{{ model.FLAG_SUBMITTED }}";
var flagSuccess = "{{ model.FLAG_SUCCESS }}";
var flagTemporaryElement = "{{ model.FLAG_TEMPORARY_ELEMENT }}";
var flagUser = "{{ model.FLAG_USER }}";
var flagWebsite = "{{ model.FLAG_WEBSITE }}";
var hashGetALTCHAChallenge = "{{ model.HASH_ALTCHA_CREATE_CHALLENGE }}";
var hashPageAccessibilityReport = "{{ model.HASH_PAGE_ACCESSIBILITY_REPORT }}";
var hashPageAccessibilityStatement = "{{ model.HASH_PAGE_ACCESSIBILITY_STATEMENT }}";
var hashPageContact = "{{ model.HASH_PAGE_CONTACT }}";
var hashPageContactSuccess = "{{ model.HASH_PAGE_CONTACT_SUCCESS }}";
var hashPageDataRetentionSchedule = "{{ model.HASH_PAGE_DATA_RETENTION_SCHEDULE }}";
var hashPageErrorNoPermission = "{{ model.HASH_PAGE_ERROR_NO_PERMISSION }}";
var hashPageHome = "{{ model.HASH_PAGE_HOME }}";
var hashPageLicense = "{{ model.HASH_PAGE_LICENSE }}";
var hashPagePrivacyPolicy = "{{ model.HASH_PAGE_PRIVACY_POLICY }}";
var idButtonApplyFilters = "#{{ model.ID_BUTTON_APPLY_FILTERS }}";
var idButtonHamburger = "#{{ model.ID_BUTTON_HAMBURGER }}";
var idCSRFToken = "#{{ model.ID_CSRF_TOKEN }}";
var idFormFilters = "#{{ model.ID_FORM_FILTERS }}";
var idLabelError = "#{{ model.ID_LABEL_ERROR }}";
var idOverlayConfirm = "#{{ model.ID_OVERLAY_CONFIRM }}";
var idOverlayError = "#{{ model.ID_OVERLAY_ERROR }}";
var idOverlayHamburger = "#{{ model.ID_OVERLAY_HAMBURGER }}";
var idPageBody = "#{{ model.ID_PAGE_BODY }}";
var idTableMain = "#{{ model.ID_TABLE_MAIN }}";
var idTextareaConfirm = "#{{ model.ID_TEXTAREA_CONFIRM }}";
var isUserLoggedIn = "{{ model.output_bool(model.IS_USER_LOGGED_IN) }}";
var _pathHost = "{{ model.get_url_host() }}";
var _rowBlank = null;
var titlePageCurrent = "{{ model.title }}";
var _verbose = ("{{ model.app.app_config.DEBUG }}" == "True");
#}
var attrIdAssessment = "{{ model.ATTR_ID_ASSESSMENT }}";
var attrIdAssessmentCommandModalityLink = "{{ model.ATTR_ID_ASSESSMENT_COMMAND_MODALITY_LINK }}";
var attrIdAssessmentResponse = "{{ model.ATTR_ID_ASSESSMENT_RESPONSE }}";
@@ -265,73 +391,70 @@
{% block page_head %}{% endblock %}
</head>
<body data-page="{{ model.hash_page_current }}">
<!-- Header -- >
<!-- Header -->
<header>
<div class="container">
<nav class="navbar">
<div class="{{ model.FLAG_LOGO }}" href="{{ model.HASH_PAGE_HOME }}">{{ model.NAME_COMPANY }}</div>
<div class="{{ model.FLAG_LOGO }}" href="{{ model.HASH_PAGE_HOME }}">{{ model.NAME_COMPANY_SHORT }}</div>
<div class="nav-links">
{% block page_nav_links %}{% endblock %}
</div>
</nav>
</div>
</header>
-->
<div class="topnav">
<div class="{{ model.FLAG_CONTAINER }} header-logo"> <!-- style="width: 18vw; min-width: 18vw; max-width: 20vw;" -->
<img class="header-logo" src="{{ url_for('static', filename='images/Wisp_LQ.webp') }}" alt="Fetch Metrics logo" aria-label="Fetch Metrics logo" tabindex="0">
</div>
<div class="{{ model.FLAG_CONTAINER }} company-name"> <!-- style="width: 75vw; min-width: 65vw; max-width: 80vw;" -->
<h1 class="company-name">{{ model.NAME_COMPANY_SHORT }} - {{ model.title }}</h1>
</div>
{#
<div class="{{ model.FLAG_CONTAINER }}"> <!-- style="width: 7vw; min-width: 7vw; max-width: 15vw; justify-content: flex-end; " padding-left: 25%; -->
<button id="{{ model.ID_BUTTON_HAMBURGER }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}" tabindex="1" alt="Hamburger menu button" aria-label="Hamburger menu button"></button>
</div>
#}
</div>
<!-- Hamburger navigation menu -->
{% include 'components/common/buttons/_icon_hamburger.html' %}
<div id="{{ model.ID_OVERLAY_HAMBURGER }}" class="{{ model.FLAG_OVERLAY}} {{ model.FLAG_HAMBURGER }} {{ model.FLAG_IS_COLLAPSED }}">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_HOME }}">Home</a>
</div>
{% if True or model.user.can_admin_dog %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_DOG_HOME }}">Dog Home</a>
</div>
{% endif %}
{% if model.user.get_is_logged_in() %}
{#
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_ACCOUNT }}">Account</a>
</div>
#}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGOUT }}">Logout</a>
</div>
{% else %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGIN }}">Login</a>
</div>
{% endif %}
</div>
<!-- Body -->
<div id="{{ model.ID_PAGE_BODY }}">
{% block page_body %}{% endblock %}
</div>
<!-- Footer -->
<div class="footer">
<h4>Copyright &copy; {{ model.NAME_COMPANY }}. <a href="{{ url_for('routes_legal.license') }}" alt="License" aria-label="License">All rights reserved.</a></h4>
<h5>Company number 13587499</h5>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}"><p><a href="{{ url_for('routes_legal.accessibility_statement') }}" alt="Accessibility statement" aria-label="Accessibility statement">Accessibility statement</a></p></div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}"><p><a href="{{ url_for('routes_legal.privacy_policy') }}" alt="Privacy notice" aria-label="Privacy notice">Privacy notice</a></p></div>
<footer class="footer">
<div class="{{ model.FLAG_CONTAINER }}">
<div class="footer-content">
<div class="footer-section">
<h3>{{ model.NAME_COMPANY }}</h3>
<p>Company Number: {{ model.COMPANY_NUMBER }}</p>
<p>Registered in England and Wales</p>
<p>Registered Office: {{ model.COMPANY_ADDRESS_SHORT }}</p>
</div>
<div class="footer-section">
<h3>Legal</h3>
<ul>
<li><a href="{{ model.HASH_PAGE_PRIVACY_POLICY }}">Privacy Policy</a></li>
<li><a href="{{ model.HASH_PAGE_ACCESSIBILITY_STATEMENT }}">Accessibility Statement</a></li>
</ul>
</div>
<div class="footer-section">
<h3>Contact</h3>
<ul>
<li><a href="mailto:{{ model.get_mail_contact_public() }}">Email: {{ model.get_mail_contact_public() }}</a></li>
<li><a href="{{ model.URL_DISCORD }}">Discord: {{ model.USERNAME_DISCORD }}</a></li>
<!-- <li><a href="{{ model.URL_FACEBOOK }}">Facebook: {{ model.USERNAME_FACEBOOK }}</a></li> -->
<li><a href="{{ model.URL_GITHUB }}">GitHub: {{ model.USERNAME_GITHUB }}</a></li>
<li><a href="{{ model.URL_INSTAGRAM }}">Instagram: {{ model.USERNAME_INSTAGRAM }}</a></li>
</ul>
</div>
<div class="footer-section">
<h3 style="color: #1f2937;">Contact</h3>
<ul>
<!-- <li>Phone</li> -->
<!-- <li><a href="{{ model.URL_LINKEDIN }}">LinkedIn: {{ model.USERNAME_LINKEDIN }}</a></li> -->
<li><a href="{{ model.URL_REDDIT }}">Reddit: {{ model.USERNAME_REDDIT }}</a></li>
<li><a href="{{ model.URL_TIKTOK }}">TikTok: {{ model.USERNAME_TIKTOK }}</a></li>
<li><a href="{{ model.URL_TWITTER }}">Twitter: {{ model.USERNAME_TWITTER }}</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>&copy; {{ current_year }} {{ model.NAME_COMPANY }}. <a href="{{ model.HASH_PAGE_LICENSE }}" alt="License" aria-label="License">All rights reserved.</a></p>
</div>
</div>
</div>
</footer>
<script src="{{ url_for('static', filename='dist/js/main.bundle.js') }}"></script>
</body>

View File

@@ -0,0 +1,341 @@
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<title>{{ model.title }} - DOG</title>
<meta name="description" content="Professional dog training management software for UK trainers. Manage clients, track training sessions, monitor progress, and engage dog owners with our comprehensive SaaS platform. Starting from £15/month." />
<meta name="keywords" content="fetch metrics, fetchmetrics, dog training software, dog trainer management, pet training app, canine training system, dog training business software, professional dog training, UK dog trainers, training session management, dog training records, client management for dog trainers, dog training progress tracking, pet training business tools, dog training scheduling, canine behavior tracking, dog trainer CRM, training appointment booking, dog training client portal, canine training documentation, dog obedience training, puppy training programs, behavioral modification, training milestones, dog training certificates, trainer scheduling, client communication, training homework assignments, progress reports, dog training analytics, British dog training, dog training software UK, professional dog training tools" />
<link rel="canonical" href="{{ model.get_url_host() }}" />
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "ProfessionalService",
"name": "Dog Training",
"url": "{{ model.get_url_host() }}",
"logo": "{{ model.get_url_host() }}{{ url_for('static', filename='images/Wisp_LQ.webp') }}",
"description": "Fetch Metrics - Professional dog training management software for UK trainers. Manage clients, track training sessions, monitor progress, and engage dog owners with our comprehensive SaaS platform. Starting from £15/month.",
"address": {
"@type": "PostalAddress",
"streetAddress": "53 Alfred Green Close",
"addressLocality": "Rugby",
"addressRegion": "Warwickshire",
"postalCode": "CV22 6DN",
"addressCountry": "United Kingdom"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": "52.22",
"longitude": "1.16"
},
"openingHours": "Mo,Tu,We,Th,Fr 09:00-17:00",
"priceRange": "$",
}
</script>
<meta name="yandex-verification" content="e8c84f13a578a656" /> <!-- fetch-metrics.co.uk -->
<meta name="yandex-verification" content="054b13bc60fb1625" /> <!-- fetch-metrics.com -->
<meta name="yandex-verification" content="f3c1a9bc28976419" /> <!-- fetchmetrics.co.uk -->
<meta id="{{ model.ID_CSRF_TOKEN }}" name="{{ model.FLAG_CSRF_TOKEN }}" content="{{ csrf_token() }}" />
<script>
var attrIdAssessment = "{{ model.ATTR_ID_ASSESSMENT }}";
var attrIdAssessmentCommandModalityLink = "{{ model.ATTR_ID_ASSESSMENT_COMMAND_MODALITY_LINK }}";
var attrIdAssessmentResponse = "{{ model.ATTR_ID_ASSESSMENT_RESPONSE }}";
var attrIdAccessLevel = "{{ model.ATTR_ID_ACCESS_LEVEL }}";
var attrIdBribe = "{{ model.ATTR_ID_BRIBE }}";
var attrIdButtonColour = "{{ model.ATTR_ID_BUTTON_COLOUR }}";
var attrIdButtonIcon = "{{ model.ATTR_ID_BUTTON_ICON }}";
var attrIdButtonShape = "{{ model.ATTR_ID_BUTTON_SHAPE }}";
var attrIdColour = "{{ model.ATTR_ID_COLOUR }}";
var attrIdCommand = "{{ model.ATTR_ID_COMMAND }}";
var attrIdCommandButtonLink = "{{ model.ATTR_ID_COMMAND_BUTTON_LINK }}";
var attrIdCommandCategory = "{{ model.ATTR_ID_COMMAND_CATEGORY }}";
var attrIdCommandModality = "{{ model.ATTR_ID_COMMAND_MODALITY }}";
var attrIdCurrency = "{{ model.ATTR_ID_CURRENCY }}";
var attrIdDistraction = "{{ model.ATTR_ID_DISTRACTION }}";
var attrIdDistractionIntensityLevel = "{{ model.ATTR_ID_DISTRACTION_INTENSITY_LEVEL }}";
var attrIdDistractionType = "{{ model.ATTR_ID_DISTRACTION_TYPE }}";
var attrIdDog = "{{ model.ATTR_ID_DOG }}";
var attrIdDogCommandLink = "{{ model.ATTR_ID_DOG_COMMAND_LINK }}";
var attrIdLightingLevel = "{{ model.ATTR_ID_LIGHTING_LEVEL }}";
var attrIdLocation = "{{ model.ATTR_ID_LOCATION }}";
var attrIdWeather = "{{ model.ATTR_ID_WEATHER }}";
var attrTextCollapsed = "{{ model.ATTR_TEXT_COLLAPSED }}";
var attrTextExpanded = "{{ model.ATTR_TEXT_EXPANDED }}";
var attrValueCurrent = "{{ model.ATTR_VALUE_CURRENT }}";
var attrValuePrevious = "{{ model.ATTR_VALUE_PREVIOUS }}";
var attrValueNew = "{{ model.ATTR_VALUE_NEW }}";
var colourAccent = "{{ model.COLOUR_ACCENT }}";
var colourError = "{{ model.COLOUR_ERROR }}";
var colourPageBackground = "{{ model.COLOUR_PAGE_BACKGROUND }}";
var colourPageBackground1 = "{{ model.COLOUR_PAGE_BACKGROUND_1 }}";
var colourPageBackground2 = "{{ model.COLOUR_PAGE_BACKGROUND_2 }}";
var colourPrimary = "{{ model.COLOUR_PRIMARY }}";
var colourSecondary = "{{ model.COLOUR_SECONDARY }}";
var colourText = "{{ model.COLOUR_TEXT }}";
var colourTextBackground = "{{ model.COLOUR_TEXT_BACKGROUND }}";
var colourTextLinkUnvisited = "{{ model.COLOUR_TEXT_LINK_UNVISITED }}";
var colourTextLinkVisited = "{{ model.COLOUR_TEXT_LINK_VISITED }}";
var environment = {
"name": "{{ model.app.app_config.FLASK_ENV }}",
"is_production": "{{ model.app.app_config.is_production | lower }}",
"is_development": "{{ model.app.app_config.is_development | lower }}",
};
var flagAccessLevel = "{{ model.FLAG_ACCESS_LEVEL }}";
var flagAccessLevelRequired = "{{ model.FLAG_ACCESS_LEVEL_REQUIRED }}";
var flagActive = "{{ model.FLAG_ACTIVE }}";
var flagActiveOnly = "{{ model.FLAG_ACTIVE_ONLY }}";
var flagAdd = "{{ model.FLAG_ADD }}";
var flagAddress = "{{ model.FLAG_ADDRESS }}";
var flagAddressLine1 = "{{ model.FLAG_ADDRESS_LINE_1 }}";
var flagAddressLine2 = "{{ model.FLAG_ADDRESS_LINE_2 }}";
var flagAssessment = "{{ model.FLAG_ASSESSMENT }}";
var flagAssessmentCommandModalityLink = "{{ model.FLAG_ASSESSMENT_COMMAND_MODALITY_LINK }}";
var flagAssessmentResponse = "{{ model.FLAG_ASSESSMENT_RESPONSE }}";
var flagBribe = "{{ model.FLAG_BRIBE }}";
var flagButton = "{{ model.FLAG_BUTTON }}";
var flagButtonIcon = "{{ model.FLAG_BUTTON_ICON }}";
var flagButtonShape = "{{ model.FLAG_BUTTON_SHAPE }}";
var flagButtonPrimary = "{{ model.FLAG_BUTTON_PRIMARY }}";
var flagCallback = "{{ model.FLAG_CALLBACK }}";
var flagCancel = "{{ model.FLAG_CANCEL }}";
var flagCaptcha = "{{ model.FLAG_CAPTCHA }}";
var flagCard = "{{ model.FLAG_CARD }}";
var flagCheckbox = "{{ model.FLAG_CHECKBOX }}";
var flagCity = "{{ model.FLAG_CITY }}";
var flagCloseTemporaryElement = "{{ model.FLAG_CLOSE_TEMPORARY_ELEMENT }}";
var flagCode = "{{ model.FLAG_CODE }}";
var flagCollapsible = "{{ model.FLAG_COLLAPSIBLE }}";
var flagColour = "{{ model.FLAG_COLOUR }}";
var flagColumn = "{{ model.FLAG_COLUMN }}";
var flagCommand = "{{ model.FLAG_COMMAND }}";
var flagCommandButtonLink = "{{ model.FLAG_COMMAND_BUTTON_LINK }}";
var flagCommandCategory = "{{ model.FLAG_COMMAND_CATEGORY }}";
var flagComment = "{{ model.FLAG_COMMENT }}";
var flagContainer = "{{ model.FLAG_CONTAINER }}";
var flagContainerInput = "{{ model.FLAG_CONTAINER_INPUT }}";
var flagCounty = "{{ model.FLAG_COUNTY }}";
var flagCsrfToken = "{{ model.FLAG_CSRF_TOKEN }}";
var flagCurrency = "{{ model.FLAG_CURRENCY }}";
var flagDdlPreview = "{{ model.FLAG_DDL_PREVIEW }}";
var flagDelete = "{{ model.FLAG_DELETE }}";
var flagDescription = "{{ model.FLAG_DESCRIPTION }}";
var flagDetail = "{{ model.FLAG_DETAIL }}";
var flagDialog = "{{ model.FLAG_DIALOG }}";
var flagDirty = "{{ model.FLAG_DIRTY }}";
var flagDisplayOrder = "{{ model.FLAG_DISPLAY_ORDER }}";
var flagDistraction = "{{ model.FLAG_DISTRACTION }}";
var flagDistractionIntensityLevel = "{{ model.FLAG_DISTRACTION_INTENSITY_LEVEL }}";
var flagDistractionType = "{{ model.FLAG_DISTRACTION_TYPE }}";
var flagDog = "{{ model.FLAG_DOG }}";
var flagDogDogCommandLink = "{{ model.FLAG_DOG_DOG_COMMAND_LINK }}";
var flagDragging = "dragging";
var flagDragOver = "drag-over";
var flagEdit = "{{ model.FLAG_EDIT }}";
var flagEmail = "{{ model.FLAG_EMAIL }}";
var flagError = "{{ model.FLAG_ERROR }}";
var flagExpanded = "{{ model.FLAG_EXPANDED }}";
var flagFailure = "{{ model.FLAG_FAILURE }}";
var flagFax = "{{ model.FLAG_FAX }}";
var flagFilter = "{{ model.FLAG_FILTER }}";
var flagForm = "{{ model.FLAG_FORM }}";
var flagFormFilters = "{{ model.FLAG_FORM_FILTERS }}";
var flagIcon = "{{ model.FLAG_ICON }}";
var flagImageLogo = "{{ model.FLAG_IMAGE_LOGO }}";
var flagInitialised = "{{ model.FLAG_INITIALISED }}";
var flagIsChecked = "{{ model.FLAG_IS_CHECKED }}";
var flagIsCollapsed = "{{ model.FLAG_IS_COLLAPSED }}";
var flagLeftHandStub = "{{ model.FLAG_LEFT_HAND_STUB }}";
var flagLightingLevel = "{{ model.FLAG_LIGHTING_LEVEL }}";
var flagLocation = "{{ model.FLAG_LOCATION }}";
var flagLocationParent = "{{ model.FLAG_LOCATION_PARENT }}";
var flagLogo = "{{ model.FLAG_LOGO }}";
var flagMessage = "{{ model.FLAG_MESSAGE }}";
var flagModal = "{{ model.FLAG_MODAL }}";
var flagMove = "move";
var flagName = "{{ model.FLAG_NAME }}";
var flagNameAttrOptionText = "{{ model.FLAG_NAME_ATTR_OPTION_TEXT}}";
var flagNameAttrOptionValue = "{{ model.FLAG_NAME_ATTR_OPTION_VALUE }}";
var flagNamePlural = "{{ model.FLAG_NAME_PLURAL }}";
var flagNavAdminHome = "{{ model.FLAG_NAV_ADMIN_HOME }}";
var flagNavContact = "{{ model.FLAG_NAV_CONTACT }}";
var flagNavHome = "{{ model.FLAG_NAV_HOME }}";
var flagNavDogAssessments = "{{ model.FLAG_NAV_DOG_ASSESSMENTS }}";
var flagNavDogButtonIcons = "{{ model.FLAG_NAV_DOG_BUTTON_ICONS }}";
var flagNavDogButtonShapes = "{{ model.FLAG_NAV_DOG_BUTTON_SHAPES }}";
var flagNavDogColour = "{{ model.FLAG_NAV_DOG_COLOUR }}";
var flagNavDogCommandButtonLinks = "{{ model.FLAG_NAV_DOG_COMMAND_BUTTON_LINKS }}";
var flagNavDogCommandCategories = "{{ model.FLAG_NAV_DOG_COMMAND_CATEGORIES }}";
var flagNavDogCommands = "{{ model.FLAG_NAV_DOG_COMMANDS }}";
var flagNavDogDogs = "{{ model.FLAG_NAV_DOG_DOGS }}";
var flagNavDogDogCommandLinks = "{{ model.FLAG_NAV_DOG_DOG_COMMAND_LINKS }}";
var flagNavDogHome = "{{ model.FLAG_NAV_DOG_HOME }}";
var flagNavDogLocations = "{{ model.FLAG_NAV_DOG_LOCATIONS }}";
var flagNavUserAccount = "{{ model.FLAG_NAV_USER_ACCOUNT }}";
var flagNavUserAdmin = "{{ model.FLAG_NAV_USER_ADMIN }}";
var flagNavUserLogin = "{{ model.FLAG_NAV_USER_LOGIN }}";
var flagNavUserLogout = "{{ model.FLAG_NAV_USER_LOGOUT }}";
var flagNotes = "{{ model.FLAG_NOTES }}";
var flagObedienceLevel = "{{ model.FLAG_OBEDIENCE_LEVEL }}";
var flagOverlay = "{{ model.FLAG_OVERLAY }}";
var flagOverlayClose = "{{ model.FLAG_OVERLAY_CLOSE }}";
var flagPageBody = "{{ model.FLAG_PAGE_BODY }}";
var flagPhoneNumber = "{{ model.FLAG_PHONE_NUMBER }}";
var flagPostcode = "{{ model.FLAG_POSTCODE }}";
var flagQuantity = "{{ model.FLAG_QUANTITY }}";
var flagResponseQualityMetric = "{{ model.FLAG_RESPONSE_QUALITY_METRIC }}";
var flagRightHandSide = "{{ model.FLAG_RIGHT_HAND_SIDE }}";
var flagRow = "{{ model.FLAG_ROW }}";
var flagRowNew = "{{ model.FLAG_ROW_NEW }}";
var flagRows = "{{ model.FLAG_ROWS }}";
var flagSave = "{{ model.FLAG_SAVE }}";
var flagScrollable = "{{ model.FLAG_SCROLLABLE }}";
var flagSearch = "{{ model.FLAG_SEARCH }}";
var flagSlider = "{{ model.FLAG_SLIDER }}";
var flagStatus = "{{ model.FLAG_STATUS }}";
var flagSubmit = "{{ model.FLAG_SUBMIT }}";
var flagSubmitted = "{{ model.FLAG_SUBMITTED }}";
var flagSuccess = "{{ model.FLAG_SUCCESS }}";
var flagTableMain = "{{ model.FLAG_TABLE_MAIN }}";
var flagTemporaryElement = "{{ model.FLAG_TEMPORARY_ELEMENT }}";
var flagUser = "{{ model.FLAG_USER }}";
var flagWeather = "{{ model.FLAG_WEATHER }}";
var flagWebsite = "{{ model.FLAG_WEBSITE }}";
var hashGetALTCHAChallenge = "{{ model.HASH_ALTCHA_CREATE_CHALLENGE }}";
var hashPageAccessibilityReport = "{{ model.HASH_PAGE_ACCESSIBILITY_REPORT }}";
var hashPageAccessibilityStatement = "{{ model.HASH_PAGE_ACCESSIBILITY_STATEMENT }}";
var hashPageAdminHome = "{{ model.HASH_PAGE_ADMIN_HOME }}";
var hashPageContact = "{{ model.HASH_PAGE_CONTACT }}";
var hashPageContactSuccess = "{{ model.HASH_PAGE_CONTACT_SUCCESS }}";
var hashPageDataRetentionSchedule = "{{ model.HASH_PAGE_DATA_RETENTION_SCHEDULE }}";
var hashPageDogAssessment = "{{ model.HASH_PAGE_DOG_ASSESSMENT }}";
var hashPageDogAssessments = "{{ model.HASH_PAGE_DOG_ASSESSMENTS }}";
var hashPageDogButtonIcons = "{{ model.HASH_PAGE_DOG_BUTTON_ICONS }}";
var hashPageDogButtonShapes = "{{ model.HASH_PAGE_DOG_BUTTON_SHAPES }}";
var hashPageDogColours = "{{ model.HASH_PAGE_DOG_COLOURS }}";
var hashPageDogCommandButtonLinks = "{{ model.HASH_PAGE_DOG_COMMAND_BUTTON_LINKS }}";
var hashPageDogCommandCategories = "{{ model.HASH_PAGE_DOG_COMMAND_CATEGORIES }}";
var hashPageDogCommands = "{{ model.HASH_PAGE_DOG_COMMANDS }}";
var hashPageDogDogCommandLinks = "{{ model.HASH_PAGE_DOG_DOG_COMMAND_LINKS }}";
var hashPageDogDogs = "{{ model.HASH_PAGE_DOG_DOGS }}";
var hashPageDogHome = "{{ model.HASH_PAGE_DOG_HOME }}";
var hashPageDogLocations = "{{ model.HASH_PAGE_DOG_LOCATIONS }}";
var hashPageErrorNoPermission = "{{ model.HASH_PAGE_ERROR_NO_PERMISSION }}";
var hashPageHome = "{{ model.HASH_PAGE_HOME }}";
var hashPageLicense = "{{ model.HASH_PAGE_LICENSE }}";
var hashPagePrivacyPolicy = "{{ model.HASH_PAGE_PRIVACY_POLICY }}";
var hashPageUserAccount = "{{ model.HASH_PAGE_USER_ACCOUNT }}";
var hashPageUserAdmin = "{{ model.HASH_PAGE_USER_ADMIN }}";
var hashPageUserLogin = "{{ model.HASH_PAGE_USER_LOGIN }}";
var hashPageUserLogout = "{{ model.HASH_PAGE_USER_LOGOUT }}";
var hashSaveDogAssessment = "{{ model.HASH_SAVE_DOG_ASSESSMENT }}";
var hashSaveDogButtonIcon = "{{ model.HASH_SAVE_DOG_BUTTON_ICON }}";
var hashSaveDogButtonShape = "{{ model.HASH_SAVE_DOG_BUTTON_SHAPE }}";
var hashSaveDogColour = "{{ model.HASH_SAVE_DOG_COLOUR }}";
var hashSaveDogCommand = "{{ model.HASH_SAVE_DOG_COMMAND }}";
var hashSaveDogCommandButtonLink = "{{ model.HASH_SAVE_DOG_COMMAND_BUTTON_LINK }}";
var hashSaveDogCommandCategory = "{{ model.HASH_SAVE_DOG_COMMAND_CATEGORY }}";
var hashSaveDogDogCommandLink = "{{ model.HASH_SAVE_DOG_DOG_COMMAND_LINK }}";
var hashSaveDogLocation = "{{ model.HASH_SAVE_DOG_LOCATION }}";
var idButtonApplyFilters = "#{{ model.ID_BUTTON_APPLY_FILTERS }}";
var idButtonHamburger = "#{{ model.ID_BUTTON_HAMBURGER }}";
var idButtonCancel = "#{{ model.ID_BUTTON_CANCEL }}";
var idButtonSave = "#{{ model.ID_BUTTON_SAVE }}";
var idContainerTemplateElements = "#{{ model.ID_CONTAINER_TEMPLATE_ELEMENTS }}";
var idCSRFToken = "#{{ model.ID_CSRF_TOKEN }}";
var idFormFilters = "#{{ model.ID_FORM_FILTERS }}";
var idLabelError = "#{{ model.ID_LABEL_ERROR }}";
var idOverlayConfirm = "#{{ model.ID_OVERLAY_CONFIRM }}";
var idOverlayError = "#{{ model.ID_OVERLAY_ERROR }}";
var idOverlayHamburger = "#{{ model.ID_OVERLAY_HAMBURGER }}";
var idPageBody = "#{{ model.ID_PAGE_BODY }}";
var idTableMain = "#{{ model.ID_TABLE_MAIN }}";
var idTextareaConfirm = "#{{ model.ID_TEXTAREA_CONFIRM }}";
var isUserLoggedIn = "{{ model.output_bool(model.IS_USER_LOGGED_IN) }}";
var _pathHost = "{{ model.get_url_host() }}";
var _rowBlank = null;
var titlePageCurrent = "{{ model.title }}";
var _verbose = ("{{ model.app.app_config.DEBUG }}" == "True");
</script>
<link rel="preload" as="style" href="{{ url_for('static', filename='dist/css/main.bundle.css') }}" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="{{ url_for('static', filename='dist/css/main.bundle.css') }}"></noscript>
{% block page_head %}{% endblock %}
</head>
<body data-page="{{ model.hash_page_current }}">
<!-- Header -- >
<header>
<div class="container">
<nav class="navbar">
<div class="{{ model.FLAG_LOGO }}" href="{{ model.HASH_PAGE_HOME }}">{{ model.NAME_COMPANY }}</div>
<div class="nav-links">
{% block page_nav_links %}{% endblock %}
</div>
</nav>
</div>
</header>
-->
<div class="topnav">
<div class="{{ model.FLAG_CONTAINER }} header-logo"> <!-- style="width: 18vw; min-width: 18vw; max-width: 20vw;" -->
<img class="header-logo" src="{{ url_for('static', filename='images/Wisp_LQ.webp') }}" alt="Fetch Metrics logo" aria-label="Fetch Metrics logo" tabindex="0">
</div>
<div class="{{ model.FLAG_CONTAINER }} company-name"> <!-- style="width: 75vw; min-width: 65vw; max-width: 80vw;" -->
<h1 class="company-name">{{ model.NAME_COMPANY_SHORT }} - {{ model.title }}</h1>
</div>
{#
<div class="{{ model.FLAG_CONTAINER }}"> <!-- style="width: 7vw; min-width: 7vw; max-width: 15vw; justify-content: flex-end; " padding-left: 25%; -->
<button id="{{ model.ID_BUTTON_HAMBURGER }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}" tabindex="1" alt="Hamburger menu button" aria-label="Hamburger menu button"></button>
</div>
#}
</div>
<!-- Hamburger navigation menu -->
{% include 'components/common/buttons/_icon_hamburger.html' %}
<div id="{{ model.ID_OVERLAY_HAMBURGER }}" class="{{ model.FLAG_OVERLAY}} {{ model.FLAG_HAMBURGER }} {{ model.FLAG_IS_COLLAPSED }}">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_HOME }}">Home</a>
</div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_CONTACT }}">Contact</a>
</div>
{% if True or model.user.can_admin_dog %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_DOG_HOME }}">Dog Home</a>
</div>
{% endif %}
{% if model.user.get_is_logged_in() %}
{#
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_ACCOUNT }}">Account</a>
</div>
#}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGOUT }}">Logout</a>
</div>
{% else %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGIN }}">Login</a>
</div>
{% endif %}
</div>
<!-- Body -->
<div id="{{ model.ID_PAGE_BODY }}">
{% block page_body %}{% endblock %}
</div>
<!-- Footer -->
<div class="footer">
<h4>Copyright &copy; {{ model.NAME_COMPANY }}. <a href="{{ url_for('routes_legal.license') }}" alt="License" aria-label="License">All rights reserved.</a></h4>
<h5>Company number 13587499</h5>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}"><p><a href="{{ url_for('routes_legal.accessibility_statement') }}" alt="Accessibility statement" aria-label="Accessibility statement">Accessibility statement</a></p></div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_COLUMN }}"><p><a href="{{ url_for('routes_legal.privacy_policy') }}" alt="Privacy notice" aria-label="Privacy notice">Privacy notice</a></p></div>
</div>
</div>
<script src="{{ url_for('static', filename='dist/js/main.bundle.js') }}"></script>
</body>
</html>

View File

@@ -0,0 +1,20 @@
<!-- v2a -->
{% extends 'layouts/layout.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/core_home.bundle.css') }}">
<div class="home-hero">
<h2 class="home-hero-title">Dog Training!</h2>
{% if not model.user.get_is_logged_in() %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGIN }} {{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Login</a>
</div>
{% elif True or model.user.can_admin_dog %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_DOG_HOME }} {{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Dog Home</a>
</div>
{% endif %}
</div>
{% endblock %}

View File

@@ -1,119 +0,0 @@
<!-- v2a -->
{% extends 'layouts/layout.html' %}
{% block page_head %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/core_home.bundle.css') }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css">
{% endblock %}
{% block page_nav_links %}
<a href="#services">Services</a>
<a href="#testimonial">Testimonial</a>
<a href="#pricing">Pricing</a>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Contact Us</a>
{% endblock %}
{% block page_body %}
<section class="hero">
<div class="container">
<div class="hero-content" data-aos="fade-up">
<h1>Transform Your Business with Modern ERP Solutions</h1>
<p>UK-based ERPNext specialist providing integrated ERP and e-commerce solutions. 5+ years experience implementing systems for builders merchants and automotive companies.</p>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Book Consultation</a>
</div>
</div>
</section>
<section id="services" class="services">
<div class="container">
<h2 class="section-title text-center">Our Services</h2>
<p class="section-subtitle text-center">Comprehensive ERP solutions tailored to your business needs</p>
<div class="services-grid">
<div class="service-card" data-aos="fade-up" data-aos-delay="100">
<h3>Implementation Services</h3>
<p>Full ERPNext implementation including setup, configuration, and training. We ensure a smooth transition to your new ERP system.</p>
</div>
<div class="service-card" data-aos="fade-up" data-aos-delay="200">
<h3>Integration & Migration</h3>
<p>Seamlessly migrate your existing data and integrate ERPNext with your current business applications and workflows.</p>
</div>
<div class="service-card" data-aos="fade-up" data-aos-delay="300">
<h3>Hosting Services</h3>
<p>Secure, reliable cloud hosting with regular backups and maintenance to keep your ERP system running smoothly.</p>
</div>
<div class="service-card" data-aos="fade-up" data-aos-delay="400">
<h3>Custom Extensions</h3>
<p>Tailored app development and customizations to extend ERPNext functionality according to your specific requirements.</p>
</div>
</div>
</div>
</section>
{#
<section id="testimonial" class="testimonial">
<div class="container">
<h2 class="section-title text-center">Client Success Story</h2>
<p class="section-subtitle text-center">See how we've helped other businesses succeed</p>
<div class="testimonial-card" data-aos="fade-up">
<p>"The ERPNext implementation has revolutionized our operations. The integrated e-commerce system has streamlined our entire sales process, and the team's support has been exceptional throughout our journey."</p>
<p><strong>- 4 Shires Builders Merchants</strong></p>
</div>
</div>
</section>
#}
<section id="pricing" class="pricing">
<div class="container">
<h2 class="section-title text-center">Simple, Transparent Pricing</h2>
<p class="section-subtitle text-center">Enterprise-grade solutions at SMB-friendly prices</p>
<div class="pricing-card" data-aos="fade-up">
<h3>Implementation</h3>
<div class="price">From £10,000</div>
<p>One-time setup fee based on business size</p>
<ul style="list-style: none; margin: 2rem 0;">
<li>✓ Full ERP & e-commerce setup</li>
<li>✓ Product catalogue configuration</li>
<li>✓ Staff training</li>
<li>✓ Data migration</li>
</ul>
<h3>Monthly Support & Hosting</h3>
<div class="price">£200</div>
<p>12-month minimum term, billed annually at £2,400</p>
<ul style="list-style: none; margin: 2rem 0;">
<li>✓ Unlimited support tickets</li>
<li>✓ Cloud hosting (99.9% uptime)</li>
<li>✓ Regular maintenance and system updates</li>
</ul>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Get Custom Quote</a>
</div>
</div>
</section>
<section class="cta">
<div class="container">
<h2 class="section-title">Ready to Transform Your Business?</h2>
<p class="section-subtitle">Contact us today to discuss your ERP needs</p>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_LIGHT }}">Book Consultation</a>
</div>
</section>
<!-- CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
AOS.init({
duration: 1000,
once: true
});
});
</script>
{% endblock %}

View File

@@ -0,0 +1,77 @@
{% extends 'layouts/layout.html' %}
{% block page_head %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/core_contact.bundle.css') }}">
{% endblock %}
{% block page_nav_links %}
{#
<a href="#contact-form">Contact Form</a>
<a href="#contact-details">Contact Details</a>
#}
{% endblock %}
{% block page_body %}
{% set form = model.form_contact %}
<section class="contact-section">
<div class="contact-form">
<h1>Contact Us</h1>
<p>Please fill in the form below and we'll get back to you as soon as possible.</p>
<form id="{{ model.ID_CONTACT_FORM }}" method="POST" action="{{ model.HASH_POST_CONTACT_FORM }}">
{{ form.csrf_token }}
<div class="form-grid">
<label class="form-label" for="{{ form.email.id }}">{{ form.email.label.text }} *</label>
<div>
{{ form.email(class="form-input", required=True) }}
</div>
<label class="form-label" for="{{ form.contact_name.id }}">{{ form.contact_name.label.text }} *</label>
<div>
{{ form.contact_name(class="form-input", required=True) }}
</div>
<label class="form-label" for="{{ form.company_name.id }}">{{ form.company_name.label.text }} *</label>
<div>
{{ form.company_name(class="form-input", required=True) }}
</div>
<label class="form-label" for="{{ form.message.id }}">{{ form.message.label.text }} *</label>
<div>
{{ form.message(class="form-input", required=True) }}
</div>
</div>
<div class="{{ model.FLAG_CONTAINER_CHECKBOX }} {{ model.FLAG_RECEIVE_MARKETING }} marketing-consent">
{{ model.form_contact.receive_marketing() }}
{{ model.form_contact.receive_marketing.label }}
</div>
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_CAPTCHA }}">
<div>
{{ form.altcha.label }}
<altcha-widget
class="altcha-widget"
challengeurl="{{ model.HASH_GET_ALTCHA_CHALLENGE }}"
auto="onload"
id="{{ form.altcha.id }}"
name="{{ form.altcha.name }}"
></altcha-widget>
</div>
<p>This CAPTCHA mechanism is fully GDPR-compliant with no cookies, no fingerprinting, no tracking, and runs in the background so you don't need to do anything!</p>
</div>
<div class="{{ model.FLAG_CONTAINER_INPUT }}">
{{ model.form_contact.submit() }}
</div>
</form>
<div class="data-notice">
<h3>How we use your information</h3>
<p>If you opt in to marketing communications, we will also use your email address to send you updates about our services, ERPNext features, and relevant industry news. You can unsubscribe from these communications at any time.</p>
<p>We retain contact form submissions for customer service purposes and retain marketing consent records as required by law. For details about how long we keep your information, please see our <a href="{{ model.HASH_PAGE_DATA_RETENTION_SCHEDULE }}">data retention schedule</a>.</p>
<p>For full details about how we handle your personal data, please read our <a href="{{ model.HASH_PAGE_PRIVACY_POLICY }}">Privacy Policy</a>.</p>
</div>
</div>
</section>
{% endblock %}

View File

@@ -0,0 +1,22 @@
{% extends 'layouts/layout.html' %}
{% block page_head %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/core_contact.bundle.css') }}">
{% endblock %}
{% block page_nav_links %}
{% endblock %}
{% block page_body %}
{% set form = model.form_contact %}
<section class="contact-section">
<div class="contact-form">
<h1>Message Received</h1>
<p>Thanks for contacting us! We've received your message and will respond within 48 hours.</p>
</div>
</section>
<script>
</script>
{% endblock %}

View File

@@ -2,19 +2,240 @@
{% extends 'layouts/layout.html' %}
{% block page_body %}
{% block page_head %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/core_home.bundle.css') }}">
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.css"> -->
{% endblock %}
<div class="home-hero">
<h2 class="home-hero-title">Dog Training!</h2>
{% if not model.user.get_is_logged_in() %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_USER_LOGIN }} {{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Login</a>
{% block page_nav_links %}
<a href="#{{ model.FLAG_PROBLEM }}">Problem</a>
<a href="#{{ model.FLAG_SOLUTION }}">Solution</a>
<a href="#{{ model.FLAG_BENEFITS }}">Benefits</a>
<a href="#{{ model.FLAG_SOCIAL_PROOF }}">Social Proof</a>
<!-- <a href="#{{ model.FLAG_EARLY_ACCESS }}">Early Access</a> -->
<a href="#{{ model.FLAG_FEATURES }}">Features</a>
<a href="#{{ model.FLAG_FAQ }}">FAQs</a>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Contact Us</a>
{% endblock %}
{% block page_body %}
<section class="hero">
<div class="container">
<div class="hero-content" data-aos="fade-up">
<h1>Track Every Tail Wag of Progress</h1>
<p>The UK's first professional dog training management platform that transforms how you document, measure, and showcase training success!</p>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Get Early Access</a>
<!-- <a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Watch 2-Minute Demo</a> -->
</div>
{% elif True or model.user.can_admin_dog %}
<div class="{{ model.FLAG_CONTAINER }} {{ model.FLAG_ROW }}">
<a class="{{ model.FLAG_NAV_DOG_HOME }} {{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Dog Home</a>
</div>
</section>
<!--
<section id="{{ model.FLAG_PROBLEM_SOLUTION }}" class="{{ model.FLAG_PROBLEM_SOLUTION }}">
<div class="container">
<h2 class="section-title text-center">Finally, Software That Understands Dog Training</h2>
<p class="section-subtitle text-center"><strong>Problem Statement:</strong> Running a dog training business shouldn't mean drowning in paperwork. Between managing client schedules, tracking each dog's progress, sending updates to worried pet parents, and keeping your business profitable, there's barely time left for actual training.</p>
<p class="section-subtitle text-center"><strong>Solution Overview:</strong> Fetch Metrics was built specifically for dog trainers by people who understand your industry. Every feature is designed around how you actually work - from intake forms that capture behavioral quirks to progress reports that build client confidence.</p>
<p>Key features:</p>
<ul> < !-- style="list-style: none; margin: 2rem 0;"-- >
<li>✓ <strong>Client & Dog Management:</strong> Complete profiles with photos, medical notes, and behavioral history</li>
<li>✓ <strong>Session Tracking:</strong> Quick note-taking, homework assignments, and progress photos</li>
</ul>
</div>
</section>
-->
<section id="{{ model.FLAG_PROBLEM }}" class="{{ model.FLAG_PROBLEM }}">
<div class="container">
<h2 class="section-title text-center">Still Using Spreadsheets and Paper Notes?</h2>
<!--
<p class="section-subtitle text-center"><strong>Problem Statement:</strong> Running a dog training business shouldn't mean drowning in paperwork. Between managing client schedules, tracking each dog's progress, sending updates to worried pet parents, and keeping your business profitable, there's barely time left for actual training.</p>
<p class="section-subtitle text-center"><strong>Solution Overview:</strong> Fetch Metrics was built specifically for dog trainers by people who understand your industry. Every feature is designed around how you actually work - from intake forms that capture behavioral quirks to progress reports that build client confidence.</p>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_PROBLEM }}">
<p class="section-subtitle text-center">Pain Points:</p>
<ul> < !-- style="list-style: none; margin: 2rem 0;"-- >
<li>Spending 10+ hours per week on paperwork and scheduling</li>
<li>Losing client information in messy spreadsheets</li>
<li>Forgetting to follow up on training progress</li>
<li>Struggling to show clients their dog's improvement</li>
<li>Missing appointments and double-booking sessions</li>
<li>Difficulty tracking payments and outstanding invoices</li>
</ul>
<p>You became a dog trainer to work with animals and help families - not to be a data entry clerk. Yet successful trainers tell us they spend more time on administration than actual training.</p>
</div>
{% endif %}
</div>
-->
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_PROBLEM }}">
<p>You're not alone. Most UK dog trainers spend hours each week juggling multiple systems, trying to remember which dog knows which commands, and struggling to show clients real progress.</p>
<p>What if you could track every command, every session, and every breakthrough in one simple system?</p>
</div>
</div>
</section>
<section id="{{ model.FLAG_SOLUTION }}" class="{{ model.FLAG_SOLUTION }}">
<div class="container">
<h2 class="section-title text-center">Professional Progress Tracking Made Simple</h2>
<!--
<p class="section-subtitle text-center"><strong>Problem Statement:</strong> Running a dog training business shouldn't mean drowning in paperwork. Between managing client schedules, tracking each dog's progress, sending updates to worried pet parents, and keeping your business profitable, there's barely time left for actual training.</p>
<p class="section-subtitle text-center"><strong>Solution Overview:</strong> Fetch Metrics was built specifically for dog trainers by people who understand your industry. Every feature is designed around how you actually work - from intake forms that capture behavioral quirks to progress reports that build client confidence.</p>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_SOLUTION }}">
<p class="section-subtitle text-center">Teaser Benefits:</p>
<ul>
<li><strong>Professional Client Management:</strong> Never lose track of a client or their dog's progress again</li>
<li><strong>Effortless Scheduling:</strong> Appointments that actually sync with your life</li>
<li><strong>Progress That Speaks:</strong> Show clients exactly how their dog is improving</li>
<li><strong>Smart Business Tools:</strong> Everything you need to run a professional training business</li>
<li><strong>Happy Dog Owners:</strong> Give clients access to their dog's training journey</li>
</ul>
<p><strong>Note:</strong> Full feature details available to beta users only</p>
</div>
-->
<p class="section-subtitle text-center">Finally, a system built specifically for how dog trainers actually work. Document command mastery, track skill progression, and generate professional progress reports that wow your clients.</p>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_SOLUTION }}">
<ul>
<li><strong>Command Performance Tracking:</strong> Monitor success rates for every command, from basic sit-stay to advanced behaviours</li>
<li><strong>Skill Level Assessment:</strong> Automatically track progression through training levels with detailed performance metrics</li>
<li><strong>Professional Progress Reports:</strong> Generate impressive client reports that showcase real, measurable improvement</li>
<li><strong>Session History:</strong> Never lose track of what you worked on last week or which exercises need reinforcement</li>
</ul>
</div>
</div>
</section>
<section id="{{ model.FLAG_BENEFITS }}" class="{{ model.FLAG_BENEFITS }}">
<div class="container">
<h2 class="section-title text-center">More Than Just Software - It's Your Training Partner</h2>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_BENEFITS }}">
<p class="section-subtitle text-center">For Your Business:</p>
<ul>
<li>✓ Reduce admin time by 70% with automated progress tracking</li>
<li>✓ Increase client retention with professional progress reports</li>
<li>✓ Stand out from competitors with data-driven training insights</li>
</ul>
<p class="section-subtitle text-center">For Your Clients:</p>
<ul>
<li>✓ See their dog's journey from first sit to graduation</li>
<li>✓ Understand exactly what their dog has mastered</li>
<li>✓ Feel confident in your professional approach</li>
</ul>
<p class="section-subtitle text-center">For Your Dogs:</p>
<ul>
<li>✓ Consistent training approach across all sessions</li>
<li>✓ Targeted practice on areas that need work</li>
<li>✓ Faster progression through structured tracking</li>
</ul>
</div>
</div>
</section>
<section id="{{ model.FLAG_SOCIAL_PROOF }}" class="{{ model.FLAG_SOCIAL_PROOF }}">
<div class="container">
<h2 class="section-title text-center">Join Progressive UK Trainers Already Transforming Their Business</h2>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_SOCIAL_PROOF }}">
<p class="section-subtitle text-center">
"I wish I'd had this 5 years ago. What used to take me a full Sunday afternoon now takes 20 minutes. My clients love seeing their dog's progress, and I actually enjoy the business side now."
<ul>
<li>Tierney G., Dog Trainer, Rugby</li>
</ul>
</p>
<!--
<p class="section-subtitle text-center">Stats:</p>
<ul>
<li>✓ 30+ Professional Trainers in Beta</li>
<li>✓ 500+ Dogs Successfully Tracked</li>
<li>✓ 10 Hours Saved Per Week (Average)</li>
<li>✓ 40% Increase in Client Retention</li>
</ul>
-->
</div>
</div>
</section>
<section id="{{ model.FLAG_FEATURES }}" class="{{ model.FLAG_FEATURES }}">
<div class="container">
<h2 class="section-title text-center">Everything You Need to Run a Modern Training Business</h2>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_FEATURES }}">
<ul>
<li>✓ Detailed command performance tracking</li>
<li>✓ Multi-level skill progression monitoring</li>
<li>✓ Professional progress report generation</li>
<li>✓ Client and dog profile management</li>
<li>✓ Session planning and note-taking</li>
<li>✓ Mobile-friendly for field use</li>
<li>✓ Secure cloud-based storage</li>
<li>✓ GDPR compliant</li>
</ul>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Reserve Your Spot Now</a>
<p>30-day money-back guarantee • Cancel anytime • No setup fees</p>
</div>
</div>
</section>
<!--
<section id="{{ model.FLAG_EARLY_ACCESS }}" class="{{ model.FLAG_EARLY_ACCESS }}">
<div class="container">
<h2 class="section-title text-center">Be Among the First to Experience the Future of Dog Training Business Management</h2>
<p class="section-subtitle text-center">Limited early access launching Autumn 2025. Join successful trainers who are already seeing results.</p>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_EARLY_ACCESS }}">
<p class="section-subtitle text-center">What You Get:</p>
<ul>
<li>✓ First access when we launch</li>
<li>✓ Exclusive beta features</li>
<li>✓ Direct input on development</li>
<li>✓ Founding member pricing (save 50% for life)</li>
<li>✓ Personal onboarding session</li>
</ul>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_PRIMARY }}">Reserve Your Spot Now</a>
<p class="section-subtitle text-center"><strong>Risk Reversal:</strong> 30-day money-back guarantee • Cancel anytime • No setup fees</p>
</div>
</div>
</section>
-->
<section class="{{ model.FLAG_CTA_1 }}">
<div class="container">
<h2 class="section-title">Ready to Revolutionise Your Training Business?</h2>
<p class="section-subtitle text-center">Join the waitlist for early access to the UK's most comprehensive dog training management platform.</p>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_LIGHT }}">Get Early Access Today</a>
<p>30-day money-back guarantee • Cancel anytime • No setup fees</p>
</div>
</section>
<section id="{{ model.FLAG_FAQ }}" class="{{ model.FLAG_FAQ }}">
<div class="container">
<h2 class="section-title text-center">FAQs</h2>
<div class="{{ model.FLAG_CARD }} {{ model.FLAG_FAQ }}">
<ul>
<li><strong>Q: Is this just another scheduling app?:</strong> A: No, we're focused on what matters most - tracking and showcasing training progress. While we include scheduling features, our core strength is detailed command performance tracking and professional reporting.</li>
<li><strong>Q: Do my clients need their own accounts?:</strong> A: That's up to you! You can generate reports to share, or give clients access to view their dog's progress directly.</li>
<li><strong>Q: How detailed is the progress tracking?:</strong> A: As detailed as you need. Track success rates, duration, distractions, environments, and more for every command and behaviour.</li>
<li><strong>Q: Will this work for my training style?:</strong> A: Built by trainers, for trainers. Whether you use positive reinforcement, balanced training, or specialised techniques, our flexible system adapts to you.</li>
</ul>
</div>
</div>
</section>
<section class="{{ model.FLAG_CTA_2 }}">
<div class="container">
<h2 class="section-title">Stop Losing Track of Training Progress</h2>
<p class="section-subtitle text-center">Your expertise deserves professional tools. Join innovative UK trainers who are already transforming how they track, measure, and showcase training success.</p>
<a href="{{ model.HASH_PAGE_CONTACT }}" class="{{ model.FLAG_BUTTON }} {{ model.FLAG_BUTTON_LIGHT }}">Join the Waitlist</a>
<p>Enter your email for updates and exclusive early access</p>
</div>
</section>
<!-- CDN -- >
<script src="https://cdnjs.cloudflare.com/ajax/libs/aos/2.3.4/aos.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
AOS.init({
duration: 1000,
once: true
});
});
</script>
-->
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_assessment.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_assessments.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_button_icons.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_command_button_links.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_command_categories.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_commands.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_dog_command_links.bundle.css') }}">

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block title %}{{ model.title }}{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends 'layouts/layout.html' %}
{% extends 'layouts/layout_dog.html' %}
{% block page_body %}
<link rel="stylesheet" href="{{ url_for('static', filename='dist/css/dog_locations.bundle.css') }}">