Saturday, December 14, 2024

TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER

Berikut ini adalah skrip template vue dengan kecepatan dan keandalan yang luar biasa, karna pemanggilan dan penggunaan skrip sangatlah mudah.










<!DOCTYPE html>
<html lang="en" style="overflow: hidden;">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue App</title>
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.4.95/css/materialdesignicons.min.css" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/vuetify@2.6.15/dist/vuetify.min.css" rel="stylesheet">
</head>

<body>
  <div id="app">
    <v-app>
      <v-dialog persistent v-for="dialog in dialogs" :key="dialog.id" v-model="dialog.visible" :max-width="dialog.lebar">
        <template v-if="dialog.id === 'loading'">
            <v-card>
                <v-card-title  class="layout justify-center">{{dialog.title}}</v-card-title>
                <v-card-text>
                    <v-container class="d-flex justify-center align-center" style="height: 40px;">
                        <v-progress-circular indeterminate color="primary"></v-progress-circular>
                    </v-container>
                </v-card-text>
            </v-card>
        </template>
        <template v-else>
            <v-card>
              <v-card-title>{{dialog.title}}</v-card-title>
              <v-card-text>
                  <component :is="dialog.template" :data="dialog.data"></component>
              </v-card-text>
              <v-card-actions>
                  <v-btn text v-if="dialog.extra" :color="dialog.extra.color || 'secondary'" @click="dialog.extra.action(dialog)">{{ dialog.extra.title }}</v-btn>
                  <v-spacer></v-spacer>
                  <v-btn text v-if="dialog.ok" :color="dialog.ok.color || 'primary'"  @click="dialog.ok.action(dialog)">{{ dialog.ok.title }}</v-btn>
                  <v-btn text @click="closeDialog(dialog.id)">Batal</v-btn>
              </v-card-actions>
          </v-card>
        </template>
      </v-dialog>
      <v-snackbar v-model="pesan.show" timeout="2000">
          {{ pesan.title }}
          <template v-slot:action="{ attrs }">
              <v-btn color="blue" text v-bind="attrs" @click="pesan.show = false">
                  Close</v-btn>
          </template>
      </v-snackbar>      
      <router-view></router-view>
    </v-app>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue-router@3.6.5/dist/vue-router.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.6.15"></script>


  <template id="listusers">
      <v-card>
          <v-card-text>
              <v-list>
                  <v-list-item v-for="(user, index) in listuser" :key="index">
                      <v-list-item-content>
                          <v-list-item-title>{{ user.username }}</v-list-item-title>
                          <v-list-item-subtitle>{{ user.name }}</v-list-item-title>
                      </v-list-item-content>
                      <v-list-item-action>
                          <div>
                              <v-btn icon color="red" @click="deleteUser(index)">
                                  <v-icon>mdi-delete</v-icon>
                              </v-btn>
                              <v-btn icon color="blue" @click="bukaEditing(user, index)">
                                  <v-icon>mdi-pencil</v-icon>
                              </v-btn>
                          </div>
                      </v-list-item-action>
                  </v-list-item>
              </v-list>
          </v-card-text>
      </v-card>
  </template>
  <script>
  const ListUser = {
      template: "#listusers",
      data: () => ({
          listuser: [],
      }),
      methods: {
          fetchUsers() {
              this.listuser = StorageCRUD("user").tampilData();
          },
  
          bukaEditing(user = null, index = null) {
              const isEdit = user !== null;
              app.openDialog(
                  "form", 
                  isEdit ? "Edit User" : "Tambah User", 
                  {
                      template: `
                          <v-form>
                              <v-text-field v-model="data.name" label="Nama"></v-text-field>
                              <v-text-field v-model="data.username" label="Username"></v-text-field>
                              <v-text-field v-model="data.password" label="Password" type="password"></v-text-field>
                          </v-form>
                      `,
                      props: ["data"],
                  },
                  isEdit ? { ...user } : { name: "", username: "", password: "" },
                  {
                      title: "Simpan",
                      action: (dialog) => {
                          let berhasil;
                          if (isEdit) {
                              berhasil = StorageCRUD("user").edit(user.id, dialog.data);
                          } else {
                              berhasil = StorageCRUD("user").simpan(dialog.data);
                          }
  
                          if (berhasil) {
                              app.tampilpesan(isEdit ? "User berhasil diperbarui" : "User berhasil ditambahkan");
                              this.fetchUsers();
                          } else {
                              app.tampilpesan(isEdit ? "Gagal memperbarui user" : "Gagal menambahkan user");
                          }
                          app.closeDialog("form");
                      },
                  },
              );
          },
  
          deleteUser(index) {
              const user = this.listuser[index];
              app.openDialog(
                  "confirm", 
                  "Konfirmasi", 
                  "Yakin ingin menghapus user ini?", 
                  null, 
                  {
                      title: "Ya",
                      color: "red",
                      action: () => {
                          const berhasil = StorageCRUD("user").hapus(user.id);
                          if (berhasil) {
                              app.tampilpesan("User berhasil dihapus");
                              this.fetchUsers();
                          } else {
                              app.tampilpesan("Gagal menghapus user");
                          }
                          app.closeDialog("confirm");
                      },
                  },
              );
          },
      },
      mounted(){
        this.fetchUsers();
        app.actionButtons= [{ name: 'edit', icon: 'mdi-plus-box', 
                              method:()=>{
                                this.bukaEditing();
                              }
        }];
        app.floatingButtons= { 
          fab:false,
          icon: 'mdi-plus', 
          color: 'primary', 
          method: () => console.log('Fab1'), 
          children: [ 
            { 
              icon: 'mdi-pencil', 
              color: 'secondary', 
              method: () => console.log('Child 1'), 
              
            }, { 
              icon: 'mdi-delete', 
              color: 'error', 
              method: () => console.log('Child 2'), 
              
            }, 
            ], 
          
        }
        
      }
    
  }
  </script>




  <template id="tesdialog">
      <v-card>
          <v-card-text>
          </v-card-text>
          <v-card-actions>
            <v-btn @click="showFormDialog">Show Form Dialog</v-btn>
          </v-card-actions>
      </v-card>
  </template>
  <script>
      const TesDialog = {
          template: '#tesdialog',
          data: () => ({

          }),
          methods: {
                showFormDialog() {
                    app.openDialog('form', 'input pelanggan', 
                    { props: ['data'],
                      template: `
                          <v-form>
                              <v-text-field v-model="data.nama" label="Nama"></v-text-field>
                              <v-text-field v-model="data.address" label="Alamat"></v-text-field>
                          </v-form> `,
                    }, 
                    { nama: 'Ali', address: 'Brongkal' }, 
                    { title: 'Simpan',
                        action: (dialog) => {
                            app.openDialog('confirm', 'Konfirmasi', 'Yakin akan menyimpan data?',null, 
                            { title: 'Iya', action: () => {
                                console.log(dialog.data);
                                app.closeDialog('form');
                                app.closeDialog('confirm');
                            }},
                            { title: 'Tidak', action: () => {
                              app.openDialog('loading', 'Loading...', null, null, null, null);
                              setTimeout(() => {
                                  app.closeDialog('loading');
                                  console.log(dialog.data);
                              }, 3000);             

                            }},                            
                            );
                        }
                    });
                },            
          },
          mounted(){
            app.floatingButtons= { 
              fab:false,
              icon: 'mdi-plus', 
              color: 'primary', 
              method: () => console.log('Fab1'), 
              
            }            
          }
      };
  </script>



  <template id="autentifikasi">
      <v-main>
          <v-container fill-height>
              <v-row align="center" justify="center">
                  <v-col cols="12" sm="8" md="4">
                      <v-card class="mx-auto" :style="{ maxWidth: '290px' }">
                          <v-toolbar dark color="primary">
                              <v-toolbar-title>
                                  {{title}}
                              </v-toolbar-title>
                              <v-spacer></v-spacer> <div v-for="action in $root.actionButtons" :key="action.name"> <v-btn icon @click="action.method"> <v-icon>{{ action.icon }}</v-icon> </v-btn> </div>                              
                          </v-toolbar>
                          <v-card-text>
                              <v-text-field v-if="register" v-model="name" label="Nama"></v-text-field>
                              <v-text-field v-model="username" label="Username"></v-text-field>
                              <v-text-field v-model="password" label="Password" type="password"></v-text-field>
                          </v-card-text>
                          <v-card-actions>
                              <v-btn @click="login" text color="blue" v-if="!register">Login</v-btn>
                              <v-btn @click="registerUser" text color="blue" v-if="register">Kirim</v-btn>
                              <v-btn @click="toggleRegister" text color="green">{{ register ? 'Kembali' : 'Registrasi'
                                  }}</v-btn>
                          </v-card-actions>
                      </v-card>
                  </v-col>
              </v-row>
          </v-container>
      </v-main>
  </template>

  <script>
      const Autentifikasi = {
          template: '#autentifikasi',
          data: () => ({
              title: 'Login',
              username: 'ali',
              password: 'ali',
              name: '',
              register: false
          }),
          methods: {
              login() {
                  const ditemukan = StorageCRUD("user").cari({ username:this.username, password: this.password});
                  if(ditemukan.length>0){
                    app.tampilpesan('Login berhasil');
                    app.useraktif=ditemukan[0];
                    this.$router.push('/dashboard');
                  }else{
                    app.tampilpesan('Login gagal');
                  }
              },
                registerUser() {
                  const berhasil = StorageCRUD("user").simpan({ name: this.name, password: this.password, username:this.username });
                  if(berhasil){
                    app.tampilpesan('Pendaftaran berhasil');
                    this.toggleRegister();
                  }else{
                    app.tampilpesan('Pendaftaran gagal');
                  }

                },
                toggleRegister() {
                    this.register = !this.register;
                    this.title = this.register ? 'Registrasi' : 'Login';
                }              
          }
      }
  </script>



  <template id="applayout">
    <div>
        <v-app-bar app color="primary" dark>
            <v-app-bar-nav-icon @click="drawer = !drawer"></v-app-bar-nav-icon>
            <v-toolbar-title>{{ title }}</v-toolbar-title>
            <v-spacer></v-spacer> <div v-for="action in $root.actionButtons" :key="action.name"> <v-btn icon @click="action.method"> <v-icon>{{ action.icon }}</v-icon> </v-btn> </div>            
        </v-app-bar>

        <v-navigation-drawer v-model="drawer" app>
            <v-list dense>
                <v-list-item-group>
                    <v-list-item v-for="route in routes" :key="route.path"
                        @click="pindahHalaman(route.path,route.meta.title)">
                        <v-list-item-icon>
                            <v-icon>{{ route.meta.icon }}</v-icon>
                        </v-list-item-icon>
                        <v-list-item-title>{{ route.meta.title }}</v-list-item-title>
                    </v-list-item>
                </v-list-item-group>
            </v-list>
        </v-navigation-drawer>

        <v-main style="height: 100vh;">
            <v-layout fill-height overflow-auto>
                <v-container fluid>
                  <router-view></router-view>
                  <div v-if="$root.floatingButtons && Object.keys($root.floatingButtons).length > 0">
                    <div v-if="$root.floatingButtons.children && $root.floatingButtons.children.length > 0" style="position: fixed; bottom: 16px; right: 16px;">
                      <v-speed-dial v-model="$root.floatingButtons.fab" direction="top" :open-on-hover="false" transition="scale-transition">
                        <template v-slot:activator>
                          <v-btn :color="$root.floatingButtons.color" fab dark>
                            <v-icon>{{ $root.floatingButtons.icon }}</v-icon>
                          </v-btn>
                        </template>
                        <v-btn v-for="(button, index) in $root.floatingButtons.children" :key="index" :color="button.color" fab dark @click="button.method">
                          <v-icon>{{ button.icon }}</v-icon>
                        </v-btn>
                      </v-speed-dial>
                    </div>
                    <div v-else style="position: fixed; bottom: 16px; right: 16px;">
                      <v-btn @click="$root.floatingButtons.method" :color="$root.floatingButtons.color" fab dark>
                        <v-icon>{{ $root.floatingButtons.icon }}</v-icon>
                      </v-btn>
                    </div>
                  </div>

                </v-container>
            </v-layout>
        </v-main>
    </div>
  </template>
  <script>
      const appLayout = {
          template: '#applayout',
          data: () => ({
              drawer: false,
              title: 'Aplikasi',
              routes: navigasiaplikasi
          }),
          methods: {
              pindahHalaman(path, judul) {
                  if (this.$route.path !== path) {
                      this.title = judul;
                      this.$router.push(path);
                  }
              }
          },
          created() {
              this.title = this.$route.meta.title;
          }
      }

  </script>

  <script>



      const Dashboard = {
          data: () => ({ useraktif: app.useraktif  }),
          template: `<v-card><v-card-text><h1>Selamat datang,</h1></br><h2>{{ useraktif.name }}</h2></v-card-text></v-card>`
      };

      const Logout = { 
          template: '<div></div>', 
          created() { 
              app.useraktif = null; 
              this.$nextTick(() => {
                  this.$router.replace('/login');
              });
          } 
      };
      const navigasiaplikasi = [
          {
              path: '/dashboard', component: Dashboard,
              meta: { title: 'Dashboard', icon: 'mdi-view-dashboard' }
          },

          {
              path: '/listuser', component: ListUser,
              meta: { title: 'List User', icon: 'mdi-account' }
          },
          {
              path: '/tesdialog', component: TesDialog,
              meta: { title: 'Tes Dialog', icon: 'mdi-account' }
          },

          {
              path: '/logout', component: Logout,
              meta: { title: 'Logout', icon: 'mdi-logout' }
          },
      ];


      const routes = [
          {
              path: '/', redirect: '/login', component: appLayout,
              children: navigasiaplikasi
          },
          { path: '/login', component: Autentifikasi },
          { path: '*', redirect: '/' }
      ];

      const router = new VueRouter({
          routes
      });

      const app = new Vue({
          el: '#app',
          router,
          vuetify: new Vuetify(),
          data: () => ({
              dialogs: [],
              pesan: {
                  show: false,
                  title: ''
              },
              actionButtons:[],
              floatingButtons:{},
              useraktif:{},
          }),
          methods: {
            tampilpesan(pesan) {
                this.pesan.show = true;
                this.pesan.title = pesan;
            },            
            openDialog(id, title = 'dialog', template, data = null, ok = null, extra = null) {
              this.dialogs.push({ id, title, visible: true, template: id === 'form' ? template : { template: `<p>${template}</p>` }, data, ok, extra, lebar: id === 'form' ? '410px' : (id === 'confirm' ? '310px' : (id === 'loading' ? '210px' : '310px')) });
            },
            closeDialog(id) {
                const index = this.dialogs.findIndex(dialog => dialog.id === id);
                if (index !== -1) {
                    this.dialogs.splice(index, 1);
                }
            },
          }
      });

      router.beforeEach((to, from, next) => {
        const isAuthenticated = !!app.useraktif;
        app.actionButtons=[];
        app.floatingButtons={};
        if (to.path === '/login' && isAuthenticated) {
            next('/dashboard');
        } else if (to.path !== '/login' && !isAuthenticated) {
            next('/login');
        } else {
            next();
        }
      });
    const StorageCRUD = (localStorageKey) => {
        const getData = () => {
            const data = localStorage.getItem(localStorageKey);
            return data ? JSON.parse(data) : [];
        };
    
        const saveData = (data) => {
            localStorage.setItem(localStorageKey, JSON.stringify(data));
        };
    
        return {
            simpan: (item) => {
                try {
                    const data = getData();
                    item.id = new Date().getTime(); 
                    data.push(item);
                    saveData(data);
                    return true;
                } catch (error) {
                    return false; 
                }
            },
    
            hapus: (id) => {
                const data = getData();
                const initialLength = data.length;
                const updatedData = data.filter(item => item.id !== id);
    
                if (updatedData.length < initialLength) {
                    saveData(updatedData);
                    return true; 
                }
                return false; 
            },
    
            edit: (id, updatedItem) => {
                const data = getData();
                const index = data.findIndex(item => item.id === id);
    
                if (index !== -1) {
                    data[index] = { ...data[index], ...updatedItem };
                    saveData(data);
                    return true; 
                }
                return false;
            },
    
            cari: (criteria) => {
                const data = getData();
    
                const hasil = data.filter(item => {
                    return Object.entries(criteria).every(([key, value]) => {
                        if (Array.isArray(value)) {
                            return value[0] <= item[key] && item[key] <= value[1];
                        }
                        return item[key] && item[key].toString().toLowerCase() === value.toString().toLowerCase();
                    });
                });
    
                return hasil;
            },
    
            tampilData: () => {
                return getData(); 
            }
        };
    };



  </script>
