Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .browserslistrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
> 1%
last 2 versions
not dead
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VUE_APP_GOOGLE_MAPS_API_KEY=AIzaSyAJbU8-UcfU6YFUhMpDjGvSkCVBsZvEPmg
23 changes: 23 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist


# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
5 changes: 5 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
28 changes: 28 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "ip-test",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"@googlemaps/js-api-loader": "^1.12.11",
"core-js": "^3.6.5",
"instead": "^1.0.3",
"vue": "^2.6.11",
"vuetify": "^2.4.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"node-sass": "^4.12.0",
"sass": "~1.32.0",
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "~2.4.5",
"vue-template-compiler": "^2.6.11",
"vuetify-loader": "^1.7.0"
}
}
Binary file added public/favicon.ico
Binary file not shown.
19 changes: 19 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
129 changes: 129 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<template>
<v-app id="inspire">
<v-app-bar app color="white" flat>
<v-container class="py-0 fill-height">
<p class="pt-3 font-weight-black">Welcome to IP data search!</p>
<v-spacer></v-spacer>

<v-responsive max-width="260">
<v-text-field
dense
flat
hide-details
rounded
solo-inverted
placeholder="Enter your IP address"
v-model="ipAddress"
></v-text-field>
</v-responsive>
<v-btn
class="ml-4"
:elevation="0"
fab
x-small
dark
color="primary"
@click="getUserData"
>
<v-icon small>mdi-magnify</v-icon>
</v-btn>
</v-container>
</v-app-bar>

<v-main class="grey lighten-3">
<v-container>
<v-row>
<v-col cols="4">
<SideItems :rawItems="sideItemData" :fetching="fetching" />
</v-col>

<v-col>
<v-sheet min-height="70vh" rounded="lg">
<Map
v-if="!fetching && userData.latitude && userData.longitude"
:lat="this.userData.latitude"
:lng="this.userData.longitude"
/>
<div v-else-if="fetching">
<v-card-text class="progress-main">
<v-progress-circular
indeterminate
color="primary"
></v-progress-circular>
</v-card-text>
</div>
<div class="welcome" v-else-if="userData.error">
{{ userData.error }}
</div>
<div class="welcome" v-else>
Welcome, please enter a valid IP address above to see the map.
</div>
</v-sheet>
</v-col>
</v-row>
</v-container>
</v-main>
</v-app>
</template>

<script>
import SideItems from "./components/SideItems.vue";
import Map from "./components/Map.vue";
export default {
data: () => ({
ipAddress: "",
}),
computed: {
userData() {
const data = this.$store.getters.getUserData;

return data;
},
fetching() {
return this.$store.state.fetching;
},
sideItemData() {
if (!Object.keys(this.userData).length > 0) {
return;
}

const sideItemData = {
address: this.userData.ip,
country: this.userData.country,
region: this.userData.regionName,
city: this.userData.city,
timezone: this.userData.timezone,
currency: this.userData.currency,
};

return sideItemData;
},
},
components: {
SideItems,
Map,
},
methods: {
getUserData() {
this.$store.dispatch("fetchUserData", this.ipAddress);
},
},
};
</script>

<style>
.welcome {
width: 100%;
min-height: 70vh;
display: flex;
justify-content: center;
align-items: center;
}
.progress-main {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
min-height: 70vh;
}
</style>
Binary file added src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/assets/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 60 additions & 0 deletions src/components/Map.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<div class="map-container">
<div class="google-map" ref="googleMap"></div>
<template v-if="Boolean(this.google) && Boolean(this.map)">
<slot :google="google" :map="map" />
</template>
</div>
</template>

<script>
import { Loader } from "@googlemaps/js-api-loader";

export default {
props: ["lat", "lng"],

data() {
return {
google: null,
map: null,
};
},

async mounted() {
const loader = new Loader({
apiKey: process.env.VUE_APP_GOOGLE_MAPS_API_KEY,
});
const mapOptions = {
center: {
lat: this.lat || 0,
lng: this.lng || 0,
},
zoom: 14,
};

this.initializeMap(loader, mapOptions);
},

methods: {
initializeMap(loader, mapOptions) {
loader
.load()
.then((google) => {
const mapContainer = this.$refs.googleMap;
this.map = new google.maps.Map(mapContainer, mapOptions);
})
.catch((e) => {
console.log(e);
});
},
},
};
</script>

<style scoped>
.map-container,
.google-map {
width: 100%;
height: 500px;
}
</style>
65 changes: 65 additions & 0 deletions src/components/SideItems.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<v-sheet rounded="lg">
<v-list v-if="items && items.length > 0" color="transparent">
<v-list-item v-for="item in items" :key="item.value">
<v-list-item-content>
<v-list-item-title class="item">
<span class="item-name">
{{ item.label }}
</span>
: {{ item.value }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
<v-list class="progress" v-else-if="fetching" color="transparent">
<v-progress-circular indeterminate color="primary"></v-progress-circular>
</v-list>
<v-list v-else color="transparent">
<v-list-item>
<v-list-item-content>
<span class="item-name"> No items yet </span>
</v-list-item-content>
</v-list-item>
</v-list>
</v-sheet>
</template>

<script>
export default {
props: ["rawItems", "fetching"],
computed: {
items() {
if (this.rawItems?.address) {
return Object.keys(this.rawItems).map((key) => {
if (this.rawItems[key]) {
return {
label: key,
value: this.rawItems[key],
};
}
return null;
}).filter(el => el);
}
return {};
},
},
};
</script>

<style scoped>
.item {
font-size: 0.8rem;
}
.item-name {
font-weight: bold;
text-transform: capitalize;
}
.progress {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
</style>

12 changes: 12 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Vue from 'vue'
import App from './App.vue'
import store from './store'
import vuetify from './plugins/vuetify'

Vue.config.productionTip = false

new Vue({
store,
vuetify,
render: h => h(App)
}).$mount('#app')
7 changes: 7 additions & 0 deletions src/plugins/vuetify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Vue from 'vue';
import Vuetify from 'vuetify/lib/framework';

Vue.use(Vuetify);

export default new Vuetify({
});
Loading