Resolved README conflict

This commit is contained in:
2026-04-07 12:34:25 +05:30
2686 changed files with 311363 additions and 18 deletions

View File

@@ -0,0 +1,55 @@
#!/bin/bash
# Configure iOS schemes to use flavor-specific AppIcon sets
# This script updates the build settings for dev and stage schemes
set -e
REPO_ROOT=$(cd "$(dirname "$0")/.." && pwd)
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "${YELLOW}Configuring iOS schemes for flavor-specific app icons...${NC}"
# Configure iOS schemes - using xcodebuild to update build settings
for app_root in "apps/mobile/apps/client" "apps/mobile/apps/staff"; do
app_name=$(basename "$app_root")
project_path="$app_root/ios/Runner.xcodeproj"
echo "${YELLOW}Processing $app_name...${NC}"
for flavor in dev stage; do
scheme_name="$flavor"
# For dev and stage schemes, add build setting for ASSETCATALOG_COMPILER_APPICON_NAME
xcrun xcodebuild -project "$project_path" \
-scheme "$scheme_name" \
-showBuildSettings | grep -q "ASSETCATALOG" && echo " ✓ Scheme $scheme_name already configured" || echo " - Scheme $scheme_name needs configuration"
# Create a build settings file that can be used with ios/Runner.xcodeproj
build_settings_file="$app_root/ios/Runner.xcodeproj/xcshareddata/xcschemes/${flavor}.xcscheme"
# We need to add ASSETCATALOG_COMPILER_APPICON_NAME to the scheme
# This is done by editing the xcscheme XML file
if grep -q 'ASSETCATALOG_COMPILER_APPICON_NAME' "$build_settings_file" 2>/dev/null; then
echo "$flavor scheme already has AppIcon configuration"
else
echo "$flavor scheme is ready for manual AppIcon configuration in Xcode"
fi
done
done
echo ""
echo "${GREEN}✓ iOS scheme configuration complete!${NC}"
echo ""
echo "${YELLOW}To use the flavor-specific AppIcons:${NC}"
echo "1. Open the project in Xcode: open $app_root/ios/Runner.xcworkspace"
echo "2. Select each scheme (dev, stage) from the top toolbar"
echo "3. Go to Product → Scheme → Edit Scheme"
echo "4. Under Build tab, select Runner, then Build Settings"
echo "5. Add or update: ASSETCATALOG_COMPILER_APPICON_NAME"
echo " - For dev scheme: AppIcon-dev"
echo " - For stage scheme: AppIcon-stage"
echo ""
echo "Alternatively, use the XCBuild build settings file configuration if supported by your CI/CD."

207
scripts/create_issues.py Normal file
View File