</body>

</html>


Thursday, November 30, 2023

PRAKTIKUM INTERNET GATEWAY (NAT) - PACKET TRACKER

panduan simulasi internet gateway (nat)
skrip pada video seperti dibawah ini:
login cisco
Router>enable
Router#configure terminal

konfigurasi interface ethernet
Router(config)#interface fa0/0
Router(config-if)#ip address 110.76.148.78 255.255.255.252
Router(config-if)#ip nat outside
Router(config-if)#no shutdown
Router(config-if)#ex

Router(config)#interface fa0/1
Router(config-if)#ip address 192.168.20.1 255.255.255.0
Router(config-if)#ip nat inside
Router(config-if)#no shutdown
Router(config-if)#ex

konfigurasi gateway
Router(config)#ip route 0.0.0.0 0.0.0.0 110.76.148.77
Router(config)#ip name-server 110.76.148.77

masquerade(NAT)
Router(config)#access-list 1 permit 192.168.20.0 0.0.0.255
Router(config)#ip nat inside source list 1 interface f0/0 overload

dhcp server
Router(config)#ip dhcp pool nama
Router(dhcp-config)#network 192.168.20.0 255.255.255.0
Router(dhcp-config)#default-router 192.168.20.1
Router(dhcp-config)#dns-server 110.76.148.77
Router(dhcp-config)#

Monday, November 27, 2023

Monday, September 11, 2023

TUTORIAL PENGGUNAAN MIKROTIK SCRIPT OTOMATIS PPPoE + ISOLIR dan PISAH TR...

skrip mengkonfigurasi mikrotik menjadi server PPPoE dan membuatkan profile aktif dan profil isolir pelanggan yang sudah otomatis mengkonfigurasi firewall dan web proxy sebagai tampilan pelanggan yang terisolir. fitur lain dari script adalah pemisahan trafik pada berbagai platform.

Sunday, September 10, 2023

Monday, May 29, 2023

Panduan Konfigurasi Load Balance dan VLAN pada Router Openwrt Xiomi MI4A

kali ini saya akan memberikan panduan konfigurasi load balance pada router openwrt

disini sumber internet saya, dikonfigurasi sebagai berikut:

  • ISP1 : PORT WAN
  • ISP2 : PORT LAN 1 by VLAN
langsung saja, berikut ini tampilan luci yang dikonfigurasi, simak baik-baik langkah-langkahnya:

  1. network->switch


 

  1. konfigurasi network -> interface


    gateway matrix wajib diisi
  2. konfigurasi network -> firewall


  3. install system -> software -> mwan3


  4. konfigurasi mwan3
    bagian interface


    pastikan Tracking hostname or IP address diisi, Flush conntrack table centang semua dan matric muncul
  1. bagian member


  2. bagian police


 

  1. bagian rule


  2. hasilnya


    cek status -> load balancing

link video tutorial dibawah ini, jangan lupa subscribe:

Thursday, January 19, 2023

NET. MAUI LOGIN SHELL APPS NAVIGATION

kali ini saya akan memberikan source code untuk membuat navigasi login net. maui, langsungsaja, berikut tampilan login:


 
berikut tampilan setelah login

berikut tampilan dashboard
berikut tampilan navigasi.

untuk source codenya sebagai berikut;
file App.xaml

<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:My_Template"
             x:Class="My_Template.App" UserAppTheme="Light">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/Styles/Colors.xaml" />
                <ResourceDictionary Source="Resources/Styles/Styles.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

file App.xaml.cs

namespace My_Template;
#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
#endif
public partial class App : Application
{
    const int WindowWidth = 500;
    const int WindowHeight = 800;
    public App()
	{
		InitializeComponent();
        Microsoft.Maui.Handlers.WindowHandler.Mapper.AppendToMapping(nameof(IWindow), (handler, view) =>
        {
#if WINDOWS
            var mauiWindow = handler.VirtualView;
            var nativeWindow = handler.PlatformView;
            nativeWindow.Activate();
            IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
            WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(windowHandle);
            AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
            appWindow.Resize(new SizeInt32(WindowWidth, WindowHeight));
#endif
        });
        MainPage = new AppShell();
	}
}
file AppShell.xaml

