🎯 Рекомендуемые коллекции

Балансированные коллекции примеров кода из различных категорий, которые вы можете исследовать

Примеры Ionic

Примеры гибридного фреймворка мобильных приложений Ionic, включая компоненты, навигацию, управление состоянием и нативную интеграцию

💻 Hello World на Ionic typescript

🟢 simple

Базовые примеры приложений Ionic с компонентами, страницами, маршрутизацией и фундаментальными концепциями для Angular, React и Vue

// Ionic Hello World Examples

// ============ IONIC ANGULAR EXAMPLES ============

// 1. Basic Ionic Angular App Structure
// src/app/app.component.ts
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  constructor(private platform: Platform) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      console.log('Platform ready');
    });
  }
}

// src/app/app.component.html
<ion-app>
  <ion-router-outlet></ion-router-outlet>
</ion-app>

// 2. Basic Hello World Page
// src/app/pages/hello-world/hello-world.page.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world',
  templateUrl: './hello-world.page.html',
  styleUrls: ['./hello-world.page.scss'],
})
export class HelloWorldPage {
  title = 'Hello Ionic!';
  subtitle = 'Welcome to the hybrid mobile development framework';

  constructor() {}

  showMessage() {
    console.log('Hello from Ionic!');
  }
}

// src/app/pages/hello-world/hello-world.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>Hello World</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">{{ title }}</ion-title>
    </ion-toolbar>
  </ion-header>

  <div class="ion-padding">
    <h1>{{ title }}</h1>
    <p>{{ subtitle }}</p>

    <ion-button expand="block" (click)="showMessage()">
      <ion-icon slot="start" name="hand-left-outline"></ion-icon>
      Say Hello
    </ion-button>
  </div>
</ion-content>

// src/app/pages/hello-world/hello-world.page.scss
ion-content {
  --background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

h1 {
  color: #fff;
  text-align: center;
  margin-bottom: 20px;
}

p {
  color: rgba(255, 255, 255, 0.8);
  text-align: center;
  margin-bottom: 30px;
}

ion-button {
  margin-top: 20px;
}

// 3. Ionic Angular Counter Component
// src/app/components/counter/counter.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.component.html',
  styleUrls: ['./counter.component.scss'],
})
export class CounterComponent {
  @Input() initialValue: number = 0;
  count: number = 0;

  constructor() {
    this.count = this.initialValue;
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }

  reset() {
    this.count = this.initialValue;
  }
}

// src/app/components/counter/counter.component.html
<div class="counter-container">
  <h2>Counter: {{ count }}</h2>

  <div class="button-group">
    <ion-button color="danger" (click)="decrement()">
      <ion-icon name="remove"></ion-icon>
    </ion-button>

    <ion-button color="warning" (click)="reset()">
      <ion-icon name="refresh"></ion-icon>
    </ion-button>

    <ion-button color="success" (click)="increment()">
      <ion-icon name="add"></ion-icon>
    </ion-button>
  </div>
</div>

// src/app/components/counter/counter.component.scss
.counter-container {
  text-align: center;
  padding: 20px;

  h2 {
    color: #fff;
    margin-bottom: 20px;
  }

  .button-group {
    display: flex;
    justify-content: center;
    gap: 10px;
  }
}

// 4. Interactive User Profile
// src/app/pages/profile/profile.page.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.page.html',
  styleUrls: ['./profile.page.scss'],
})
export class ProfilePage {
  user = {
    name: 'John Doe',
    email: '[email protected]',
    age: 28,
    bio: 'Mobile app developer passionate about hybrid apps',
    avatar: 'https://via.placeholder.com/150'
  };

  isEditing = false;
  editUser = { ...this.user };

  constructor() {}

  toggleEdit() {
    this.isEditing = !this.isEditing;
    if (!this.isEditing) {
      this.editUser = { ...this.user };
    }
  }

  saveProfile() {
    this.user = { ...this.editUser };
    this.isEditing = false;
  }

  cancelEdit() {
    this.editUser = { ...this.user };
    this.isEditing = false;
  }
}