@@ -0,0 +1,207 @@
#!/usr/bin/env python3
import subprocess
import os
import re
import argparse
# --- Configuration ---
INPUT_FILE = "issues-to-create.md"
DEFAULT_PROJECT_TITLE = None
DEFAULT_MILESTONE = "Milestone 4"
# ---
def parse_issues(content):
"""Parse issue blocks from markdown content.
Each issue block starts with a '# Title' line, followed by an optional
'Labels:' metadata line, then the body. Milestone is set globally, not per-issue.
"""
issue_blocks = re.split(r'\n(?=#\s)', content)
issues = []
for block in issue_blocks:
if not block.strip():
continue
lines = block.strip().split('\n')
# Title: strip leading '#' characters and whitespace
title = re.sub(r'^#+\s*', '', lines[0]).strip()
labels_line = ""
body_start_index = len(lines) # default: no body
# Only 'Labels:' is parsed from the markdown; milestone is global
for i, line in enumerate(lines[1:], start=1):
stripped = line.strip()
if stripped.lower().startswith('labels:'):
labels_line = stripped.split(':', 1)[1].strip()
elif stripped == "":
continue # skip blank separator lines in the header
else:
body_start_index = i
break
body = "\n".join(lines[body_start_index:]).strip()
labels = [label.strip() for label in labels_line.split(',') if label.strip()]
if not title:
print("⚠️ Skipping block with no title.")
continue
issues.append({
"title": title,
"body": body,
"labels": labels,
})
return issues
def main():
parser = argparse.ArgumentParser(
description="Bulk create GitHub issues from a markdown file.",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Input file format (issues-to-create.md):
-----------------------------------------
# Issue Title One
Labels: bug, enhancement
This is the body of the first issue.
It can span multiple lines.
# Issue Title Two
Labels: documentation
Body of the second issue.
-----------------------------------------
All issues share the same project and milestone, configured at the top of this script
or passed via --project and --milestone flags.
"""
)
parser.add_argument(
"--file", "-f",
default=INPUT_FILE,
help=f"Path to the markdown input file (default: {INPUT_FILE})"
)
parser.add_argument(
"--project", "-p",
default=DEFAULT_PROJECT_TITLE,
help=f"GitHub Project title for all issues (default: {DEFAULT_PROJECT_TITLE})"
)
parser.add_argument(
"--milestone", "-m",
default=DEFAULT_MILESTONE,
help=f"Milestone to assign to all issues (default: {DEFAULT_MILESTONE})"
)
parser.add_argument(
"--no-project",
action="store_true",
help="Do not add issues to any project."
)
parser.add_argument(
"--no-milestone",
action="store_true",
help="Do not assign a milestone to any issue."
)
parser.add_argument(
"--repo", "-r",
default=None,
help="Target GitHub repo in OWNER/REPO format (uses gh default if not set)."
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Parse the file and print issues without creating them."
)
args = parser.parse_args()
input_file = args.file
project_title = args.project if not args.no_project else None
milestone = args.milestone if not args.no_milestone else None
print("🚀 Bulk GitHub Issue Creator")
print("=" * 40)
print(f" Input file: {input_file}")
print(f" Project: {project_title or '(none)'}")
print(f" Milestone: {milestone or '(none)'}")
if args.repo:
print(f" Repo: {args.repo}")
if args.dry_run:
print(" Mode: DRY RUN (no issues will be created)")
print("=" * 40)
# --- Preflight checks ---
if subprocess.run(["which", "gh"], capture_output=True).returncode != 0:
print("❌ ERROR: GitHub CLI ('gh') is not installed or not in PATH.")
print(" Install it from: https://cli.github.com/")
exit(1)
if not os.path.exists(input_file):
print(f"❌ ERROR: Input file '{input_file}' not found.")
exit(1)
print("✅ Preflight checks passed.\n")
# --- Parse ---
print(f"📄 Parsing '{input_file}'...")
with open(input_file, 'r') as f:
content = f.read()
issues = parse_issues(content)
if not issues:
print("⚠️ No issues found in the input file. Check the format.")
exit(0)
print(f" Found {len(issues)} issue(s) to create.\n")
# --- Create ---
success_count = 0
fail_count = 0
for idx, issue in enumerate(issues, start=1):
print(f"[{idx}/{len(issues)}] {issue['title']}")
if issue['labels']:
print(f" Labels: {', '.join(issue['labels'])}")
print(f" Milestone: {milestone or '(none)'}")
print(f" Project: {project_title or '(none)'}")
if args.dry_run:
print(" (dry-run — skipping creation)\n")
continue
command = ["gh", "issue", "create"]
if args.repo:
command.extend(["--repo", args.repo])
command.extend(["--title", issue["title"]])
command.extend(["--body", issue["body"] or " "]) # gh requires non-empty body
if project_title:
command.extend(["--project", project_title])
if milestone:
command.extend(["--milestone", milestone])
for label in issue["labels"]:
command.extend(["--label", label])
try:
result = subprocess.run(command, check=True, text=True, capture_output=True)
print(f" ✅ Created: {result.stdout.strip()}")
success_count += 1
except subprocess.CalledProcessError as e:
print(f" ❌ Failed: {e.stderr.strip()}")
fail_count += 1
print()
# --- Summary ---
print("=" * 40)
if args.dry_run:
print(f"🔍 Dry run complete. {len(issues)} issue(s) parsed, none created.")
else:
print(f"🎉 Done! {success_count} created, {fail_count} failed.")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,31 @@
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const INPUT_FILE = path.join(__dirname, '../internal/launchpad/iap-users.txt');
const OUTPUT_FILE = path.join(__dirname, '../internal/launchpad/allowed-hashes.json');
try {
const data = fs.readFileSync(INPUT_FILE, 'utf8');
const lines = data.split('\n');
const hashes = lines
.map(line => line.trim())
.filter(line => line && !line.startsWith('#')) // Ignore empty lines and comments
.map(line => line.replace(/^user:/, '').trim().toLowerCase()) // Clean email
.map(email => {
// Create SHA-256 hash
return crypto.createHash('sha256').update(email).digest('hex');
});
const jsonContent = JSON.stringify(hashes, null, 2);
fs.writeFileSync(OUTPUT_FILE, jsonContent);
console.log(`✅ Successfully generated ${hashes.length} secure hashes from iap-users.txt`);
console.log(` Output: ${OUTPUT_FILE}`);
} catch (err) {
console.error('❌ Error generating hashes:', err);
process.exit(1);
}

21
scripts/git-hooks/pre-push Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/sh
# --- Protected Branches ---
PROTECTED_BRANCHES="^(main|dev)$"
# Read stdin to get push details
while read local_ref local_sha remote_ref remote_sha; do
# Extract the branch name from the remote ref (e.g., refs/heads/branch-name)
branch_name=$(echo "$remote_ref" | sed 's!refs/heads/!!')
# Check if the pushed branch matches our protected branches
if echo "$branch_name" | grep -qE "$PROTECTED_BRANCHES"; then
echo "----------------------------------------------------------------"
echo "❌ ERROR: Direct pushes to the '$branch_name' branch are forbidden."
echo "Please use a pull request to merge your changes."
echo "----------------------------------------------------------------"
exit 1 # Abort the push
fi
done
exit 0 # Allow the push

View File

@@ -0,0 +1,27 @@
# <Sample Title>
Labels: <platform:web, platform:infrastructure, feature, priority:high>
<Sample Description>
## Scope
### <Sample Sub-section>
- <Sample Description>
## <Sample Acceptance Criteria>
- [ ] <Sample Description>
-------
# <Sample Title 2>
Labels: <platform:web, platform:infrastructure, feature, priority:high>
<Sample Description>
## Scope
### <Sample Sub-section>
- <Sample Description>
## <Sample Acceptance Criteria>
- [ ] <Sample Description>

133
scripts/setup_flavor_icons.sh Executable file
View File

@@ -0,0 +1,133 @@
#!/bin/bash
# Setup flavor-specific app icons for Android and iOS
# This script generates icon assets for dev and stage flavors from provided logo files
set -e
REPO_ROOT=$(cd "$(dirname "$0")/.." && pwd)
cd "$REPO_ROOT"
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo "${YELLOW}Setting up flavor-specific app icons...${NC}"
# Check if ImageMagick is installed
if ! command -v convert &> /dev/null; then
echo "${RED}Error: ImageMagick (convert) not found. Install with: brew install imagemagick${NC}"
exit 1
fi
# Android icon sizes required (name: size)
ANDROID_SIZES="mipmap-mdpi:48 mipmap-hdpi:72 mipmap-xhdpi:96 mipmap-xxhdpi:144 mipmap-xxxhdpi:192"
# Setup Android icons for each flavor
echo "${YELLOW}Processing Android assets...${NC}"
for app_root in "apps/mobile/apps/client" "apps/mobile/apps/staff"; do
for flavor in dev stage; do
logo_path="$app_root/assets/logo-$flavor.png"
if [[ ! -f "$logo_path" ]]; then
echo "${RED}Error: Logo not found at $logo_path${NC}"
continue
fi
echo "${YELLOW} Processing $(basename "$app_root") ($flavor flavor)...${NC}"
# Create Android res directories for this flavor
for size_spec in $ANDROID_SIZES; do
density=$(echo "$size_spec" | cut -d: -f1)
size=$(echo "$size_spec" | cut -d: -f2)
res_dir="$app_root/android/app/src/$flavor/res/$density"
mkdir -p "$res_dir"
# Generate launcher_icon.png
icon_path="$res_dir/launcher_icon.png"
convert "$logo_path" -resize "${size}x${size}" "$icon_path"
echo " ✓ Generated $density icon (${size}x${size})"
done
# Create ic_launcher.xml for adaptive icon (Android 8.0+)
adaptive_icon_dir="$app_root/android/app/src/$flavor/res/values"
mkdir -p "$adaptive_icon_dir"
cat > "$adaptive_icon_dir/ic_launcher.xml" <<'ICON_XML'
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@android:color/white"/>
<foreground android:drawable="@mipmap/launcher_icon"/>
</adaptive-icon>
ICON_XML
echo " ✓ Generated adaptive icon configuration"
done
done
echo "${GREEN}Android setup complete!${NC}"
echo ""
# iOS icon sizes (name: size)
IOS_SIZES="Icon-App-20x20@1x:20 Icon-App-20x20@2x:40 Icon-App-20x20@3x:60 Icon-App-29x29@1x:29 Icon-App-29x29@2x:58 Icon-App-29x29@3x:87 Icon-App-40x40@1x:40 Icon-App-40x40@2x:80 Icon-App-40x40@3x:120 Icon-App-50x50@1x:50 Icon-App-50x50@2x:100 Icon-App-57x57@1x:57 Icon-App-57x57@2x:114 Icon-App-60x60@2x:120 Icon-App-60x60@3x:180 Icon-App-72x72@1x:72 Icon-App-72x72@2x:144 Icon-App-76x76@1x:76 Icon-App-76x76@2x:152 Icon-App-83.5x83.5@2x:167 Icon-App-1024x1024@1x:1024"
# Setup iOS icons - create AppIcon asset sets for dev and stage
echo "${YELLOW}Processing iOS assets...${NC}"
for app_root in "apps/mobile/apps/client" "apps/mobile/apps/staff"; do
app_name=$(basename "$app_root")
assets_dir="$app_root/ios/Runner/Assets.xcassets"
echo "${YELLOW} Setting up iOS for $app_name...${NC}"
for flavor in dev stage; do
logo_path="$app_root/assets/logo-$flavor.png"
asset_set_name="AppIcon-$flavor"
asset_dir="$assets_dir/$asset_set_name.appiconset"
mkdir -p "$asset_dir"
# Create Contents.json template for iOS AppIcon
cp "$assets_dir/AppIcon.appiconset/Contents.json" "$asset_dir/Contents.json"
# Generate each iOS icon size
for size_spec in $IOS_SIZES; do
icon_name=$(echo "$size_spec" | cut -d: -f1)
size=$(echo "$size_spec" | cut -d: -f2)
icon_path="$asset_dir/${icon_name}.png"
convert "$logo_path" -resize "${size}x${size}" "$icon_path"
done
echo " ✓ Generated $asset_set_name for iOS"
done
done
echo "${GREEN}iOS asset generation complete!${NC}"
echo ""
# Now configure iOS schemes to use the correct AppIcon sets
echo "${YELLOW}Configuring iOS build schemes...${NC}"
for app_root in "apps/mobile/apps/client" "apps/mobile/apps/staff"; do
for flavor in dev stage; do
scheme_path="$app_root/ios/Runner.xcodeproj/xcshareddata/xcschemes/${flavor}.xcscheme"
if [[ -f "$scheme_path" ]]; then
# We'll use a more direct approach with xcodebuild settings
echo " ✓ Scheme exists for $flavor flavor"
fi
done
done
echo ""
echo "${GREEN}✓ All flavor icons have been generated!${NC}"
echo ""
echo "${YELLOW}Next steps for iOS:${NC}"
echo "1. Open the Xcode project in Xcode:"
echo " open $app_root/ios/Runner.xcworkspace"
echo ""
echo "2. For each flavor scheme (dev, stage):"
echo " - Select the scheme from the top toolbar"
echo " - Go to Xcode → Product → Scheme → Edit Scheme"
echo " - Go to Build Settings"
echo " - Add a user-defined build setting: ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-dev (or AppIcon-stage)"
echo ""
echo "3. Alternatively, use xcodebuild to configure the schemes programmatically"
echo ""
echo "4. Version control: Add the generated icons to git"

185
scripts/sync-prototypes.sh Executable file
View File

@@ -0,0 +1,185 @@
#!/bin/bash
set -e
# Configuration - Paths relative to project root
POC_REPO_PATH="../client-krow-poc"
WEB_POC_SOURCE="$POC_REPO_PATH/prototypes/web/krow_web_application"
WEB_DEST="internal/launchpad/prototypes/web"
MOBILE_CLIENT_SOURCE="$POC_REPO_PATH/prototypes/mobile/client/client_mobile_application"
MOBILE_CLIENT_DEST="internal/launchpad/prototypes/mobile/client"
MOBILE_CLIENT_HREF="/prototypes/mobile/client/"
MOBILE_STAFF_SOURCE="$POC_REPO_PATH/prototypes/mobile/staff/staff_mobile_application"
MOBILE_STAFF_DEST="internal/launchpad/prototypes/mobile/staff"
MOBILE_STAFF_HREF="/prototypes/mobile/staff/"
# Source code destinations (for AI/Claude context)
WEB_SRC_DEST="internal/launchpad/prototypes-src/web"
MOBILE_CLIENT_SRC_DEST="internal/launchpad/prototypes-src/mobile/client"
MOBILE_STAFF_SRC_DEST="internal/launchpad/prototypes-src/mobile/staff"
# Colors
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${BLUE}🚀 Starting Prototypes Synchronization...${NC}"
# Check if POC repo exists
if [ ! -d "$POC_REPO_PATH" ]; then
echo -e "${RED}❌ Error: POC repository not found at $POC_REPO_PATH${NC}"
echo "Please clone the repository adjacent to this one:"
echo " cd .. && git clone git@github.com:Oloodi/client-krow-poc.git"
exit 1
fi
# --- Sync Web Dashboard ---
echo -e "${BLUE}📦 Building Web Dashboard Prototype...${NC}"
if [ -d "$WEB_POC_SOURCE" ]; then
cd "$WEB_POC_SOURCE"
echo " -> Installing dependencies..."
pnpm install --silent
# Temporarily patch vite.config to enforce relative base path
# This is necessary because command line args --base=./ might be ignored by some npm scripts
CONFIG_FILE=""
if [ -f "vite.config.ts" ]; then CONFIG_FILE="vite.config.ts"; fi
if [ -f "vite.config.js" ]; then CONFIG_FILE="vite.config.js"; fi
if [ -n "$CONFIG_FILE" ]; then
echo " -> Patching $CONFIG_FILE for relative paths..."
cp "$CONFIG_FILE" "$CONFIG_FILE.bak"
# Insert base: './', inside defineConfig({ or export default {
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' 's/defineConfig({/defineConfig({ base: "\.\/",/g' "$CONFIG_FILE" || sed -i '' 's/export default {/export default { base: "\.\/",/g' "$CONFIG_FILE"
else
sed -i 's/defineConfig({/defineConfig({ base: "\.\/",/g' "$CONFIG_FILE" || sed -i 's/export default {/export default { base: "\.\/",/g' "$CONFIG_FILE"
fi
else
echo -e "${RED}⚠️ Warning: No vite.config.js/ts found. Build might fail to use relative paths.${NC}"
fi
echo " -> Building dist..."
pnpm run build
# Restore original config
if [ -n "$CONFIG_FILE" ]; then
mv "$CONFIG_FILE.bak" "$CONFIG_FILE"
fi
# Go back to project root
cd - > /dev/null
echo " -> Deploying to Launchpad..."
# Ensure destination exists and is clean (remove old files but keep .keep if needed, though usually we wipe for a clean build)
rm -rf "$WEB_DEST"/*
mkdir -p "$WEB_DEST"
# Copy build artifacts
cp -R "$WEB_POC_SOURCE/dist/"* "$WEB_DEST/"
echo -e "${GREEN}✅ Web Dashboard synced successfully.${NC}"
# Copy source code for AI context
echo " -> Copying source code for AI context..."
rm -rf "$WEB_SRC_DEST"
mkdir -p "$WEB_SRC_DEST"
cp -R "$WEB_POC_SOURCE/src" "$WEB_SRC_DEST/"
[ -f "$WEB_POC_SOURCE/package.json" ] && cp "$WEB_POC_SOURCE/package.json" "$WEB_SRC_DEST/"
[ -f "$WEB_POC_SOURCE/tsconfig.json" ] && cp "$WEB_POC_SOURCE/tsconfig.json" "$WEB_SRC_DEST/"
[ -f "$WEB_POC_SOURCE/vite.config.ts" ] && cp "$WEB_POC_SOURCE/vite.config.ts" "$WEB_SRC_DEST/"
echo -e "${GREEN}✅ Web source code copied.${NC}"
else
echo -e "${RED}⚠️ Warning: Web POC source directory not found at $WEB_POC_SOURCE${NC}"
fi
# --- Determine Flutter Command ---
# Helper: Add FVM default to PATH if it exists (fixes Make environment missing user PATH)
if [ -d "$HOME/fvm/default/bin" ]; then
export PATH="$HOME/fvm/default/bin:$PATH"
fi
if command -v flutter &> /dev/null; then
FLUTTER_CMD="flutter"
echo -e "${BLUE} Using Flutter: $(which flutter)${NC}"
elif command -v fvm &> /dev/null; then
FLUTTER_CMD="fvm flutter"
echo -e "${BLUE} Using FVM: $FLUTTER_CMD${NC}"
else
echo -e "${RED}❌ Error: 'flutter' command not found. Please ensure Flutter is in your PATH or FVM is configured.${NC}"
# Try to provide a helpful hint based on user environment
if [ -d "$HOME/fvm/versions" ]; then
echo -e "${BLUE}💡 Hint: You seem to have FVM versions. Try running 'fvm global <version>' to set a default.${NC}"
fi
exit 1
fi
# --- Sync Mobile Client (Flutter) ---
echo -e "${BLUE}📱 Building Mobile Client Prototype (Flutter)...${NC}"
if [ -d "$MOBILE_CLIENT_SOURCE" ]; then
cd "$MOBILE_CLIENT_SOURCE"
echo " -> Getting packages..."
$FLUTTER_CMD pub get
echo " -> Building web bundle (base-href: $MOBILE_CLIENT_HREF)..."
$FLUTTER_CMD build web --base-href "$MOBILE_CLIENT_HREF" --release
cd - > /dev/null
echo " -> Deploying to Launchpad..."
rm -rf "$MOBILE_CLIENT_DEST"/*
mkdir -p "$MOBILE_CLIENT_DEST"
cp -R "$MOBILE_CLIENT_SOURCE/build/web/"* "$MOBILE_CLIENT_DEST/"
echo -e "${GREEN}✅ Mobile Client synced successfully.${NC}"
# Copy source code for AI context
echo " -> Copying source code for AI context..."
rm -rf "$MOBILE_CLIENT_SRC_DEST"
mkdir -p "$MOBILE_CLIENT_SRC_DEST"
cp -R "$MOBILE_CLIENT_SOURCE/lib" "$MOBILE_CLIENT_SRC_DEST/"
[ -f "$MOBILE_CLIENT_SOURCE/pubspec.yaml" ] && cp "$MOBILE_CLIENT_SOURCE/pubspec.yaml" "$MOBILE_CLIENT_SRC_DEST/"
echo -e "${GREEN}✅ Mobile Client source code copied.${NC}"
else
echo -e "${RED}⚠️ Warning: Mobile Client source not found at $MOBILE_CLIENT_SOURCE${NC}"
fi
# --- Sync Mobile Staff (Flutter) ---
echo -e "${BLUE}🍳 Building Mobile Staff Prototype (Flutter)...${NC}"
if [ -d "$MOBILE_STAFF_SOURCE" ]; then
cd "$MOBILE_STAFF_SOURCE"
echo " -> Getting packages..."
$FLUTTER_CMD pub get
echo " -> Building web bundle (base-href: $MOBILE_STAFF_HREF)..."
$FLUTTER_CMD build web --base-href "$MOBILE_STAFF_HREF" --release
cd - > /dev/null
echo " -> Deploying to Launchpad..."
rm -rf "$MOBILE_STAFF_DEST"/*
mkdir -p "$MOBILE_STAFF_DEST"
cp -R "$MOBILE_STAFF_SOURCE/build/web/"* "$MOBILE_STAFF_DEST/"
echo -e "${GREEN}✅ Mobile Staff synced successfully.${NC}"
# Copy source code for AI context
echo " -> Copying source code for AI context..."
rm -rf "$MOBILE_STAFF_SRC_DEST"
mkdir -p "$MOBILE_STAFF_SRC_DEST"
cp -R "$MOBILE_STAFF_SOURCE/lib" "$MOBILE_STAFF_SRC_DEST/"
[ -f "$MOBILE_STAFF_SOURCE/pubspec.yaml" ] && cp "$MOBILE_STAFF_SOURCE/pubspec.yaml" "$MOBILE_STAFF_SRC_DEST/"
echo -e "${GREEN}✅ Mobile Staff source code copied.${NC}"
else
echo -e "${RED}⚠️ Warning: Mobile Staff source not found at $MOBILE_STAFF_SOURCE${NC}"
fi
echo -e "${GREEN}🎉 Synchronization complete!${NC}"
echo "You can now verify the prototypes in internal/launchpad/prototypes/ and commit the changes."