From 5d5a721f4ba9458e81df642f444a4a4f4585a878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20de=20Ryckel?= Date: Tue, 19 May 2026 08:06:34 +0700 Subject: [PATCH] feat: Revamp demo and service pages with new content and structure (#2) - Updated the "Book a Demo" page with enhanced descriptions and a new layout. - Created a new "Book a Call" page to facilitate direct inquiries. - Introduced "Data Governance" and "Education Systems" pages with detailed offerings. - Added "Ifitwala Ed" page highlighting the flagship education ERP features. - Developed "ERP Implementation" service page outlining implementation steps. - Created a new services index page summarizing all service offerings. - Introduced a "SystemsMap" component to visually represent service workflows. --- README.md | 8 +- ifitwala_doc/api/build.py | 6 +- ifitwala_doc/api/site.py | 12 + ifitwala_doc/crm/api.py | 19 +- ifitwala_doc/crm/doctype/lead/lead.json | 28 ++- ifitwala_doc/hooks.py | 4 +- .../test_ifitwala_web_page.py | 10 +- ifitwala_doc/src/components/Hero.vue | 2 +- ifitwala_doc/www/index.html | 4 +- install_ifitwala_nginx.sh | 4 +- pyproject.toml | 2 +- src/components/LeadForm.vue | 223 +++++++++++------ src/components/site/HeroSection.astro | 14 +- src/components/site/SystemsMap.astro | 49 ++++ src/components/site/TrustLogosSection.astro | 2 +- src/layouts/SiteShell.astro | 27 ++- src/lib/siteClient.ts | 24 +- src/pages/[...page].astro | 26 +- src/pages/book-a-call.astro | 66 ++++++ src/pages/book-a-demo.astro | 93 ++++---- src/pages/data-governance.astro | 108 +++++++++ src/pages/education.astro | 108 +++++++++ src/pages/ifitwala-ed.astro | 126 ++++++++++ src/pages/index.astro | 224 ++++++++++++++---- src/pages/services/erp-implementation.astro | 112 +++++++++ src/pages/services/index.astro | 105 ++++++++ 26 files changed, 1203 insertions(+), 203 deletions(-) create mode 100644 src/components/site/SystemsMap.astro create mode 100644 src/pages/book-a-call.astro create mode 100644 src/pages/data-governance.astro create mode 100644 src/pages/education.astro create mode 100644 src/pages/ifitwala-ed.astro create mode 100644 src/pages/services/erp-implementation.astro create mode 100644 src/pages/services/index.astro diff --git a/README.md b/README.md index aa0affb..fdcd810 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ -### Ifitwala Doc +# Ifitwala Website and Documentation -Site and Docs for IFitwala Ed +Company website, product showcase, and documentation hub for Ifitwala. + +Ifitwala helps organizations grow better systems. We support ERP implementation, workflow improvement, and data governance for organizations that depend on accurate, sensitive, and operationally critical data. + +Our deepest expertise is in education: schools, education groups, LMS ecosystems, admissions, student records, reporting, safeguarding workflows, and privacy-aware data operations. Ifitwala Ed is our flagship education ERP, built from direct international-school experience. ### Installation diff --git a/ifitwala_doc/api/build.py b/ifitwala_doc/api/build.py index 5fffac0..1a7ef6a 100644 --- a/ifitwala_doc/api/build.py +++ b/ifitwala_doc/api/build.py @@ -250,9 +250,9 @@ def run_yarn(args): run_yarn("--version") _run("node --version", cwd=proj_root, env=env) - # 2) Build via package.json script (runs 'astro build' and other steps) + # 2) Build via package.json script (runs marketing assets and Astro pages) try: - run_yarn("build:docs") + run_yarn("build") except Exception as build_error: error_text = str(build_error).lower() # Astro can fail when stale compile artifacts are present in dist/.astro. @@ -272,7 +272,7 @@ def run_yarn(args): cwd="/", env=env, ) - run_yarn("build:docs") + run_yarn("build") # 3) Deploy built assets dist_root = os.path.join(proj_root, "dist") diff --git a/ifitwala_doc/api/site.py b/ifitwala_doc/api/site.py index 76b8d4e..3deedf1 100644 --- a/ifitwala_doc/api/site.py +++ b/ifitwala_doc/api/site.py @@ -55,11 +55,17 @@ class PagePayload(TypedDict, total=False): } BOOK_A_DEMO_PATH = "/book-a-demo/" +BOOK_A_CALL_PATH = "/book-a-call/" DEMO_LABEL_HINTS = { "demo", "book a demo", "see a live demo", } +CALL_LABEL_HINTS = { + "book a call", + "discuss your systems", + "talk to us", +} # ----------------------- @@ -71,6 +77,8 @@ def _normalize_demo_href(label: Any, href: Any) -> str: href_value = (href or "").strip() if not href_value: + if label_value in CALL_LABEL_HINTS: + return BOOK_A_CALL_PATH if label_value in DEMO_LABEL_HINTS: return BOOK_A_DEMO_PATH return href_value @@ -81,8 +89,12 @@ def _normalize_demo_href(label: Any, href: Any) -> str: except Exception: parsed_path = href_value.strip().rstrip("/") + if label_value in CALL_LABEL_HINTS: + return BOOK_A_CALL_PATH if label_value in DEMO_LABEL_HINTS: return BOOK_A_DEMO_PATH + if parsed_path in {"/call", "/book-call", "/book-a-call", "/contact"}: + return BOOK_A_CALL_PATH if parsed_path in {"/demo", "/book-demo", "/book-a-demo"}: return BOOK_A_DEMO_PATH diff --git a/ifitwala_doc/crm/api.py b/ifitwala_doc/crm/api.py index ee3b745..026f518 100644 --- a/ifitwala_doc/crm/api.py +++ b/ifitwala_doc/crm/api.py @@ -2,7 +2,20 @@ import frappe @frappe.whitelist(allow_guest=True) -def capture_lead(first_name, email, last_name=None, phone=None, school_name=None, job_title=None, source="Website", notes=None): +def capture_lead( + first_name, + email, + last_name=None, + phone=None, + organization=None, + organization_type=None, + school_name=None, + job_title=None, + interest_area=None, + current_system=None, + source="Website", + notes=None, +): lead = frappe.get_doc({ "doctype": "Lead", "first_name": first_name, @@ -10,8 +23,12 @@ def capture_lead(first_name, email, last_name=None, phone=None, school_name=None "email_id": email, # Standard field is email_id usually in Core, but since I created Custom Lead, use 'email' "email": email, # I defined 'email' in my JSON "phone": phone, + "organization": organization, + "organization_type": organization_type, "school_name": school_name, "job_title": job_title, + "interest_area": interest_area, + "current_system": current_system, "source": source, "notes": notes, "status": "New" diff --git a/ifitwala_doc/crm/doctype/lead/lead.json b/ifitwala_doc/crm/doctype/lead/lead.json index a53b7ae..2d11225 100644 --- a/ifitwala_doc/crm/doctype/lead/lead.json +++ b/ifitwala_doc/crm/doctype/lead/lead.json @@ -11,8 +11,12 @@ "email", "phone", "column_break_organization", + "organization", + "organization_type", "school_name", "job_title", + "interest_area", + "current_system", "section_status", "status", "source", @@ -54,6 +58,17 @@ "fieldname": "column_break_organization", "fieldtype": "Column Break" }, + { + "fieldname": "organization", + "fieldtype": "Data", + "label": "Organization" + }, + { + "fieldname": "organization_type", + "fieldtype": "Select", + "label": "Organization Type", + "options": "\nCompany\nSchool\nEducation group\nTraining organization\nNGO\nOther" + }, { "fieldname": "school_name", "fieldtype": "Data", @@ -64,6 +79,17 @@ "fieldtype": "Data", "label": "Job Title" }, + { + "fieldname": "interest_area", + "fieldtype": "Select", + "label": "Interest Area", + "options": "\nERP implementation\nIfitwala Ed\nData governance / privacy\nEducation systems\nNot sure yet" + }, + { + "fieldname": "current_system", + "fieldtype": "Data", + "label": "Current System" + }, { "fieldname": "section_status", "fieldtype": "Section Break", @@ -80,7 +106,7 @@ "fieldname": "source", "fieldtype": "Select", "label": "Source", - "options": "Website\nReferral\nLinkedIn\nInstagram\nEvent\nOutbound", + "options": "Website\nWebsite - Book a Call\nWebsite - Ifitwala Ed Demo\nReferral\nLinkedIn\nInstagram\nEvent\nOutbound", "default": "Website" }, { diff --git a/ifitwala_doc/hooks.py b/ifitwala_doc/hooks.py index 40dd8b6..f11c253 100644 --- a/ifitwala_doc/hooks.py +++ b/ifitwala_doc/hooks.py @@ -1,7 +1,7 @@ app_name = "ifitwala_doc" -app_title = "Ifitwala Doc" +app_title = "Ifitwala Website" app_publisher = "François de Ryckel" -app_description = "Site and Docs for IFitwala Ed" +app_description = "Company website, product showcase, and documentation hub for Ifitwala" app_email = "f.deryckel@gmail.com" app_license = "mit" diff --git a/ifitwala_doc/ifitwala_doc/doctype/ifitwala_web_page/test_ifitwala_web_page.py b/ifitwala_doc/ifitwala_doc/doctype/ifitwala_web_page/test_ifitwala_web_page.py index b6c4ffc..17833f6 100644 --- a/ifitwala_doc/ifitwala_doc/doctype/ifitwala_web_page/test_ifitwala_web_page.py +++ b/ifitwala_doc/ifitwala_doc/doctype/ifitwala_web_page/test_ifitwala_web_page.py @@ -108,12 +108,20 @@ def test_get_nav_returns_enabled_menu_items_in_order(self): "item_order": 20, "target_blank": 1, }, + { + "doctype": "Navigation Menu Item", + "label": "Book a Call", + "href": "/contact", + "item_order": 30, + "target_blank": 0, + }, ], } ).insert() items = site_api.get_nav("Header") - self.assertEqual([item["label"] for item in items], ["Docs", "Book a Demo"]) + self.assertEqual([item["label"] for item in items], ["Docs", "Book a Demo", "Book a Call"]) self.assertEqual(items[0]["href"], "/docs") self.assertEqual(items[1]["href"], "/book-a-demo/") self.assertEqual(items[1]["target_blank"], 1) + self.assertEqual(items[2]["href"], "/book-a-call/") diff --git a/ifitwala_doc/src/components/Hero.vue b/ifitwala_doc/src/components/Hero.vue index 4f468fa..0f89b35 100644 --- a/ifitwala_doc/src/components/Hero.vue +++ b/ifitwala_doc/src/components/Hero.vue @@ -4,7 +4,7 @@ import { Button } from 'frappe-ui'; const props = defineProps({ - title: { type: String, default: 'A campus where curiosity blooms.' }, + title: { type: String, default: 'Systems that help organizations grow.' }, subtitle: { type: String, default: '' }, actions: { type: Array, diff --git a/ifitwala_doc/www/index.html b/ifitwala_doc/www/index.html index aa3a668..ee2a5ca 100644 --- a/ifitwala_doc/www/index.html +++ b/ifitwala_doc/www/index.html @@ -2,7 +2,7 @@ - Ifitwala Ed — Loading + Ifitwala - Loading