Initial commit, framework/frontend assets setup

This commit is contained in:
Maarten 2024-11-25 18:59:11 +01:00
commit 9d9858bb37
32 changed files with 4651 additions and 0 deletions

View 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>

View 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>

View 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
View 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);

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View 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>