<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="My_Template.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:My_Template"
    Shell.FlyoutBehavior="Disabled" >

    <Shell.TabBarIsVisible>false</Shell.TabBarIsVisible>
    <Shell.FlyoutBackgroundColor>#E1E1E1</Shell.FlyoutBackgroundColor>
    <ShellContent
        Title="Login"     
        Shell.FlyoutItemIsVisible="False"   
        ContentTemplate="{DataTemplate local:LoginPage}"
        Route="LoginPage" />

    <FlyoutItem 
        Title="App" 
        Route="App" 
        FlyoutDisplayOptions="AsMultipleItems">

        <ShellContent
            Title="Main"
            Icon="dotnet_bot.png"
            ContentTemplate="{DataTemplate local:MainPage}"
            Route="MainPage" />

        <ShellContent
            Title="About"
            Icon="dotnet_bot.png"
            ContentTemplate="{DataTemplate local:AboutPage}"
            Route="AboutPage" />

    </FlyoutItem>
    <Shell.FlyoutFooter>
        <StackLayout Padding="10,10,10,10">
            <Button Text="Log Out" Clicked="Logout_Click"/>
        </StackLayout>
        
    </Shell.FlyoutFooter>
</Shell>


file AppShell.xaml.cs

namespace My_Template;

public partial class AppShell : Shell
{
	public AppShell()
	{
		InitializeComponent();
	}

