Initial commit, framework/frontend assets setup
This commit is contained in:
commit
9d9858bb37
32 changed files with 4651 additions and 0 deletions
105
resources/scripts/app/Subnet.vue
Normal file
105
resources/scripts/app/Subnet.vue
Normal file
|
@ -0,0 +1,105 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import axios from 'axios';
|
||||
import { useToast } from 'vue-toast-notification';
|
||||
import Button from '@app/components/Button.vue';
|
||||
import Input from '@app/components/Input.vue';
|
||||
|
||||
const $toast = useToast();
|
||||
|
||||
const subnet = ref( '' );
|
||||
const isLoading = ref( false );
|
||||
const hasResults = ref( false );
|
||||
const results = ref( {} );
|
||||
|
||||
/**
|
||||
* Load subnet data based on input
|
||||
*/
|
||||
const getSubnetData = () => {
|
||||
// Enable loading icon
|
||||
isLoading.value = true;
|
||||
|
||||
// Create post data
|
||||
const postData = new FormData();
|
||||
postData.append( 'subnet', subnet.value );
|
||||
|
||||
// Send request
|
||||
axios.post( '/api/subnet', postData ).then( (response) => {
|
||||
const { data } = response;
|
||||
|
||||
// Load new block
|
||||
isLoading.value = false;
|
||||
hasResults.value = true;
|
||||
results.value = data.result;
|
||||
} ).catch( (error) => {
|
||||
isLoading.value = false;
|
||||
|
||||
// Show error message
|
||||
const errorMessage = error.response.data.message || 'Something went wrong.';
|
||||
$toast.error(errorMessage, {
|
||||
position: 'top',
|
||||
duration: 1500,
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset form by resetting al vars
|
||||
*/
|
||||
const resetForm = () => {
|
||||
subnet.value = '';
|
||||
isLoading.value = false;
|
||||
hasResults.value = false;
|
||||
results.value = {};
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center items-center min-h-screen">
|
||||
<div class="sm:w-3/4 md:w-2/3 lg:w-2/4 xl:w-2/5 2xl:w-1/5 -translate-y-24">
|
||||
<img src="https://www.bit.nl/assets/images/bit_logo_white.png" alt="BIT Logo" class="mx-auto w-52 mb-6">
|
||||
|
||||
<div class="bg-white p-10 rounded-xl shadow-2xl">
|
||||
<h1 class="text-2xl font-semibold text-center mb-6">IPcalc-u-later</h1>
|
||||
|
||||
<div v-if="hasResults">
|
||||
<table class="min-w-full table-auto text-left">
|
||||
<tbody>
|
||||
<tr class="">
|
||||
<td class="py-2 font-medium">Network Address</td>
|
||||
<td class="py-2 text-right">{{ results.network }}</td>
|
||||
</tr>
|
||||
<tr class="">
|
||||
<td class="py-2 font-medium">First Usable IP</td>
|
||||
<td class="py-2 text-right">{{ results.first }}</td>
|
||||
</tr>
|
||||
<tr class="">
|
||||
<td class="py-2 font-medium">Last Usable IP</td>
|
||||
<td class="py-2 text-right">{{ results.last }}</td>
|
||||
</tr>
|
||||
<tr class="">
|
||||
<td class="py-2 font-medium">Number of Usable Hosts</td>
|
||||
<td class="py-2 text-right">{{ results.hosts }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<Button @click="resetForm">Reset</Button>
|
||||
</div>
|
||||
|
||||
<form v-else method="post" class="text-left" @submit.prevent="getSubnetData">
|
||||
<div class="mb-4">
|
||||
<label for="subnet" class="block text-sm font-medium">Enter Subnet</label>
|
||||
|
||||
<Input name="subnet" v-model="subnet" placeholder="(e.g. 192.168.1.0/24 or 2001:db8::/64)" />
|
||||
</div>
|
||||
|
||||
<Button type="submit">
|
||||
<i class="fa-solid fa-circle-notch fa-pulse" v-if="isLoading"></i>
|
||||
<span v-else>Submit</span>
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
14
resources/scripts/app/components/Button.vue
Normal file
14
resources/scripts/app/components/Button.vue
Normal file
|
@ -0,0 +1,14 @@
|
|||
<script setup lang="ts">
|
||||
defineProps( {
|
||||
type: {
|
||||
type: String,
|
||||
default: "button"
|
||||
}
|
||||
} )
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button :type class="w-full py-2 mt-4 bg-primary text-white rounded-lg hover:bg-primary-light focus:outline-none focus:ring-2 focus:ring-primary-light">
|
||||
<slot />
|
||||
</button>
|
||||
</template>
|
45
resources/scripts/app/components/Input.vue
Normal file
45
resources/scripts/app/components/Input.vue
Normal file
|
@ -0,0 +1,45 @@
|
|||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits, ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps( {
|
||||
modelValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "",
|
||||
}
|
||||
} );
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const inputValue = ref(props.modelValue);
|
||||
const updateValue = () => {
|
||||
emit('update:modelValue', inputValue.value);
|
||||
};
|
||||
|
||||
// If the modelValue prop changes externally, update the local ref
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
inputValue.value = newVal;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<input
|
||||
type="text"
|
||||
:id="name"
|
||||
:name="name"
|
||||
class="mt-1 p-2 w-full border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
|
||||
:placeholder
|
||||
:required
|
||||
v-model="inputValue"
|
||||
@input="updateValue"
|
||||
>
|
||||
</template>
|
21
resources/scripts/main.ts
Normal file
21
resources/scripts/main.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import '@styles/main.scss';
|
||||
import { createApp } from 'vue';
|
||||
import ToastPlugin from 'vue-toast-notification';
|
||||
import 'vue-toast-notification/dist/theme-default.css';
|
||||
|
||||
// Import components
|
||||
import Subnet from '@app/Subnet.vue';
|
||||
|
||||
// Initialize vue app
|
||||
function initializeApp(element: string, component: any): void {
|
||||
const app = createApp(component);
|
||||
|
||||
// Use plugins and global settings
|
||||
app.use(ToastPlugin);
|
||||
|
||||
// Mount the app to a specific DOM element
|
||||
app.mount(element);
|
||||
}
|
||||
|
||||
// Load components
|
||||
initializeApp('#subnet-app', Subnet);
|
3
resources/styles/main.scss
Normal file
3
resources/styles/main.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
14
resources/views/subnet.php
Normal file
14
resources/views/subnet.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>IPcalc-u-later</title>
|
||||
|
||||
<link rel="stylesheet" href="/dist/css/app.css">
|
||||
<script type="module" src="/dist/scripts/app.js"></script>
|
||||
</head>
|
||||
<body class="bg-gradient-to-r from-primary to-primary-light">
|
||||
<div id="subnet-app"></div>
|
||||
<script src="https://kit.fontawesome.com/02e67c0aed.js" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue