codymaster 7.0.2 → 7.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +64 -0
- package/README.md +38 -1
- package/dist/agent/codex.js +73 -21
- package/dist/agent-dispatch.js +63 -48
- package/dist/cli/commands/brain.js +18 -0
- package/dist/cli/commands/design-studio.js +1 -1
- package/dist/cm-suggest.js +3 -3
- package/dist/dashboard-project-summary.js +9 -0
- package/dist/dashboard.js +11 -5
- package/dist/execution-analyzer.js +9 -1
- package/dist/judge.js +16 -15
- package/dist/mcp-context-server.js +45 -23
- package/dist/mcp-skills-tools.js +2 -2
- package/dist/skill-chain.js +26 -3
- package/dist/skill-token-report.js +105 -0
- package/dist/sprint-pipeline.js +3 -3
- package/dist/ui/onboarding.js +3 -4
- package/dist/utils/design-taste.js +1 -1
- package/dist/utils/output-compress.js +8 -0
- package/package.json +2 -1
- package/public/dashboard/app.js +40 -13
- package/public/dashboard/index.html +190 -5
- package/public/dashboard/style.css +1 -1
- package/scripts/build-skills.mjs +36 -2
- package/scripts/mcp-bridge.js +41 -24
- package/scripts/pack-plugin.mjs +206 -0
- package/skills/cm-ads-tracker/SKILL.md +401 -0
- package/skills/cm-ads-tracker/evals/evals.json +55 -0
- package/skills/cm-ads-tracker/references/gtm-architecture.md +321 -0
- package/skills/cm-ads-tracker/references/industry-events.md +294 -0
- package/skills/cm-ads-tracker/references/platforms-api.md +238 -0
- package/skills/cm-ads-tracker/templates/capi-payload.md +79 -0
- package/skills/cm-ads-tracker/templates/datalayer-push.js +104 -0
- package/skills/cm-ads-tracker/templates/gtm-variables.js +56 -0
- package/skills/cm-auto-publisher/SKILL.md +81 -0
- package/skills/cm-booking-calendar/SKILL.md +521 -0
- package/skills/cm-booking-calendar/references/industry-patterns.md +527 -0
- package/skills/cm-booking-calendar/templates/booking-form.css +626 -0
- package/skills/cm-booking-calendar/templates/booking-form.html +477 -0
- package/skills/cm-booking-calendar/templates/calendar-engine.js +419 -0
- package/skills/cm-booking-calendar/templates/calendar-export.js +395 -0
- package/skills/cm-booking-calendar/templates/reminder-config.js +629 -0
- package/skills/cm-brainstorm-idea/SKILL.md +5 -5
- package/skills/cm-code-review/SKILL.md +2 -2
- package/skills/cm-codeintell/SKILL.md +47 -580
- package/skills/cm-codeintell/references/integration-workflows.md +23 -0
- package/skills/cm-codeintell/references/layer-0-skeleton.md +54 -0
- package/skills/cm-codeintell/references/layer-1-codegraph.md +58 -0
- package/skills/cm-codeintell/references/layer-2-architecture.md +31 -0
- package/skills/cm-codeintell/references/layer-3-context-builder.md +32 -0
- package/skills/cm-content-factory/.content-factory-state.json +132 -0
- package/skills/cm-content-factory/.git 2/logs/refs/heads/main +1 -0
- package/skills/cm-content-factory/.git 2/logs/refs/remotes/origin/main +1 -0
- package/skills/cm-content-factory/.git 2/objects/02/fb0956734b5f8ba3f918b7defd04a89cfe0076 +0 -0
- package/skills/cm-content-factory/.git 2/objects/08/1e129d75dc6feac6c02037272e6bd1a04e3324 +0 -0
- package/skills/cm-content-factory/.git 2/objects/0c/5393416f3c5e01c9a655a802bff0dd52f76f0a +0 -0
- package/skills/cm-content-factory/.git 2/objects/10/0b9be46978a946a77188f68be725098a122001 +0 -0
- package/skills/cm-content-factory/.git 2/objects/10/cf041167fc9843610eb3d90259ef3396315fdc +0 -0
- package/skills/cm-content-factory/.git 2/objects/12/5e19538dd6e1338ffe74f6c4c165b00435bf48 +0 -0
- package/skills/cm-content-factory/.git 2/objects/16/a9b9d0088d5c1347628b45a2620b479d8ad57c +0 -0
- package/skills/cm-content-factory/.git 2/objects/17/8c2a9ef93c33ae4eec9d58e82321f9229843a1 +0 -0
- package/skills/cm-content-factory/.git 2/objects/25/397ae41d09104d763bdcac2695209d85cdea89 +0 -0
- package/skills/cm-content-factory/.git 2/objects/2f/a836b7947f2d458e1f639788bf4bb0983a3305 +0 -0
- package/skills/cm-content-factory/.git 2/objects/3a/baaaf0a1c0909c0828335791557125fba911e0 +0 -0
- package/skills/cm-content-factory/.git 2/objects/42/2924221b81f5ce3c4e4daac9a64a24f9b01f9a +0 -0
- package/skills/cm-content-factory/.git 2/objects/42/ec0ce707447dc11446a34c9995fb8533801731 +0 -0
- package/skills/cm-content-factory/.git 2/objects/46/e43ce92866d56ce74b1d750db307cfe6154a15 +0 -0
- package/skills/cm-content-factory/.git 2/objects/48/5e41b633c63f55b8277bcc59f44f67681f671a +0 -0
- package/skills/cm-content-factory/.git 2/objects/49/49c596a3a89fa240642acd95dd3258e261eb09 +0 -0
- package/skills/cm-content-factory/.git 2/objects/50/9d42d8412ef8eaf7f7e138476bac2e4d10ce60 +0 -0
- package/skills/cm-content-factory/.git 2/objects/55/0c8c389d981b463ef849aeb792d8be3ccb6ec8 +0 -0
- package/skills/cm-content-factory/.git 2/objects/5d/82d3b18410cdda3ace3677436f0cb599dbe2d2 +0 -0
- package/skills/cm-content-factory/.git 2/objects/60/0617c58e871a38b33bf29e282d132bb3c381ad +0 -0
- package/skills/cm-content-factory/.git 2/objects/6a/8369a99c687b7245c92ffaf0e0f0dab9014504 +0 -0
- package/skills/cm-content-factory/.git 2/objects/79/bea435d40ab531c1aaf6be0432c6a5b7aaed21 +0 -0
- package/skills/cm-content-factory/.git 2/objects/7e/5ebd79251c2f14e4aceb86c74b6b6daae6b500 +0 -0
- package/skills/cm-content-factory/.git 2/objects/81/98a822a60178d6d5023ddb3e222cddf048742e +0 -0
- package/skills/cm-content-factory/.git 2/objects/86/0a0e1943dfe53411d2e499a1f16f46a96ef758 +0 -0
- package/skills/cm-content-factory/.git 2/objects/86/971fb55fdc081fdbae52376f0f13e57a4e9b04 +0 -0
- package/skills/cm-content-factory/.git 2/objects/88/b89dd609a0a03f8d4fe8bfde20d5b8fc1d326d +0 -0
- package/skills/cm-content-factory/.git 2/objects/90/8737edb6b7809e32cc01590b4e08ba42a9d40d +0 -0
- package/skills/cm-content-factory/.git 2/objects/93/d5a8a9a7d4fb7f11491cb596a6880528725118 +0 -0
- package/skills/cm-content-factory/.git 2/objects/98/46a2ab81d0c3b3eb00ef88fc56989aa7e9f316 +0 -0
- package/skills/cm-content-factory/.git 2/objects/9b/d8dd1e49cf274eaf9c555f3ab39dce7af5715e +0 -0
- package/skills/cm-content-factory/.git 2/objects/a1/13329fb0cec96ae78b222d33a24c3b5bc7fa1f +0 -0
- package/skills/cm-content-factory/.git 2/objects/a9/e6effe626e8a3aea3a8fc3364b492191c6e7d0 +0 -0
- package/skills/cm-content-factory/.git 2/objects/ad/6de7e48d9782cca9353d1ff0aa1aab7fe1df85 +0 -0
- package/skills/cm-content-factory/.git 2/objects/af/54ae316f771ff692e299ffcd8bf2f06b413b59 +0 -0
- package/skills/cm-content-factory/.git 2/objects/b0/4cb8b0b00dad633e731c1472161419e738d674 +0 -0
- package/skills/cm-content-factory/.git 2/objects/b3/094abb0b9ed46419b269e4a4e36a459690e3b0 +0 -0
- package/skills/cm-content-factory/.git 2/objects/b9/435c5d4baac2cfc5c83009ddd27b46b60db5f1 +0 -0
- package/skills/cm-content-factory/.git 2/objects/ba/5da17dbaec5ec2dcfdfd126aead518d1171d5c +0 -0
- package/skills/cm-content-factory/.git 2/objects/c0/bf58703aa258ba5dd63083bebaec8f223d844c +0 -0
- package/skills/cm-content-factory/.git 2/objects/c4/701a34edf1fc1bad58ccc57bd03f9426acb59a +0 -0
- package/skills/cm-content-factory/.git 2/objects/c7/5ccce9a4e5cc74d9b3174550cf6d993ca43638 +0 -0
- package/skills/cm-content-factory/.git 2/objects/c7/710d59b5a35b0f1f0a0399386643a0bd94c929 +0 -0
- package/skills/cm-content-factory/.git 2/objects/d1/fe58237112e953e5fec52da22cf38e08be3df9 +5 -0
- package/skills/cm-content-factory/.git 2/objects/d2/2bbe9fd2f74c95bc5583e803f5e435f1e2cd86 +0 -0
- package/skills/cm-content-factory/.git 2/objects/d7/e72852ea2bff74581dbf247d400120086229f4 +0 -0
- package/skills/cm-content-factory/.git 2/objects/d8/d4c3b5553e4fd72807e1d4b49ef07d9ef3ac35 +0 -0
- package/skills/cm-content-factory/.git 2/objects/dc/75050c2876f6a02ae2a53a3c886f395b622977 +0 -0
- package/skills/cm-content-factory/.git 2/objects/ee/e8546f95acec500187c08a28a8b9ee02db0dec +0 -0
- package/skills/cm-content-factory/.git 2/objects/ef/263c059208b416c2146434f10cb2b9fabcba16 +0 -0
- package/skills/cm-content-factory/.git 2/objects/f3/ae597e84d9a59b88acd21c99bde2eaf686d785 +0 -0
- package/skills/cm-content-factory/.git 2/objects/f3/f6f5673c821d3d8e76fa267a9e882e7a5387ea +0 -0
- package/skills/cm-content-factory/.git 2/objects/f9/6e6d0ad02624dd11d5848594d056caef7a5e8b +0 -0
- package/skills/cm-content-factory/.git 2/objects/ff/278988fc1edf0db3abcf18de795f4cc0b4f3e1 +0 -0
- package/skills/cm-content-factory/.git 2/refs/heads/main +1 -0
- package/skills/cm-content-factory/.git 2/refs/remotes/origin/main +1 -0
- package/skills/cm-content-factory/.pytest_cache 2/v/cache/nodeids +76 -0
- package/skills/cm-content-factory/.pytest_cache 2/v/cache/stepwise +1 -0
- package/skills/cm-content-factory/AGENTS.md +61 -0
- package/skills/cm-content-factory/CLAUDE.md +63 -0
- package/skills/cm-content-factory/CURSOR.md +43 -0
- package/skills/cm-content-factory/Content Factory.zip +0 -0
- package/skills/cm-content-factory/SKILL.md +416 -0
- package/skills/cm-content-factory/cf +313 -0
- package/skills/cm-content-factory/config.schema.json +397 -0
- package/skills/cm-content-factory/dashboard/app.js +556 -0
- package/skills/cm-content-factory/dashboard/index.html +397 -0
- package/skills/cm-content-factory/dashboard/style.css +1211 -0
- package/skills/cm-content-factory/examples/01-real-estate.config.json +146 -0
- package/skills/cm-content-factory/examples/02-personal-finance.config.json +146 -0
- package/skills/cm-content-factory/examples/03-health-wellness.config.json +147 -0
- package/skills/cm-content-factory/examples/04-saas-software.config.json +147 -0
- package/skills/cm-content-factory/examples/05-legal-services.config.json +147 -0
- package/skills/cm-content-factory/examples/06-insurance.config.json +146 -0
- package/skills/cm-content-factory/examples/07-ecommerce-dropship.config.json +146 -0
- package/skills/cm-content-factory/examples/08-online-education.config.json +147 -0
- package/skills/cm-content-factory/examples/09-crypto-defi.config.json +147 -0
- package/skills/cm-content-factory/examples/10-beauty-skincare.config.json +147 -0
- package/skills/cm-content-factory/examples/11-home-services.config.json +146 -0
- package/skills/cm-content-factory/examples/12-dental-clinic.config.json +147 -0
- package/skills/cm-content-factory/examples/13-pet-care.config.json +147 -0
- package/skills/cm-content-factory/examples/14-travel-hospitality.config.json +147 -0
- package/skills/cm-content-factory/examples/15-ai-automation.config.json +147 -0
- package/skills/cm-content-factory/examples/16-wedding-events.config.json +147 -0
- package/skills/cm-content-factory/examples/17-fitness-coaching.config.json +148 -0
- package/skills/cm-content-factory/examples/18-cybersecurity.config.json +147 -0
- package/skills/cm-content-factory/examples/19-food-restaurant.config.json +148 -0
- package/skills/cm-content-factory/examples/20-solar-energy.config.json +147 -0
- package/skills/cm-content-factory/examples/fitness-blog.config.json +116 -0
- package/skills/cm-content-factory/examples/tech-blog.config.json +107 -0
- package/skills/cm-content-factory/extensions/EXTENSION_GUIDE.md +72 -0
- package/skills/cm-content-factory/extensions/hooks.py +126 -0
- package/skills/cm-content-factory/extensions/openclaw_adapter.py +132 -0
- package/skills/cm-content-factory/landing/docs/content/changelog.md +36 -0
- package/skills/cm-content-factory/landing/docs/content/deployment.md +46 -0
- package/skills/cm-content-factory/landing/docs/content/execution-flow.md +67 -0
- package/skills/cm-content-factory/landing/docs/content/openspace.md +27 -0
- package/skills/cm-content-factory/landing/docs/content/openviking.md +33 -0
- package/skills/cm-content-factory/landing/docs/content/use-cases.md +26 -0
- package/skills/cm-content-factory/landing/docs/content/v5-intro.md +28 -0
- package/skills/cm-content-factory/landing/docs/index.html +240 -0
- package/skills/cm-content-factory/landing/index.html +680 -0
- package/skills/cm-content-factory/landing/script.js +143 -0
- package/skills/cm-content-factory/landing/style.css +1216 -0
- package/skills/cm-content-factory/landing/translations.js +508 -0
- package/skills/cm-content-factory/logs/events.jsonl +11 -0
- package/skills/cm-content-factory/profiles/_template.profile.json +231 -0
- package/skills/cm-content-factory/profiles/finance.profile.json +278 -0
- package/skills/cm-content-factory/profiles/legal.profile.json +263 -0
- package/skills/cm-content-factory/profiles/medical-research.profile.json +321 -0
- package/skills/cm-content-factory/profiles/technology.profile.json +275 -0
- package/skills/cm-content-factory/scripts/agent_dispatcher.py +266 -0
- package/skills/cm-content-factory/scripts/audit.py +106 -0
- package/skills/cm-content-factory/scripts/dashboard_server.py +225 -0
- package/skills/cm-content-factory/scripts/deploy.py +146 -0
- package/skills/cm-content-factory/scripts/extract.py +132 -0
- package/skills/cm-content-factory/scripts/landing_generator.py +459 -0
- package/skills/cm-content-factory/scripts/memory.py +521 -0
- package/skills/cm-content-factory/scripts/monetize.py +239 -0
- package/skills/cm-content-factory/scripts/pipeline.py +357 -0
- package/skills/cm-content-factory/scripts/plan.py +163 -0
- package/skills/cm-content-factory/scripts/publish.py +145 -0
- package/skills/cm-content-factory/scripts/research.py +337 -0
- package/skills/cm-content-factory/scripts/scaffold.py +464 -0
- package/skills/cm-content-factory/scripts/scoreboard.py +336 -0
- package/skills/cm-content-factory/scripts/seo.py +90 -0
- package/skills/cm-content-factory/scripts/state_manager.py +320 -0
- package/skills/cm-content-factory/scripts/token_manager.py +268 -0
- package/skills/cm-content-factory/scripts/validate.py +221 -0
- package/skills/cm-content-factory/scripts/wizard.py +329 -0
- package/skills/cm-content-factory/scripts/write.py +93 -0
- package/skills/cm-content-factory/sites/docs-site/src/assets/houston.webp +0 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/architecture.md +90 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/data-flow.md +54 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/deployment.md +38 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/index.md +65 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/lc-content-lifecycle.md +48 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/seq-write-mode.md +39 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/uj-first-batch.md +42 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-content-pipeline.md +51 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-learning-cycle.md +52 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/configuration.md +86 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/installation.md +80 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/intro.md +58 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/index.md +102 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/index.md +45 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/optimize-seo.md +29 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/scale-content-production.md +55 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/standardize-quality.md +29 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-cmo-huong.md +41 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-content-lead-khoa.md +40 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/index.md +56 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-content-manager-lan.md +46 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-seo-minh.md +45 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-writer-tu.md +45 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/content-pipeline.md +108 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/index.md +22 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/memory-system.md +52 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/seo-optimization.md +58 -0
- package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/troubleshooting-guide.md +92 -0
- package/skills/cm-content-factory/sites/docs-site/src/styles/custom.css +575 -0
- package/skills/cm-content-factory/tests/conftest.py +66 -0
- package/skills/cm-content-factory/tests/test_agent_dispatcher.py +125 -0
- package/skills/cm-content-factory/tests/test_memory.py +128 -0
- package/skills/cm-content-factory/tests/test_pipeline.py +107 -0
- package/skills/cm-content-factory/tests/test_research.py +56 -0
- package/skills/cm-content-factory/tests/test_state_manager.py +131 -0
- package/skills/cm-content-factory/tests/test_token_manager.py +110 -0
- package/skills/cm-content-factory/tests/test_wizard.py +121 -0
- package/skills/cm-continuity/SKILL.md +49 -480
- package/skills/cm-continuity/references/cm-uri-scheme.md +23 -0
- package/skills/cm-continuity/references/continuity-template.md +48 -0
- package/skills/cm-continuity/references/mcp-context-server.md +27 -0
- package/skills/cm-continuity/references/memory-architecture.md +26 -0
- package/skills/cm-continuity/references/memory-audit.md +18 -0
- package/skills/cm-continuity/references/session-protocol.md +31 -0
- package/skills/cm-continuity/references/storage-formats.md +20 -0
- package/skills/cm-cro-methodology/SKILL.md +290 -0
- package/skills/cm-cro-methodology/references/COPYWRITING.md +178 -0
- package/skills/cm-cro-methodology/references/OBJECTIONS.md +135 -0
- package/skills/cm-cro-methodology/references/PERSUASION.md +158 -0
- package/skills/cm-cro-methodology/references/RESEARCH.md +220 -0
- package/skills/cm-cro-methodology/references/funnel-analysis.md +365 -0
- package/skills/cm-cro-methodology/references/testing-methodology.md +330 -0
- package/skills/cm-design-system/SKILL.md +5 -6
- package/skills/cm-execution/SKILL.md +61 -379
- package/skills/cm-execution/references/mode-a-batch.md +28 -0
- package/skills/cm-execution/references/mode-b-subagent.md +46 -0
- package/skills/cm-execution/references/mode-c-parallel.md +39 -0
- package/skills/cm-execution/references/mode-d-rarv.md +62 -0
- package/skills/cm-execution/references/mode-e-triz-parallel.md +53 -0
- package/skills/cm-execution/references/mode-f-party.md +61 -0
- package/skills/cm-execution/references/persona-dispatch.md +22 -0
- package/skills/cm-execution/references/security-rules.md +47 -0
- package/skills/cm-google-form/SKILL.md +266 -0
- package/skills/cm-google-form/templates/apps-script.js +55 -0
- package/skills/cm-google-form/templates/form-markup.html +110 -0
- package/skills/cm-google-form/templates/form-submit.js +201 -0
- package/skills/cm-google-form/templates/toast.css +152 -0
- package/skills/cm-growth-hacking/SKILL.md +282 -0
- package/skills/cm-growth-hacking/bottom-sheet-engine.md +261 -0
- package/skills/cm-growth-hacking/calendar-integration.md +264 -0
- package/skills/cm-growth-hacking/references/engagement-patterns.md +346 -0
- package/skills/cm-growth-hacking/templates/bottom-sheet.css +528 -0
- package/skills/cm-growth-hacking/templates/bottom-sheet.js +269 -0
- package/skills/cm-growth-hacking/templates/calendar-cta.js +213 -0
- package/skills/cm-growth-hacking/templates/tracking-events.js +211 -0
- package/skills/cm-growth-hacking/templates/trigger-manager.js +254 -0
- package/skills/cm-growth-hacking/tracking-events.md +246 -0
- package/skills/cm-growth-hacking/trigger-system.md +342 -0
- package/skills/cm-how-it-work/SKILL.md +8 -9
- package/skills/cm-identity-guard/SKILL.md +4 -4
- package/skills/cm-jtbd/SKILL.md +98 -0
- package/skills/cm-notebooklm/SKILL.md +156 -0
- package/skills/cm-notebooklm/references/command_reference.md +94 -0
- package/skills/cm-notebooklm/references/workflows.md +60 -0
- package/skills/cm-notebooklm/resources/knowledge_sources.md +106 -0
- package/skills/cm-notebooklm/scripts/brain-sync.sh +453 -0
- package/skills/cm-notebooklm/scripts/graduate_wisdom.py +101 -0
- package/skills/cm-planning/SKILL.md +3 -3
- package/skills/cm-project-bootstrap/SKILL.md +2 -2
- package/skills/cm-quality-gate/SKILL.md +1 -1
- package/skills/cm-readit/SKILL.md +289 -0
- package/skills/cm-readit/audio-player.md +206 -0
- package/skills/cm-readit/examples/blog-reader.js +352 -0
- package/skills/cm-readit/examples/voice-cro.js +390 -0
- package/skills/cm-readit/tts-engine.md +262 -0
- package/skills/cm-readit/ui-patterns.md +362 -0
- package/skills/cm-readit/voice-cro.md +223 -0
- package/skills/cm-safe-deploy/SKILL.md +80 -510
- package/skills/cm-safe-deploy/references/gate-0-5-security-scan.md +31 -0
- package/skills/cm-safe-deploy/references/gate-0-secret-hygiene.md +68 -0
- package/skills/cm-safe-deploy/references/gate-1-syntax.md +23 -0
- package/skills/cm-safe-deploy/references/gate-2-test-suite.md +28 -0
- package/skills/cm-safe-deploy/references/gate-3-i18n.md +19 -0
- package/skills/cm-safe-deploy/references/gate-4-5-build-dist.md +16 -0
- package/skills/cm-safe-deploy/references/gate-6-deploy-smoke.md +18 -0
- package/skills/cm-safe-deploy/references/rollback.md +17 -0
- package/skills/cm-safe-deploy/references/setup-new-project.md +20 -0
- package/skills/cm-skill-index/SKILL.md +15 -15
- package/skills/cm-start/SKILL.md +1 -1
- package/skills/cm-tdd/SKILL.md +51 -356
- package/skills/cm-tdd/references/bugfix-example.md +15 -0
- package/skills/cm-tdd/references/rationalizations.md +20 -0
- package/skills/cm-tdd/references/red-green-refactor.md +33 -0
- package/skills/cm-tdd/references/stuck-debugging.md +18 -0
- package/skills/cm-tdd/references/test-quality.md +19 -0
- package/skills/cm-ux-master/SKILL.md +368 -115
- package/skills/profiles/core.txt +1 -4
- package/skills/profiles/design.txt +1 -2
- package/skills/profiles/full.txt +10 -16
- package/skills/profiles/growth.txt +9 -9
- package/skills/profiles/top35.json +13 -13
- package/skills/cm-conductor-worktrees/SKILL.archive.md +0 -28
- package/skills/cm-conductor-worktrees/SKILL.md +0 -26
- package/skills/cm-dashboard/SKILL.archive.md +0 -15
- package/skills/cm-dashboard/SKILL.md +0 -26
- package/skills/cm-dashboard/ui/app.js +0 -1278
- package/skills/cm-dashboard/ui/index.html +0 -206
- package/skills/cm-dashboard/ui/style.css +0 -440
- package/skills/cm-design-studio/SKILL.archive.md +0 -34
- package/skills/cm-design-studio/SKILL.md +0 -26
- package/skills/cm-engineering-meta/SKILL.archive.md +0 -73
- package/skills/cm-engineering-meta/SKILL.md +0 -26
- package/skills/cm-git-worktrees/SKILL.archive.md +0 -157
- package/skills/cm-git-worktrees/SKILL.md +0 -26
- package/skills/cm-post-deploy-canary/SKILL.archive.md +0 -22
- package/skills/cm-post-deploy-canary/SKILL.md +0 -26
- package/skills/cm-qa-visual-cli/SKILL.archive.md +0 -22
- package/skills/cm-qa-visual-cli/SKILL.md +0 -26
- package/skills/cm-second-opinion-cli/SKILL.archive.md +0 -23
- package/skills/cm-second-opinion-cli/SKILL.md +0 -26
- package/skills/cm-secret-shield/SKILL.archive.md +0 -580
- package/skills/cm-secret-shield/SKILL.md +0 -26
- package/skills/cm-security-gate/SKILL.archive.md +0 -239
- package/skills/cm-security-gate/SKILL.md +0 -26
- package/skills/cm-skill-health/SKILL.archive.md +0 -83
- package/skills/cm-skill-health/SKILL.md +0 -26
- package/skills/cm-skill-mastery/SKILL.archive.md +0 -156
- package/skills/cm-skill-mastery/SKILL.md +0 -26
- package/skills/cm-skill-search/SKILL.archive.md +0 -49
- package/skills/cm-skill-search/SKILL.md +0 -26
- package/skills/cm-skill-share/SKILL.archive.md +0 -58
- package/skills/cm-skill-share/SKILL.md +0 -26
- package/skills/cm-test-gate/SKILL.archive.md +0 -245
- package/skills/cm-test-gate/SKILL.md +0 -26
- package/skills/cm-ui-preview/SKILL.archive.md +0 -153
- package/skills/cm-ui-preview/SKILL.md +0 -26
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Bottom Sheet Engine
|
|
2
|
+
|
|
3
|
+
> Core module cho mọi engagement UI. Modular, responsive, accessible.
|
|
4
|
+
> Một engine — nhiều content types.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🏗️ Architecture
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
BottomSheetEngine
|
|
12
|
+
├── create(config) → Build DOM + attach events
|
|
13
|
+
├── show() → Slide up animation
|
|
14
|
+
├── hide() → Slide down + cleanup
|
|
15
|
+
├── destroy() → Remove from DOM entirely
|
|
16
|
+
├── setContent(html) → Swap inner content dynamically
|
|
17
|
+
├── setSize(size) → Switch compact/standard/full
|
|
18
|
+
└── onDismiss(callback) → Hook for tracking/state
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 3 Size Variants
|
|
22
|
+
|
|
23
|
+
| Size | Height | Use Case |
|
|
24
|
+
|------|--------|----------|
|
|
25
|
+
| `compact` | ~120px | Simple CTA, chat buttons, promo banner |
|
|
26
|
+
| `standard` | ~320px | Booking form, lead capture, calendar CTA |
|
|
27
|
+
| `full` | ~80vh | Survey, multi-step form, detailed content |
|
|
28
|
+
|
|
29
|
+
### DOM Structure
|
|
30
|
+
|
|
31
|
+
```html
|
|
32
|
+
<!-- Backdrop (optional, for full-size sheets) -->
|
|
33
|
+
<div class="eng-backdrop" data-sheet-id="booking"></div>
|
|
34
|
+
|
|
35
|
+
<!-- Bottom Sheet -->
|
|
36
|
+
<div class="eng-sheet eng-sheet--standard" data-sheet-id="booking" role="dialog" aria-modal="true" aria-label="Đặt Lịch Khám">
|
|
37
|
+
<!-- Drag handle -->
|
|
38
|
+
<div class="eng-sheet__handle" aria-hidden="true">
|
|
39
|
+
<div class="eng-sheet__handle-bar"></div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- Close button -->
|
|
43
|
+
<button class="eng-sheet__close" aria-label="Đóng">✕</button>
|
|
44
|
+
|
|
45
|
+
<!-- Content area (swappable) -->
|
|
46
|
+
<div class="eng-sheet__content">
|
|
47
|
+
<!-- Dynamic content injected here -->
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## 🎨 Styling Principles
|
|
55
|
+
|
|
56
|
+
### Must-Have CSS Features
|
|
57
|
+
|
|
58
|
+
| Feature | Why |
|
|
59
|
+
|---------|-----|
|
|
60
|
+
| `position: fixed; bottom: 0` | Anchored to viewport bottom |
|
|
61
|
+
| `transform: translateY(100%)` → `translateY(0)` | Smooth slide-up animation |
|
|
62
|
+
| `backdrop-filter: blur(24px)` | Glassmorphism, premium feel |
|
|
63
|
+
| `border-radius: 20px 20px 0 0` | iOS-style rounded top corners |
|
|
64
|
+
| `padding-bottom: env(safe-area-inset-bottom)` | Safe area for notched devices |
|
|
65
|
+
| `z-index: 1100` | Above nav bars but below modals |
|
|
66
|
+
| Drag handle pseudo-element | Visual signal "this is draggable" |
|
|
67
|
+
|
|
68
|
+
### Animation Timing
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
/* Open: slightly bouncy, feels natural */
|
|
72
|
+
transition: transform 0.4s cubic-bezier(0.32, 0.72, 0, 1);
|
|
73
|
+
|
|
74
|
+
/* Close: quick, decisive */
|
|
75
|
+
transition: transform 0.25s cubic-bezier(0.4, 0, 1, 1);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Responsive Rules
|
|
79
|
+
|
|
80
|
+
| Viewport | Behavior |
|
|
81
|
+
|----------|----------|
|
|
82
|
+
| Mobile (< 768px) | Full-width, touch-optimized, swipe dismiss |
|
|
83
|
+
| Tablet (768-1024px) | Max-width 480px, centered |
|
|
84
|
+
| Desktop (> 1024px) | Max-width 480px, right-aligned or centered |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 👆 Touch Interactions
|
|
89
|
+
|
|
90
|
+
### Swipe-to-Dismiss
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
touchstart → record startY
|
|
94
|
+
touchmove → calculate deltaY
|
|
95
|
+
if deltaY > 0 → sheet follows finger (translateY)
|
|
96
|
+
if deltaY > threshold (80px) → dismiss
|
|
97
|
+
touchend → snap back or dismiss based on velocity
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Key Rules:**
|
|
101
|
+
- Only allow downward swipe (deltaY > 0)
|
|
102
|
+
- Apply `will-change: transform` during drag for perf
|
|
103
|
+
- Use velocity calculation: fast swipe = dismiss even if < 80px
|
|
104
|
+
- Add `touch-action: none` on the drag handle only
|
|
105
|
+
|
|
106
|
+
### Focus Trap (Accessibility)
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
When sheet opens:
|
|
110
|
+
1. Save currently focused element
|
|
111
|
+
2. Move focus to sheet
|
|
112
|
+
3. Trap Tab/Shift+Tab within sheet
|
|
113
|
+
4. On close: restore focus to saved element
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 📦 Content Type Patterns
|
|
119
|
+
|
|
120
|
+
### 1. Booking Form Content
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<div class="eng-sheet__content">
|
|
124
|
+
<div class="eng-content-booking">
|
|
125
|
+
<h3 class="eng-content__title">📅 Đặt Lịch Khám</h3>
|
|
126
|
+
<form data-form-type="booking" onsubmit="window.submitToGoogleSheet(event)">
|
|
127
|
+
<input type="hidden" name="url" value="">
|
|
128
|
+
<input type="text" name="name" placeholder="Họ tên" required>
|
|
129
|
+
<input type="tel" name="phone" placeholder="Số điện thoại" required>
|
|
130
|
+
<div class="eng-date-chips" id="dateChips"><!-- JS generated --></div>
|
|
131
|
+
<div class="eng-time-slots" id="timeSlots"><!-- JS generated --></div>
|
|
132
|
+
<select name="service"><!-- Industry-specific options --></select>
|
|
133
|
+
<textarea name="note" placeholder="Ghi chú (tùy chọn)"></textarea>
|
|
134
|
+
<button type="submit" class="eng-btn eng-btn--primary">Xác Nhận Đặt Lịch</button>
|
|
135
|
+
</form>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### 2. Calendar CTA Content (Post-Submit)
|
|
141
|
+
|
|
142
|
+
```html
|
|
143
|
+
<div class="eng-content-calendar">
|
|
144
|
+
<div class="eng-content__icon">✅</div>
|
|
145
|
+
<h3 class="eng-content__title">Đặt lịch thành công!</h3>
|
|
146
|
+
<p class="eng-content__subtitle">Thêm vào lịch để không quên nhé</p>
|
|
147
|
+
<div class="eng-calendar-buttons">
|
|
148
|
+
<button onclick="addToGoogleCal()" class="eng-btn eng-btn--gcal">
|
|
149
|
+
<img src="gcal-icon.svg" alt="" width="20"> Google Calendar
|
|
150
|
+
</button>
|
|
151
|
+
<button onclick="downloadICS()" class="eng-btn eng-btn--ics">
|
|
152
|
+
📥 Apple Calendar / Khác
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
<p class="eng-content__benefit">💡 Lịch sẽ tự nhắc bạn — hoàn toàn miễn phí</p>
|
|
156
|
+
</div>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### 3. Lead Capture Content
|
|
160
|
+
|
|
161
|
+
```html
|
|
162
|
+
<div class="eng-content-lead">
|
|
163
|
+
<div class="eng-content__icon">🎁</div>
|
|
164
|
+
<h3 class="eng-content__title">Nhận tài liệu miễn phí</h3>
|
|
165
|
+
<p class="eng-content__subtitle">Để lại SĐT, chúng tôi gửi ngay</p>
|
|
166
|
+
<form data-form-type="lead" onsubmit="window.submitToGoogleSheet(event)">
|
|
167
|
+
<input type="hidden" name="url" value="">
|
|
168
|
+
<input type="tel" name="phone" placeholder="Số điện thoại" required>
|
|
169
|
+
<button type="submit" class="eng-btn eng-btn--primary">Gửi Cho Tôi</button>
|
|
170
|
+
</form>
|
|
171
|
+
</div>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 4. Flash Sale Content
|
|
175
|
+
|
|
176
|
+
```html
|
|
177
|
+
<div class="eng-content-promo">
|
|
178
|
+
<div class="eng-content__icon">🔥</div>
|
|
179
|
+
<h3 class="eng-content__title">Ưu đãi đặc biệt!</h3>
|
|
180
|
+
<div class="eng-countdown" id="countdown">
|
|
181
|
+
<span class="eng-countdown__unit"><span id="hours">00</span>h</span>
|
|
182
|
+
<span class="eng-countdown__unit"><span id="minutes">00</span>m</span>
|
|
183
|
+
<span class="eng-countdown__unit"><span id="seconds">00</span>s</span>
|
|
184
|
+
</div>
|
|
185
|
+
<p class="eng-content__subtitle">Giảm 30% khi đặt lịch hôm nay</p>
|
|
186
|
+
<a href="#booking" class="eng-btn eng-btn--primary">Đặt Ngay →</a>
|
|
187
|
+
<button class="eng-btn eng-btn--outline" onclick="addDeadlineToCalendar()">
|
|
188
|
+
📅 Nhắc tôi trước khi hết hạn
|
|
189
|
+
</button>
|
|
190
|
+
</div>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### 5. Survey / Feedback Content
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<div class="eng-content-survey">
|
|
197
|
+
<h3 class="eng-content__title">⭐ Đánh giá trải nghiệm</h3>
|
|
198
|
+
<div class="eng-rating" id="starRating">
|
|
199
|
+
<button data-rating="1" aria-label="1 sao">⭐</button>
|
|
200
|
+
<button data-rating="2" aria-label="2 sao">⭐</button>
|
|
201
|
+
<button data-rating="3" aria-label="3 sao">⭐</button>
|
|
202
|
+
<button data-rating="4" aria-label="4 sao">⭐</button>
|
|
203
|
+
<button data-rating="5" aria-label="5 sao">⭐</button>
|
|
204
|
+
</div>
|
|
205
|
+
<textarea name="feedback" placeholder="Chia sẻ thêm (tùy chọn)"></textarea>
|
|
206
|
+
<button class="eng-btn eng-btn--primary" onclick="submitSurvey()">Gửi Đánh Giá</button>
|
|
207
|
+
</div>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### 6. Chat / Contact CTA
|
|
211
|
+
|
|
212
|
+
```html
|
|
213
|
+
<div class="eng-content-chat">
|
|
214
|
+
<p class="eng-content__title">💬 Cần tư vấn?</p>
|
|
215
|
+
<div class="eng-chat-buttons">
|
|
216
|
+
<a href="https://zalo.me/PHONE" class="eng-btn eng-btn--zalo">Zalo</a>
|
|
217
|
+
<a href="tel:PHONE" class="eng-btn eng-btn--phone">📞 Gọi ngay</a>
|
|
218
|
+
<a href="https://m.me/PAGE" class="eng-btn eng-btn--messenger">Messenger</a>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 🔄 Multi-Step Flow
|
|
226
|
+
|
|
227
|
+
For complex interactions (e.g., booking → success → calendar CTA):
|
|
228
|
+
|
|
229
|
+
```javascript
|
|
230
|
+
// Step 1: Show booking form
|
|
231
|
+
sheet.setContent(bookingFormHTML);
|
|
232
|
+
sheet.show();
|
|
233
|
+
|
|
234
|
+
// Step 2: On form success → swap to calendar CTA
|
|
235
|
+
onFormSuccess(() => {
|
|
236
|
+
sheet.setContent(calendarCTAHTML);
|
|
237
|
+
// Track transition
|
|
238
|
+
trackEngagement('cro_booking_submit', { service: formData.service });
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// Step 3: On calendar add → show thank you + close
|
|
242
|
+
onCalendarAdd(() => {
|
|
243
|
+
trackEngagement('cro_calendar_add', { type: 'gcal' });
|
|
244
|
+
sheet.hide();
|
|
245
|
+
showToast('success', 'Đã thêm vào lịch! 🎉');
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## ❌ Anti-Patterns
|
|
252
|
+
|
|
253
|
+
| ❌ Don't | ✅ Do |
|
|
254
|
+
|----------|------|
|
|
255
|
+
| Nest sheets inside sheets | One sheet at a time, swap content |
|
|
256
|
+
| Hardcode content | Use setContent() for flexibility |
|
|
257
|
+
| Forget backdrop for full sheets | Add backdrop + blur for full-size |
|
|
258
|
+
| Skip keyboard navigation | Trap Tab key, close on Escape |
|
|
259
|
+
| Ignore safe-area-inset | Always pad for notched phones |
|
|
260
|
+
| Use `overflow: hidden` on body | Use `overscroll-behavior: contain` on sheet |
|
|
261
|
+
| Animate with JS | Use CSS transitions + `requestAnimationFrame` |
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Calendar Integration
|
|
2
|
+
|
|
3
|
+
> Kế thừa từ `cm-booking-calendar` skill. Focus vào post-engagement calendar CTA.
|
|
4
|
+
> Google Calendar deep link + Apple Calendar ICS + smart device routing.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🎯 Purpose
|
|
9
|
+
|
|
10
|
+
Sau khi user hoàn thành một action trong bottom sheet (đặt lịch, đăng ký event, nhận promo), hiển thị **Calendar CTA** để:
|
|
11
|
+
|
|
12
|
+
1. **Giảm no-show 30-60%** — Calendar reminder thay SMS
|
|
13
|
+
2. **Tăng commitment 40%** — Micro-action = tâm lý cam kết
|
|
14
|
+
3. **Free reminder forever** — Không tốn SMS/ZNS
|
|
15
|
+
4. **Google Maps built-in** — Navigate 1 chạm
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 📱 Smart Device Routing
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
User clicks "Add to Calendar"
|
|
23
|
+
│
|
|
24
|
+
├─ iOS detected (iPhone/iPad)
|
|
25
|
+
│ └─ Download .ics file
|
|
26
|
+
│ └─ iOS auto-opens Apple Calendar
|
|
27
|
+
│
|
|
28
|
+
├─ Android detected
|
|
29
|
+
│ └─ Open Google Calendar deep link
|
|
30
|
+
│ └─ Pre-filled event in new tab
|
|
31
|
+
│
|
|
32
|
+
└─ Desktop
|
|
33
|
+
└─ Show both options
|
|
34
|
+
└─ "Google Calendar" + "Tải file lịch (.ics)"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Detection Logic
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
function detectDevice() {
|
|
41
|
+
const ua = navigator.userAgent;
|
|
42
|
+
if (/iPhone|iPad|iPod/.test(ua)) return 'ios';
|
|
43
|
+
if (/Android/.test(ua)) return 'android';
|
|
44
|
+
return 'desktop';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function addToCalendar(event, config) {
|
|
48
|
+
const device = detectDevice();
|
|
49
|
+
if (device === 'ios') {
|
|
50
|
+
downloadICS(event, config);
|
|
51
|
+
} else if (device === 'android') {
|
|
52
|
+
addToGoogleCal(event, config);
|
|
53
|
+
} else {
|
|
54
|
+
// Desktop: show both options
|
|
55
|
+
showCalendarOptions(event, config);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 📅 Google Calendar Deep Link
|
|
63
|
+
|
|
64
|
+
### URL Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
https://calendar.google.com/calendar/render?action=TEMPLATE
|
|
68
|
+
&text={title}
|
|
69
|
+
&dates={startISO}/{endISO}
|
|
70
|
+
&details={description}
|
|
71
|
+
&location={location}
|
|
72
|
+
&sf=true
|
|
73
|
+
&output=xml
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Building the URL
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
function buildGoogleCalUrl(event, config) {
|
|
80
|
+
const formatDate = (d) => d.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
|
|
81
|
+
|
|
82
|
+
const start = formatDate(new Date(event.date + 'T' + event.time));
|
|
83
|
+
const end = formatDate(new Date(new Date(event.date + 'T' + event.time).getTime() + 60 * 60 * 1000)); // +1h
|
|
84
|
+
|
|
85
|
+
const description = [
|
|
86
|
+
event.description || '',
|
|
87
|
+
'',
|
|
88
|
+
`📍 ${config.clinicName}`,
|
|
89
|
+
`📌 ${config.address}`,
|
|
90
|
+
`📞 ${config.phone}`,
|
|
91
|
+
config.mapsUrl ? `🗺️ ${config.mapsUrl}` : '',
|
|
92
|
+
'',
|
|
93
|
+
config.preparation ? `⚠️ Lưu ý: ${config.preparation}` : '',
|
|
94
|
+
].filter(Boolean).join('\n');
|
|
95
|
+
|
|
96
|
+
const params = new URLSearchParams({
|
|
97
|
+
action: 'TEMPLATE',
|
|
98
|
+
text: event.title || `${event.service} — ${config.clinicName}`,
|
|
99
|
+
dates: `${start}/${end}`,
|
|
100
|
+
details: description,
|
|
101
|
+
location: config.address || '',
|
|
102
|
+
sf: 'true',
|
|
103
|
+
output: 'xml',
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
return `https://calendar.google.com/calendar/render?${params.toString()}`;
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 📥 ICS File Generation (Apple Calendar + Others)
|
|
113
|
+
|
|
114
|
+
### RFC 5545 Format
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
function buildICSContent(event, config) {
|
|
118
|
+
const uid = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}@${window.location.hostname}`;
|
|
119
|
+
const formatICSDate = (d) => d.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
|
|
120
|
+
|
|
121
|
+
const start = new Date(event.date + 'T' + event.time);
|
|
122
|
+
const end = new Date(start.getTime() + 60 * 60 * 1000);
|
|
123
|
+
const now = new Date();
|
|
124
|
+
|
|
125
|
+
const description = [
|
|
126
|
+
event.description || event.service,
|
|
127
|
+
'',
|
|
128
|
+
`📍 ${config.clinicName}`,
|
|
129
|
+
`📌 ${config.address}`,
|
|
130
|
+
`📞 ${config.phone}`,
|
|
131
|
+
config.preparation ? `⚠️ ${config.preparation}` : '',
|
|
132
|
+
].filter(Boolean).join('\\n');
|
|
133
|
+
|
|
134
|
+
let ics = [
|
|
135
|
+
'BEGIN:VCALENDAR',
|
|
136
|
+
'VERSION:2.0',
|
|
137
|
+
'PRODID:-//CMGrowthHacking//Calendar//VI',
|
|
138
|
+
'CALSCALE:GREGORIAN',
|
|
139
|
+
'METHOD:PUBLISH',
|
|
140
|
+
'BEGIN:VEVENT',
|
|
141
|
+
`UID:${uid}`,
|
|
142
|
+
`DTSTAMP:${formatICSDate(now)}`,
|
|
143
|
+
`DTSTART:${formatICSDate(start)}`,
|
|
144
|
+
`DTEND:${formatICSDate(end)}`,
|
|
145
|
+
`SUMMARY:${event.title || event.service + ' — ' + config.clinicName}`,
|
|
146
|
+
`DESCRIPTION:${description}`,
|
|
147
|
+
`LOCATION:${config.address || ''}`,
|
|
148
|
+
config.mapsUrl ? `URL:${config.mapsUrl}` : '',
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
// Add reminders (VALARM)
|
|
152
|
+
const reminders = config.reminderMinutes || [1440, 120]; // 1 day + 2h
|
|
153
|
+
reminders.forEach(minutes => {
|
|
154
|
+
ics.push(
|
|
155
|
+
'BEGIN:VALARM',
|
|
156
|
+
'TRIGGER:-PT' + minutes + 'M',
|
|
157
|
+
'ACTION:DISPLAY',
|
|
158
|
+
`DESCRIPTION:${event.title || event.service} — ${getReminderText(minutes)}`,
|
|
159
|
+
'END:VALARM'
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
ics.push('END:VEVENT', 'END:VCALENDAR');
|
|
164
|
+
|
|
165
|
+
return ics.filter(Boolean).join('\r\n');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function getReminderText(minutes) {
|
|
169
|
+
if (minutes >= 1440) return `Nhắc trước ${minutes / 1440} ngày`;
|
|
170
|
+
if (minutes >= 60) return `Nhắc trước ${minutes / 60} giờ`;
|
|
171
|
+
return `Nhắc trước ${minutes} phút`;
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Download Trigger
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
function triggerICSDownload(content, filename) {
|
|
179
|
+
const blob = new Blob([content], { type: 'text/calendar;charset=utf-8' });
|
|
180
|
+
const url = URL.createObjectURL(blob);
|
|
181
|
+
const a = document.createElement('a');
|
|
182
|
+
a.href = url;
|
|
183
|
+
a.download = filename || 'appointment.ics';
|
|
184
|
+
document.body.appendChild(a);
|
|
185
|
+
a.click();
|
|
186
|
+
document.body.removeChild(a);
|
|
187
|
+
URL.revokeObjectURL(url);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 🗓️ Calendar CTA UI Pattern
|
|
194
|
+
|
|
195
|
+
After successful form submission, swap bottom sheet content to calendar CTA:
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
function showCalendarCTA(event, config) {
|
|
199
|
+
const device = detectDevice();
|
|
200
|
+
|
|
201
|
+
let buttonsHTML = '';
|
|
202
|
+
|
|
203
|
+
if (device === 'ios') {
|
|
204
|
+
buttonsHTML = `
|
|
205
|
+
<button onclick="downloadICS()" class="eng-btn eng-btn--primary eng-btn--full">
|
|
206
|
+
📥 Thêm vào Apple Calendar
|
|
207
|
+
</button>
|
|
208
|
+
`;
|
|
209
|
+
} else if (device === 'android') {
|
|
210
|
+
buttonsHTML = `
|
|
211
|
+
<button onclick="addToGoogleCal()" class="eng-btn eng-btn--primary eng-btn--full">
|
|
212
|
+
<img src="gcal-icon.svg" alt="" width="20"> Thêm vào Google Calendar
|
|
213
|
+
</button>
|
|
214
|
+
`;
|
|
215
|
+
} else {
|
|
216
|
+
buttonsHTML = `
|
|
217
|
+
<button onclick="addToGoogleCal()" class="eng-btn eng-btn--gcal">
|
|
218
|
+
<img src="gcal-icon.svg" alt="" width="20"> Google Calendar
|
|
219
|
+
</button>
|
|
220
|
+
<button onclick="downloadICS()" class="eng-btn eng-btn--ics">
|
|
221
|
+
📥 Tải file lịch (.ics)
|
|
222
|
+
</button>
|
|
223
|
+
`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return `
|
|
227
|
+
<div class="eng-content-calendar">
|
|
228
|
+
<div class="eng-content__icon">✅</div>
|
|
229
|
+
<h3 class="eng-content__title">Đặt lịch thành công!</h3>
|
|
230
|
+
<p class="eng-content__subtitle">Thêm vào lịch để không quên nhé</p>
|
|
231
|
+
<div class="eng-calendar-buttons">${buttonsHTML}</div>
|
|
232
|
+
<p class="eng-content__benefit">
|
|
233
|
+
💡 Lịch sẽ tự nhắc bạn trước ${config.reminderMinutes[0] / 60}h — hoàn toàn miễn phí
|
|
234
|
+
</p>
|
|
235
|
+
</div>
|
|
236
|
+
`;
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## ⚙️ Configuration Defaults
|
|
243
|
+
|
|
244
|
+
```javascript
|
|
245
|
+
const CALENDAR_DEFAULTS = {
|
|
246
|
+
reminderMinutes: [1440, 120], // 1 day + 2 hours before
|
|
247
|
+
duration: 60, // event duration in minutes
|
|
248
|
+
timezone: 'Asia/Ho_Chi_Minh',
|
|
249
|
+
providers: ['gcal', 'ics'], // available calendar providers
|
|
250
|
+
};
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## 🔗 Skill Inheritance
|
|
256
|
+
|
|
257
|
+
| Feature | Source Skill | Reuse |
|
|
258
|
+
|---------|-------------|-------|
|
|
259
|
+
| `BookingCalendarEngine` class | `cm-booking-calendar/calendar-engine.js` | Full schedule generation for milestone-based industries |
|
|
260
|
+
| Industry reminder configs | `cm-booking-calendar/reminder-config.js` | 20 industry presets with preparation instructions |
|
|
261
|
+
| ICS export | `cm-booking-calendar/calendar-export.js` | Core ICS generation logic |
|
|
262
|
+
| GCal deep link | `cm-booking-calendar/calendar-export.js` | URL builder |
|
|
263
|
+
|
|
264
|
+
> 📌 **Rule:** If user needs full scheduling (milestones, follow-ups, multi-appointment), delegate to `cm-booking-calendar` skill. This module handles the **post-action calendar CTA** only.
|