// src/app/pages/profile/profile.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="end">
      <ion-button (click)="toggleEdit()">
        <ion-icon [name]="isEditing ? 'save' : 'create'"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title>User Profile</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <div class="ion-padding">
    <!-- Avatar Section -->
    <div class="avatar-section">
      <ion-avatar>
        <img [src]="user.avatar" [alt]="user.name">
      </ion-avatar>

      <ion-chip color="primary">
        <ion-icon name="star"></ion-icon>
        <ion-label>Pro User</ion-label>
      </ion-chip>
    </div>

    <!-- User Information -->
    <ion-card>
      <ion-card-header>
        <ion-card-title>User Information</ion-card-title>
      </ion-card-header>

      <ion-card-content>
        <ion-list>
          <ion-item>
            <ion-label position="stacked">Name</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.name"
              type="text">
            </ion-input>
            <h3 *ngIf="!isEditing">{{ user.name }}</h3>
          </ion-item>

          <ion-item>
            <ion-label position="stacked">Email</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.email"
              type="email">
            </ion-input>
            <p *ngIf="!isEditing">{{ user.email }}</p>
          </ion-item>

          <ion-item>
            <ion-label position="stacked">Age</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.age"
              type="number">
            </ion-input>
            <p *ngIf="!isEditing">{{ user.age }} years old</p>
          </ion-item>
        </ion-list>
      </ion-card-content>
    </ion-card>

    <!-- Bio Section -->
    <ion-card>
      <ion-card-header>
        <ion-card-title>About</ion-card-title>
      </ion-card-header>

      <ion-card-content>
        <ion-textarea
          *ngIf="isEditing"
          [(ngModel)]="editUser.bio"
          placeholder="Tell us about yourself..."
          rows="4">
        </ion-textarea>
        <p *ngIf="!isEditing">{{ user.bio }}</p>
      </ion-card-content>
    </ion-card>

    <!-- Action Buttons -->
    <div class="action-buttons" *ngIf="isEditing">
      <ion-button expand="block" color="success" (click)="saveProfile()">
        <ion-icon name="checkmark" slot="start"></ion-icon>
        Save Changes
      </ion-button>

      <ion-button expand="block" fill="outline" (click)="cancelEdit()">
        <ion-icon name="close" slot="start"></ion-icon>
        Cancel
      </ion-button>
    </div>
  </div>
</ion-content>

// ============ IONIC REACT EXAMPLES ============

// 1. Basic Ionic React App
// src/App.tsx
import React from 'react';
import { IonApp, IonRouterOutlet } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { Route, Redirect } from 'react-router-dom';

/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';

/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';

/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';

import HelloPage from './pages/HelloPage';
import CounterPage from './pages/CounterPage';
import ProfilePage from './pages/ProfilePage';

const App: React.FC = () => (
  <IonApp>
    <IonReactRouter>
      <IonRouterOutlet>
        <Route exact path="/hello" component={HelloPage} />
        <Route exact path="/counter" component={CounterPage} />
        <Route exact path="/profile" component={ProfilePage} />
        <Route exact path="/">
          <Redirect to="/hello" />
        </Route>
      </IonRouterOutlet>
    </IonReactRouter>
  </IonApp>
);

export default App;

// 2. Hello World Page with React
// src/pages/HelloPage.tsx
import React, { useState } from 'react';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonButton,
  IonIcon,
  IonCard,
  IonCardContent,
  IonCardHeader,
  IonCardTitle,
  IonItem,
  IonLabel,
  IonBadge,
  IonChip,
} from '@ionic/react';
import { heart, star, thumbsUp } from 'ionicons/icons';

