Saturday, December 14, 2024

TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER

Selamat datang di blog ali-mahdali.blogstpot.com, kali ini penulis memposting artikel yang berjudul TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER yang mana artikel ini dapat kalian akses melalui alamat : https://ali-mahdali.blogspot.com/2024/12/template-vuetify-vue-2-dan-vue-router.html,
tanpa basa-basi yuk disimak artikelnya dibawah ini. Selamat membaca

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>


Sebelum melanjutkan membaca artikel ini, berikut adalah artikel yang berkaitan dengan judul artikel TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER :
ok, silahkan lanjut membaca.

Terimakasih atas kunjungan Anda dan Karena telah sudi membaca artikel yang berjudul TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER.Tak Lengkap Rasanya Jika Kunjungan Anda di Blog ini Tanpa Meninggalkan Komentar, untuk Itu Silahkan Berikan Kritik dan saran Pada Kotak Komentar di bawah. Anda boleh menyebarluaskan atau mengcopy artikel TEMPLATE VUETIFY, VUE 2 DAN VUE-ROUTER ini jika memang bermanfaat bagi anda, namun jangan lupa untuk mencantumkan link sumbernya. Terima Kasih, Happy Blogging :)


EmoticonEmoticon