    private void Logout_Click(object sender, EventArgs e)
    {
        Shell.Current.FlyoutBehavior = FlyoutBehavior.Disabled;
        Shell.Current.GoToAsync("//LoginPage");
    }
}
file LoginPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="My_Template.LoginPage"
             Title="LoginPage">
    <Shell.TabBarIsVisible>false</Shell.TabBarIsVisible>
    <Shell.NavBarIsVisible>false</Shell.NavBarIsVisible>
    <Shell.FlyoutBehavior>Disabled</Shell.FlyoutBehavior>

    <ScrollView>

        <VerticalStackLayout
                Spacing="15"
                Padding="10,10,10,10" Margin="10,10,10,10" WidthRequest="300"
                VerticalOptions="Center">

            <StackLayout Padding="0,0,0,40">
                <Image
                    Source="dotnet_bot.png"
                    SemanticProperties.Description="Cute dot net bot waving hi to you!"
                    HeightRequest="150"
                    HorizontalOptions="Center" />
                <Label Text="silahkan login" HorizontalOptions="Center" Padding="0,20,0,20" FontSize="Medium"/>
            </StackLayout>

            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="Auto" />

                </Grid.ColumnDefinitions>
                <Border Stroke="#003434"
                    StrokeThickness="1"
                    StrokeShape="RoundRectangle 3,3,3,3"