const HelloPage: React.FC = () => {
  const [likeCount, setLikeCount] = useState(0);
  const [isLiked, setIsLiked] = useState(false);

  const handleLike = () => {
    setLikeCount(prev => prev + (isLiked ? -1 : 1));
    setIsLiked(!isLiked);
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Hello Ionic React</IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Welcome</IonTitle>
          </IonToolbar>
        </IonHeader>

        <div className="ion-padding">
          <div className="welcome-section">
            <h1>Hello, Ionic!</h1>
            <p>Welcome to the hybrid mobile framework with React</p>

            <IonChip color="primary">
              <IonIcon icon={star} />
              <IonLabel>React</IonLabel>
            </IonChip>

            <IonChip color="secondary">
              <IonIcon icon={heart} />
              <IonLabel>TypeScript</IonLabel>
            </IonChip>
          </div>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Interactive Demo</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonLabel>
                  <h3>Like this page!</h3>
                  <p>Click the button to show your appreciation</p>
                </IonLabel>
                <IonBadge color="primary">{likeCount}</IonBadge>
              </IonItem>

              <div className="button-container">
                <IonButton
                  expand="block"
                  fill={isLiked ? "solid" : "outline"}
                  color={isLiked ? "danger" : "primary"}
                  onClick={handleLike}
                >
                  <IonIcon icon={thumbsUp} slot="start" />
                  {isLiked ? 'Liked!' : 'Like'}
                </IonButton>
              </div>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Features</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonIcon icon={heart} color="danger" slot="start" />
                <IonLabel>Cross-platform development</IonLabel>
              </IonItem>

              <IonItem>
                <IonIcon icon={star} color="warning" slot="start" />
                <IonLabel>Beautiful UI components</IonLabel>
              </IonItem>

              <IonItem>
                <IonIcon icon={thumbsUp} color="success" slot="start" />
                <IonLabel>Native app performance</IonLabel>
              </IonItem>
            </IonCardContent>
          </IonCard>
        </div>
      </IonContent>
    </IonPage>
  );
};

export default HelloPage;

// 3. Counter Component with React Hooks
// src/pages/CounterPage.tsx
import React, { useState, useEffect } from 'react';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonButton,
  IonIcon,
  IonCard,
  IonCardContent,
  IonCardHeader,
  IonCardTitle,
  IonItem,
  IonLabel,
  IonGrid,
  IonRow,
  IonCol,
  IonRange,
  IonProgressBar,
  IonChip,
} from '@ionic/react';
import { add, remove, refresh, stats } from 'ionicons/icons';

interface CounterHistory {
  id: number;
  action: string;
  value: number;
  timestamp: Date;
}

const CounterPage: React.FC = () => {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);
  const [history, setHistory] = useState<CounterHistory[]>([]);
  const [maxValue, setMaxValue] = useState(100);

  useEffect(() => {
    // Calculate progress
    const progress = (Math.abs(count) / maxValue) * 100;
    console.log(`Progress: ${progress}%`);
  }, [count, maxValue]);

  const addToHistory = (action: string, value: number) => {
    const newEntry: CounterHistory = {
      id: Date.now(),
      action,
      value,
      timestamp: new Date(),
    };
    setHistory(prev => [newEntry, ...prev].slice(0, 10));
  };

  const increment = () => {
    const newValue = count + step;
    setCount(newValue);
    addToHistory('increment', newValue);
  };

  const decrement = () => {
    const newValue = count - step;
    setCount(newValue);
    addToHistory('decrement', newValue);
  };

  const reset = () => {
    setCount(0);
    addToHistory('reset', 0);
  };

  const getCountColor = () => {
    if (count > 0) return 'success';
    if (count < 0) return 'danger';
    return 'primary';
  };

  const getProgress = () => {
    const progress = (Math.abs(count) / maxValue) * 100;
    return Math.min(progress, 100);
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Counter</IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Interactive Counter</IonTitle>
          </IonToolbar>
        </IonHeader>

        <div className="ion-padding">
          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Counter Value</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <div className="counter-display">
                <IonChip color={getCountColor()}>
                  <IonIcon icon={stats} />
                  <IonLabel>{count}</IonLabel>
                </IonChip>
              </div>

              <IonProgressBar
                value={getProgress() / 100}
                color={getCountColor()}
                className="ion-margin-top"
              />

              <p className="ion-text-center">
                Progress: {getProgress().toFixed(1)}%
              </p>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Controls</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonLabel position="stacked">Step Size</IonLabel>
                <IonRange
                  min={1}
                  max={10}
                  value={step}
                  onIonChange={e => setStep(parseInt(e.detail.value as string))}
                  snaps
                  ticks
                >
                  <IonLabel slot="start">{step}</IonLabel>
                  <IonLabel slot="end">{step}</IonLabel>
                </IonRange>
              </IonItem>

              <IonItem>
                <IonLabel position="stacked">Max Value</IonLabel>
                <IonRange
                  min={50}
                  max={200}
                  step={10}
                  value={maxValue}
                  onIonChange={e => setMaxValue(parseInt(e.detail.value as string))}
                  snaps
                >
                  <IonLabel slot="start">{maxValue}</IonLabel>
                  <IonLabel slot="end">{maxValue}</IonLabel>
                </IonRange>
              </IonItem>

              <IonGrid>
                <IonRow>
                  <IonCol>
                    <IonButton
                      expand="block"
                      color="danger"
                      onClick={decrement}
                      disabled={count <= -maxValue}
                    >
                      <IonIcon icon={remove} slot="start" />
                      Decrease
                    </IonButton>
                  </IonCol>

                  <IonCol>
                    <IonButton
                      expand="block"
                      color="warning"
                      onClick={reset}
                    >
                      <IonIcon icon={refresh} slot="start" />
                      Reset
                    </IonButton>
                  </IonCol>

                  <IonCol>
                    <IonButton
                      expand="block"
                      color="success"
                      onClick={increment}
                      disabled={count >= maxValue}
                    >
                      <IonIcon icon={add} slot="start" />
                      Increase
                    </IonButton>
                  </IonCol>
                </IonRow>
              </IonGrid>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>History</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              {history.length > 0 ? (
                history.map(item => (
                  <IonItem key={item.id}>
                    <IonLabel>
                      <h3>{item.action}</h3>
                      <p>New value: {item.value}</p>
                    </IonLabel>
                    <IonLabel slot="end">
                      {item.timestamp.toLocaleTimeString()}
                    </IonLabel>
                  </IonItem>
                ))
              ) : (
                <p className="ion-text-center ion-color-medium">
                  No actions yet. Start counting!
                </p>
              )}
            </IonCardContent>
          </IonCard>
        </div>
      </IonContent>
    </IonPage>
  );
};

export default CounterPage;

// ============ IONIC VUE EXAMPLES ============

// 1. Basic Ionic Vue App
// src/main.ts
import { createApp } from 'vue';
import { IonicVue } from '@ionic/vue';
import router from './router';

import App from './App.vue';

import '@ionic/vue/css/core.css';
import '@ionic/vue/css/normalize.css';
import '@ionic/vue/css/structure.css';
import '@ionic/vue/css/typography.css';
import '@ionic/vue/css/padding.css';
import '@ionic/vue/css/float-elements.css';
import '@ionic/vue/css/text-alignment.css';
import '@ionic/vue/css/text-transformation.css';
import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';

const app = createApp(App).use(IonicVue).use(router);
app.mount('#app');