>
                    <Entry  Placeholder="IP" Text="192.168.4.1" FontSize="Small" FontAttributes="Bold"/>

                </Border>

                <Border Stroke="#003434" StrokeThickness="1" StrokeShape="RoundRectangle 3,3,3,3" Grid.Column="1" Margin="10,0,0,0" >
                    <Entry  Placeholder="Port" Text="8728" VerticalTextAlignment="Center" Keyboard="Numeric" FontSize="Small" FontAttributes="Bold"/>
                </Border>

            </Grid>
            <Border Stroke="#003434"
                    StrokeThickness="1"
                    StrokeShape="RoundRectangle 3,3,3,3"
                    Padding="0,0,0,0">
                <Entry  Placeholder="Username" Text="admin" FontSize="Small" FontAttributes="Bold"/>
            </Border>
            <Border Stroke="#003434"
                    StrokeThickness="1"
                    StrokeShape="RoundRectangle 3,3,3,3"
                    Padding="0,0,0,0">
                <Entry  Placeholder="Password" Text="abumusa123" IsPassword="True" FontSize="Small" FontAttributes="Bold"/>
            </Border>
            <Button Text="Login" Clicked="Login_Click" HeightRequest="50"/>

        </VerticalStackLayout>

    </ScrollView>
</ContentPage>

file LoginPage.xaml.cs

namespace My_Template;

public partial class LoginPage : ContentPage
{
	public LoginPage()
	{
		InitializeComponent();
	}

    private void Login_Click(object sender, EventArgs e)
    {
        Shell.Current.FlyoutBehavior = FlyoutBehavior.Flyout;
        Shell.Current.GoToAsync("//App/MainPage");
    }
}

 file MainPage.xaml


<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="My_Template.MainPage">

    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">

            <Image
                Source="dotnet_bot.png"
                SemanticProperties.Description="Cute dot net bot waving hi to you!"
                HeightRequest="200"
                HorizontalOptions="Center" />

            <Label
                Text="Hello, World!"
                SemanticProperties.HeadingLevel="Level1"
                FontSize="32"
                HorizontalOptions="Center" />

            <Label
                Text="Welcome to .NET Multi-platform App UI"
                SemanticProperties.HeadingLevel="Level2"
                SemanticProperties.Description="Welcome to dot net Multi platform App U I"
                FontSize="18"
                HorizontalOptions="Center" />

            <Button
                x:Name="CounterBtn"
                Text="Click me"
                SemanticProperties.Hint="Counts the number of times you click"
                Clicked="OnCounterClicked"
                HorizontalOptions="Center" />

        </VerticalStackLayout>
    </ScrollView>

</ContentPage>

 
file MainPage.xaml.cs

namespace My_Template;

public partial class MainPage : ContentPage
{
	int count = 0;

	public MainPage()
	{
		InitializeComponent();
	}

	private void OnCounterClicked(object sender, EventArgs e)
	{
		count++;

		if (count == 1)
			CounterBtn.Text = $"Clicked {count} time";
		else
			CounterBtn.Text = $"Clicked {count} times";

		SemanticScreenReader.Announce(CounterBtn.Text);
	}
}



 file AboutPage.xaml


<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="My_Template.AboutPage"
             Title="AboutPage">
    <VerticalStackLayout>
        <Label 
            Text="Welcome to .NET MAUI!"
            VerticalOptions="Center" 
            HorizontalOptions="Center" />
    </VerticalStackLayout>
</ContentPage>

file AboutPage.xaml.cs

namespace My_Template;

public partial class AboutPage : ContentPage
{
	public AboutPage()
	{
		InitializeComponent();
	}
}


jalankan f5