// 2. Hello World Page with Vue 3 Composition API
// src/views/HelloWorld.vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Hello Ionic Vue</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">{{ title }}</ion-title>
        </ion-toolbar>
      </ion-header>

      <div class="ion-padding">
        <div class="welcome-container">
          <h1>{{ title }}</h1>
          <p>{{ subtitle }}</p>

          <ion-chip color="primary">
            <ion-icon :icon="starOutline" />
            <ion-label>Vue 3</ion-label>
          </ion-chip>

          <ion-chip color="secondary">
            <ion-icon :icon="codeSlash" />
            <ion-label>TypeScript</ion-label>
          </ion-chip>

          <ion-chip color="tertiary">
            <ion-icon :icon="phonePortrait" />
            <ion-label>Mobile</ion-label>
          </ion-chip>
        </div>

        <ion-card>
          <ion-card-header>
            <ion-card-title>Interactive Features</ion-card-title>
          </ion-card-header>

          <ion-card-content>
            <ion-list>
              <ion-item>
                <ion-thumbnail slot="start">
                  <img src="https://via.placeholder.com/50" alt="Feature 1" />
                </ion-thumbnail>
                <ion-label>
                  <h3>Cross-platform</h3>
                  <p>Build once, deploy everywhere</p>
                </ion-label>
              </ion-item>

              <ion-item>
                <ion-thumbnail slot="start">
                  <img src="https://via.placeholder.com/50" alt="Feature 2" />
                </ion-thumbnail>
                <ion-label>
                  <h3>Native Performance</h3>
                  <p>Fast, smooth user experience</p>
                </Ion-label>
              </ion-item>
            </ion-list>

            <div class="button-group">
              <ion-button
                expand="block"
                color="primary"
                @click="showAlert"
              >
                <ion-icon :icon="heart" slot="start" />
                Show Alert
              </ion-button>

              <ion-button
                expand="block"
                fill="outline"
                color="secondary"
                @click="navigateToCounter"
              >
                <ion-icon :icon="trendingUp" slot="start" />
                Try Counter
              </ion-button>
            </div>
          </ion-card-content>
        </ion-card>
      </div>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import {
  alertController,
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonChip,
  IonLabel,
  IonIcon,
  IonCard,
  IonCardHeader,
  IonCardTitle,
  IonCardContent,
  IonList,
  IonItem,
  IonThumbnail,
  IonButton
} from '@ionic/vue';
import { useRouter } from 'vue-router';
import {
  starOutline,
  codeSlash,
  phonePortrait,
  heart,
  trendingUp
} from 'ionicons/icons';

const router = useRouter();
const title = ref('Hello, Ionic!');
const subtitle = ref('Welcome to the hybrid mobile development framework with Vue 3');

const showAlert = async () => {
  const alert = await alertController.create({
    header: 'Welcome!',
    message: 'This is an Ionic alert dialog in Vue 3!',
    buttons: ['OK'],
  });

  await alert.present();
};

const navigateToCounter = () => {
  router.push('/counter');
};
</script>

<style scoped>
.welcome-container {
  text-align: center;
  margin-bottom: 30px;
}

.welcome-container h1 {
  color: #fff;
  margin-bottom: 10px;
}

.welcome-container p {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 20px;
}

.button-group {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

ion-content {
  --background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
</style>

// 3. Reactive Counter with Vue Composition API
// src/views/Counter.vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Counter</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <div class="ion-padding">
        <ion-card>
          <ion-card-header>
            <ion-card-title>Reactive Counter</ion-card-title>
          </ion-card-header>

          <ion-card-content>
            <div class="counter-display">
              <ion-chip :color="counterColor">
                <ion-icon :icon="stats" />
                <ion-label>{{ count }}</ion-label>
              </ion-chip>
            </div>

            <ion-progress-bar
              :value="progress"
              :color="counterColor"
              class="ion-margin-top"
            />

            <p class="ion-text-center">
              {{ progressText }}
            </p>
          </ion-card-content>
        </ion-card>

        <ion-card>
          <ion-card-header>
            <ion-card-title>Statistics</ion-cardTitle>
          </ion-card-header>

          <ion-card-content>
            <ion-grid>
              <ion-row>
                <ion-col>
                  <div class="stat-item">
                    <h2>{{ incrementCount }}</h2>
                    <p>Increments</p>
                  </div>
                </ion-col>

                <ion-col>
                  <div class="stat-item">
                    <h2>{{ decrementCount }}</h2>
                    <p>Decrements</p>
                  </div>
                </ion-col>

                <ion-col>
                  <div class="stat-item">
                    <h2>{{ resetCount }}</h2>
                    <p>Resets</p>
                  </div>
                </ion-col>
              </ion-row>
            </ion-grid>
          </ion-card-content>
        </ion-card>

        <ion-card>
          <ion-card-header>
            <ion-cardTitle>Controls</ion-cardTitle>
          </ion-cardHeader>

          <ion-cardContent>
            <ion-range
              v-model="stepSize"
              :min="1"
              :max="10"
              :step="1"
              :snaps="true"
              :ticks="true"
            >
              <ion-label slot="start">Step: {{ stepSize }}</ion-label>
              <ion-label slot="end">{{ stepSize }}</ion-label>
            </ion-range>

            <ion-grid class="ion-margin-top">
              <ion-row>
                <ion-col>
                  <ion-button
                    expand="block"
                    color="danger"
                    @click="decrement"
                    :disabled="count <= -maxValue"
                  >
                    <ion-icon :icon="remove" slot="start" />
                    Decrease
                  </ion-button>
                </ion-col>

                <ion-col>
                  <ion-button
                    expand="block"
                    color="warning"
                    @click="reset"
                  >
                    <ion-icon :icon="refresh" slot="start" />
                    Reset
                  </ion-button>
                </ion-col>

                <ion-col>
                  <ion-button
                    expand="block"
                    color="success"
                    @click="increment"
                    :disabled="count >= maxValue"
                  >
                    <ion-icon :icon="add" slot="start" />
                    Increase
                  </ion-button>
                </ion-col>
              </ion-row>
            </ion-grid>
          </ion-cardContent>
        </ion-card>
      </div>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonCard,
  IonCardHeader,
  IonCardTitle,
  IonCardContent,
  IonChip,
  IonLabel,
  IonIcon,
  IonProgressBar,
  IonGrid,
  IonRow,
  IonCol,
  IonRange,
  IonButton
} from '@ionic/vue';
import {
  stats,
  add,
  remove,
  refresh
} from 'ionicons/icons';

// Reactive state
const count = ref(0);
const stepSize = ref(1);
const maxValue = ref(100);

// Statistics
const incrementCount = ref(0);
const decrementCount = ref(0);
const resetCount = ref(0);

// Computed properties
const counterColor = computed(() => {
  if (count.value > 0) return 'success';
  if (count.value < 0) return 'danger';
  return 'primary';
});

const progress = computed(() => {
  const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
  return Math.min(progressValue / 100, 1);
});

const progressText = computed(() => {
  const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
  return `Progress: ${progressValue.toFixed(1)}%`;
});

// Methods
const increment = () => {
  if (count.value < maxValue.value) {
    count.value += stepSize.value;
    incrementCount.value++;
  }
};

const decrement = () => {
  if (count.value > -maxValue.value) {
    count.value -= stepSize.value;
    decrementCount.value++;
  }
};

const reset = () => {
  count.value = 0;
  resetCount.value++;
};
</script>

<style scoped>
.counter-display {
  text-align: center;
  margin: 20px 0;
}

.stat-item {
  text-align: center;
}

.stat-item h2 {
  margin: 0;
  font-size: 24px;
  font-weight: bold;
}

.stat-item p {
  margin: 4px 0 0 0;
  color: var(--ion-color-medium);
}
</style>

// ============ SHARED TYPES AND INTERFACES ============

// types/interfaces.ts
export interface User {
  id: string;
  name: string;
  email: string;
  age: number;
  bio: string;
  avatar?: string;
}

export interface TodoItem {
  id: string;
  title: string;
  description: string;
  completed: boolean;
  createdAt: Date;
  dueDate?: Date;
  priority: 'low' | 'medium' | 'high';
}

export interface CounterState {
  count: number;
  step: number;
  maxValue: number;
  history: HistoryEntry[];
}

export interface HistoryEntry {
  id: string;
  action: 'increment' | 'decrement' | 'reset';
  value: number;
  timestamp: Date;
}

// ============ ROUTING CONFIGURATION ============

// Angular Routing - app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'home',
    loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
  },
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

// React Routing - App.tsx (shown above)
// Vue Router - router/index.ts (shown above)

// ============ MAIN ENTRIES ============

// Use these main functions to run different framework examples:

// For Angular:
// npm run start (in Ionic Angular project)

// For React:
// npm run start (in Ionic React project)

// For Vue:
// npm run dev (in Ionic Vue project)