chore: more work on cv and on main page
This commit is contained in:
parent
8bb068499b
commit
407b955950
@ -1,5 +1,5 @@
|
|||||||
spring.datasource.driver-class-name=org.postgresql.Driver
|
spring.datasource.driver-class-name=org.postgresql.Driver
|
||||||
spring.datasource.url=jdbc:postgresql://localhost:5432/applications
|
spring.datasource.url=jdbc:postgresql://kronos:5432/applications
|
||||||
spring.datasource.username=applications
|
spring.datasource.username=applications
|
||||||
spring.datasource.password=applications
|
spring.datasource.password=applications
|
||||||
|
|
||||||
|
@ -30,7 +30,9 @@ data class Application(
|
|||||||
var extra_data: String,
|
var extra_data: String,
|
||||||
var payrange: String,
|
var payrange: String,
|
||||||
var status: Int,
|
var status: Int,
|
||||||
var flairs: List<Flair>
|
var company: String,
|
||||||
|
var recruiter: String,
|
||||||
|
var flairs: List<Flair>,
|
||||||
) {
|
) {
|
||||||
companion object : RowMapper<Application> {
|
companion object : RowMapper<Application> {
|
||||||
override public fun mapRow(rs: ResultSet, rowNum: Int): Application {
|
override public fun mapRow(rs: ResultSet, rowNum: Int): Application {
|
||||||
@ -44,6 +46,8 @@ data class Application(
|
|||||||
rs.getString("extra_data"),
|
rs.getString("extra_data"),
|
||||||
rs.getString("payrange"),
|
rs.getString("payrange"),
|
||||||
rs.getInt("status"),
|
rs.getInt("status"),
|
||||||
|
rs.getString("company"),
|
||||||
|
rs.getString("recruiter"),
|
||||||
emptyList()
|
emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -60,6 +64,8 @@ data class FlairRequest(val id: String, val text: String)
|
|||||||
|
|
||||||
data class UpdateUrl(val id: String, val url: String)
|
data class UpdateUrl(val id: String, val url: String)
|
||||||
|
|
||||||
|
data class CVData(val company: String, val recruiter: String, val flairs: List<SimpleFlair>)
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
@RequestMapping("/api/application")
|
@RequestMapping("/api/application")
|
||||||
@ -69,6 +75,23 @@ class ApplicationsController(
|
|||||||
val flairService: FlairService
|
val flairService: FlairService
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@GetMapping(path = ["/cv/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||||
|
public fun getCV(
|
||||||
|
@PathVariable id: String,
|
||||||
|
@RequestHeader("token") token: String
|
||||||
|
): CVData? {
|
||||||
|
print("here!");
|
||||||
|
val user = sessionService.verifyToken(token);
|
||||||
|
|
||||||
|
val application = applicationService.findApplicationByIdNoUser(id);
|
||||||
|
|
||||||
|
if (application == null) return null;
|
||||||
|
|
||||||
|
val flairs = application.flairs.map {it.toFlairSimple()};
|
||||||
|
|
||||||
|
return CVData(application.company, application.recruiter, flairs);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(path = ["/text"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
@PostMapping(path = ["/text"], produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||||
public fun submitText(
|
public fun submitText(
|
||||||
@RequestBody submit: SubmitRequest,
|
@RequestBody submit: SubmitRequest,
|
||||||
@ -179,6 +202,8 @@ class ApplicationsController(
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
emptyList()
|
emptyList()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -435,13 +460,27 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) {
|
|||||||
return application
|
return application
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun findApplicationByIdNoUser(id: String): Application? {
|
||||||
|
var applications = db.query("select * from applications where id=?", arrayOf(id), Application).toList()
|
||||||
|
|
||||||
|
if (applications.size == 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
var application = applications[0]
|
||||||
|
|
||||||
|
application.flairs = flairService.listFromLinkApplicationId(application.id)
|
||||||
|
|
||||||
|
return application
|
||||||
|
}
|
||||||
|
|
||||||
public fun createApplication(user: UserDb, application: Application): Boolean {
|
public fun createApplication(user: UserDb, application: Application): Boolean {
|
||||||
if (this.findApplicationByUrl(user, application.url, application.unique_url) != null) {
|
if (this.findApplicationByUrl(user, application.url, application.unique_url) != null) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
db.update(
|
db.update(
|
||||||
"insert into applications (id, url, original_url, unique_url, title, user_id, extra_data, payrange, status) values (?, ?, ?, ?, ?, ?, ?, ?, ?);",
|
"insert into applications (id, url, original_url, unique_url, title, user_id, extra_data, payrange, status, company, recruiter) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
|
||||||
application.id,
|
application.id,
|
||||||
application.url,
|
application.url,
|
||||||
application.original_url,
|
application.original_url,
|
||||||
@ -451,6 +490,8 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) {
|
|||||||
application.extra_data,
|
application.extra_data,
|
||||||
application.payrange,
|
application.payrange,
|
||||||
application.status,
|
application.status,
|
||||||
|
application.company,
|
||||||
|
application.recruiter
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -476,7 +517,7 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) {
|
|||||||
|
|
||||||
public fun update(application: Application): Application {
|
public fun update(application: Application): Application {
|
||||||
db.update(
|
db.update(
|
||||||
"update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, status=? where id=?",
|
"update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, status=?, company=?, recruiter=? where id=?",
|
||||||
application.url,
|
application.url,
|
||||||
application.original_url,
|
application.original_url,
|
||||||
application.unique_url,
|
application.unique_url,
|
||||||
@ -485,6 +526,8 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) {
|
|||||||
application.extra_data,
|
application.extra_data,
|
||||||
application.payrange,
|
application.payrange,
|
||||||
application.status,
|
application.status,
|
||||||
|
application.company,
|
||||||
|
application.recruiter,
|
||||||
application.id,
|
application.id,
|
||||||
)
|
)
|
||||||
return application
|
return application
|
||||||
|
@ -68,6 +68,12 @@ class FlairController(val sessionService: SessionService, val flairService: Flai
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class SimpleFlair(
|
||||||
|
val name: String,
|
||||||
|
val description: String,
|
||||||
|
val color: String,
|
||||||
|
)
|
||||||
|
|
||||||
data class Flair(
|
data class Flair(
|
||||||
var id: String,
|
var id: String,
|
||||||
var user_id: String,
|
var user_id: String,
|
||||||
@ -88,6 +94,10 @@ data class Flair(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun toFlairSimple(): SimpleFlair {
|
||||||
|
return SimpleFlair(this.name, this.description, this.color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FlairLink(var id: String, var application_id: String, var flair_id: String)
|
data class FlairLink(var id: String, var application_id: String, var flair_id: String)
|
||||||
@ -134,14 +144,14 @@ public class FlairService(val db: JdbcTemplate) {
|
|||||||
|
|
||||||
public fun listFromLinkApplicationId(id: String): List<Flair> =
|
public fun listFromLinkApplicationId(id: String): List<Flair> =
|
||||||
db.query(
|
db.query(
|
||||||
"select f.id, f.user_id, f.color, f.name, f.expr, f.description from flair_link as fl inner join flair as f on f.id = fl.flair_id where application_id=?;",
|
"select f.id, f.user_id, f.color, f.name, f.expr, f.description from flair_link as fl inner join flair as f on f.id = fl.flair_id where application_id=? order by name asc;",
|
||||||
arrayOf(id),
|
arrayOf(id),
|
||||||
Flair
|
Flair
|
||||||
)
|
)
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
public fun listUser(user: UserDb): List<Flair> =
|
public fun listUser(user: UserDb): List<Flair> =
|
||||||
db.query("select * from flair where user_id=?;", arrayOf(user.id), Flair).toList()
|
db.query("select * from flair where user_id=? order by name asc;", arrayOf(user.id), Flair).toList()
|
||||||
|
|
||||||
public fun getById(user: UserDb, id: String): Flair? {
|
public fun getById(user: UserDb, id: String): Flair? {
|
||||||
val items =
|
val items =
|
||||||
|
@ -16,6 +16,8 @@ create table if not exists applications (
|
|||||||
url text not null,
|
url text not null,
|
||||||
original_url text,
|
original_url text,
|
||||||
unique_url text,
|
unique_url text,
|
||||||
|
company text,
|
||||||
|
recruiter text,
|
||||||
title text,
|
title text,
|
||||||
user_id text,
|
user_id text,
|
||||||
extra_data text,
|
extra_data text,
|
||||||
|
@ -1,20 +1,28 @@
|
|||||||
browser.runtime.onMessage.addListener(function (message) {
|
browser.runtime.onMessage.addListener((message) => {
|
||||||
if (message.type === "MY_GET_URL_R") {
|
if (message.type === "MY_GET_URL_R") {
|
||||||
window.postMessage(message);
|
window.postMessage(message);
|
||||||
} else if (message.type === "GET_DATA_FROM_PAGE") {
|
} else if (message.type === "GET_DATA_FROM_PAGE") {
|
||||||
let company = document
|
const company = document
|
||||||
.querySelector('header[data-test="job-details-header"]')
|
.querySelector('header[data-test="job-details-header"]')
|
||||||
.children[0].children[0].querySelector("h4").innerHTML;
|
.children[0].children[0].querySelector("h4").innerHTML;
|
||||||
let jobTitle = document
|
const jobTitle = document
|
||||||
.querySelector('header[data-test="job-details-header"]')
|
.querySelector('header[data-test="job-details-header"]')
|
||||||
.querySelector("h1").innerHTML;
|
.querySelector("h1").innerHTML;
|
||||||
browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle });
|
|
||||||
|
let money = ""
|
||||||
|
|
||||||
|
const moneySectionNode = document.querySelector('section>section');
|
||||||
|
if (moneySectionNode && ["Base pay range", "Base pay"].includes(moneySectionNode.querySelector('h2').textContent)) {
|
||||||
|
money = moneySectionNode.querySelector("div>div>div").children[1]?.textContent ?? ''
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle, money });
|
||||||
} else if (message.type === "GOT_INFO_R") {
|
} else if (message.type === "GOT_INFO_R") {
|
||||||
window.postMessage(message);
|
window.postMessage(message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("message", function (e) {
|
window.addEventListener("message", (e) => {
|
||||||
if (e.data.type === "MY_GET_URL") {
|
if (e.data.type === "MY_GET_URL") {
|
||||||
browser.runtime.sendMessage({ type: "MY_GET_URL" });
|
browser.runtime.sendMessage({ type: "MY_GET_URL" });
|
||||||
} else if (e.data.type === "HAS_EXTENSION_Q") {
|
} else if (e.data.type === "HAS_EXTENSION_Q") {
|
||||||
|
@ -32,6 +32,8 @@ export type Application = {
|
|||||||
extra_data: string;
|
extra_data: string;
|
||||||
payrange: string;
|
payrange: string;
|
||||||
status: number;
|
status: number;
|
||||||
|
recruiter: string;
|
||||||
|
company: string;
|
||||||
flairs: Flair[];
|
flairs: Flair[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
let ready = $state(false);
|
let ready = $state(false);
|
||||||
|
|
||||||
const { children }: { children: Snippet } = $props();
|
const { children, redirect }: { children: Snippet, redirect: string } = $props();
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
ready = userStore.checkLogin();
|
ready = userStore.checkLogin(redirect);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -22,23 +22,19 @@ function createUserStore() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
checkLogin(redirect = true) {
|
checkLogin(redirect = "/login") {
|
||||||
console.log('test1');
|
|
||||||
if (user !== undefined) {
|
if (user !== undefined) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('test2');
|
|
||||||
if (redirect) {
|
if (redirect) {
|
||||||
goto('/login');
|
goto(redirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('test3');
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
get isLoggedIn() {
|
get isLoggedIn() {
|
||||||
console.log(user);
|
|
||||||
return user !== undefined;
|
return user !== undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import AppliyedList from './AppliyedList.svelte';
|
import AppliyedList from './AppliyedList.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<HasUser>
|
<HasUser redirect="/cv">
|
||||||
<div class="flex flex-col h-[100vh]">
|
<div class="flex flex-col h-[100vh]">
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<div class="w-full px-4 grow h-full gap-3 flex flex-col">
|
<div class="w-full px-4 grow h-full gap-3 flex flex-col">
|
||||||
|
@ -23,7 +23,14 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const f = new RegExp(filter, 'ig');
|
const f = new RegExp(filter, 'ig');
|
||||||
return i.title.match(f);
|
|
||||||
|
let x = i.title;
|
||||||
|
|
||||||
|
if (i.company) {
|
||||||
|
x = `${x} @ ${i.company}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.match(f);
|
||||||
}) as item}
|
}) as item}
|
||||||
<div
|
<div
|
||||||
class="card p-2 my-2 bg-slate-100"
|
class="card p-2 my-2 bg-slate-100"
|
||||||
@ -39,8 +46,16 @@
|
|||||||
<div class:animate-pulse={applicationStore.dragging?.id === item.id}>
|
<div class:animate-pulse={applicationStore.dragging?.id === item.id}>
|
||||||
<h2 class="text-lg text-blue-500">
|
<h2 class="text-lg text-blue-500">
|
||||||
{item.title}
|
{item.title}
|
||||||
|
{#if item.company}
|
||||||
|
<div class="text-violet-800" >
|
||||||
|
@ {item.company}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</h2>
|
</h2>
|
||||||
<a href={item.url} class="text-violet-600 overflow-hidden whitespace-nowrap block">
|
<a
|
||||||
|
href={item.url}
|
||||||
|
class="text-violet-600 overflow-hidden whitespace-nowrap block"
|
||||||
|
>
|
||||||
{item.url}
|
{item.url}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { get } from '$lib/utils';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import Flair from '../flair/Flair.svelte';
|
||||||
|
|
||||||
let id: string | undefined | null;
|
let id: string | undefined | null;
|
||||||
|
|
||||||
@ -11,9 +13,39 @@
|
|||||||
loadData();
|
loadData();
|
||||||
});
|
});
|
||||||
|
|
||||||
const application = undefined;
|
type SimpleFlair = {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
async function loadData() {}
|
type Application = {
|
||||||
|
flairs: SimpleFlair[];
|
||||||
|
};
|
||||||
|
|
||||||
|
let application: Application | undefined = $state(undefined);
|
||||||
|
|
||||||
|
async function loadData() {
|
||||||
|
try {
|
||||||
|
application = await get(`application/cv/${id}`);
|
||||||
|
|
||||||
|
application.flairs.sort((a, b) => {
|
||||||
|
if (a.description && b.description) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (a.description) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b.description) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log('TODO show this to the user', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -21,10 +53,10 @@
|
|||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="flex items-center w-full flex-col">
|
<div class="flex items-center w-full flex-col">
|
||||||
<div class="max-w-[210mm] px-5 py-16">
|
<div class="py-10 w-[210mm]">
|
||||||
<div class="bg-white rounded-lg p-3">
|
<div class="bg-white rounded-lg p-3">
|
||||||
<div class="w-full flex">
|
<div class="w-full flex">
|
||||||
<h1 class="dark:text-white text-black text-5xl">Andre Henriques</h1>
|
<h1 class="text-black text-5xl">Andre Henriques</h1>
|
||||||
<div class="flex-grow"></div>
|
<div class="flex-grow"></div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<ul>
|
<ul>
|
||||||
@ -34,9 +66,7 @@
|
|||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="px-1">
|
<li class="px-1">
|
||||||
<a class="underline" href="tel:+4407823391342"
|
<a class="underline" href="tel:+4407823391342">+44 0 782339 1342</a>
|
||||||
>+44 0 782339 1342</a
|
|
||||||
>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -56,42 +86,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{#if application}
|
{#if application}
|
||||||
<div class="p-5"></div>
|
<h2 class="text-white p-3 text-4xl">
|
||||||
<div>TODO: Application Information</div>
|
👋 Hello
|
||||||
|
{#if application.recruiter}
|
||||||
|
<span class="font-bold">{application.recruiter}</span> @ <span class="font-bold">{application.company}</span>
|
||||||
|
{:else if application.company}
|
||||||
|
recruiter @ <span class="font-bold">{application.company}</span>
|
||||||
|
{/if}
|
||||||
|
</h2>
|
||||||
|
<div class="p-3 bg-white w-[210mm] rounded-lg">
|
||||||
|
<h1>Your Ad / My skills</h1>
|
||||||
|
<div class="flex flex-wrap gap-2 py-2">
|
||||||
|
{#each application.flairs as flair}
|
||||||
|
<div class="min-w-0 {flair.description ? 'flex-grow w-full' : ''}">
|
||||||
|
<div class="p-2 rounded-lg" style="background: {flair.color};">
|
||||||
|
{flair.name}
|
||||||
|
{#if flair.description}
|
||||||
|
<div class="bg-white my-1 p-1 rounded-md">{flair.description}</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="p-5"></div>
|
<div class="p-5"></div>
|
||||||
<div class="text-black bg-white p-4 rounded-lg">
|
<div class="px-5 w-[210mm]">
|
||||||
<h2 class="pb-2 text-3xl">Work Expericence</h2>
|
<h2 class="pb-2 text-4xl font-bold text-white">Work Expericence</h2>
|
||||||
<div>
|
</div>
|
||||||
<div>
|
|
||||||
|
<div class="p-2"></div>
|
||||||
|
|
||||||
|
<div class="w-[100vw] flex items-center flex-col">
|
||||||
|
<div class="p-3 bg-white w-[210mm] rounded-lg">
|
||||||
<h1>Senior Software Developer @ Planum Solucoes</h1>
|
<h1>Senior Software Developer @ Planum Solucoes</h1>
|
||||||
<div class="ml-5">
|
<div class="ml-5">
|
||||||
<h2>4 year - May 2020 - Present</h2>
|
<h2>4 year - May 2020 - Present</h2>
|
||||||
<h3>Working with:</h3>
|
<h3>Developed various projects:</h3>
|
||||||
<ul class="pl-5 list-disc">
|
<ul class="pl-5 list-disc">
|
||||||
<li>Python</li>
|
<li>Developing various websites using React and Svelte.</li>
|
||||||
<li>Jenkins</li>
|
<li>Interacting with a RESTful API</li>
|
||||||
<li>GitLab CI</li>
|
<li>Implemented an ORM system using Java Reflection</li>
|
||||||
<li>Ansible</li>
|
<li>Implemented automatic deployment with GitLab CI/CD tools.</li>
|
||||||
<li>Docker</li>
|
<li>Linux Server Administration</li>
|
||||||
</ul>
|
<li>Technologies used: React, WebRTC, WebSockets, Rest, Google Maps AP</li>
|
||||||
<h3>Associated Software Developer / DevOps Engineer:</h3>
|
|
||||||
<ul class="pl-5 list-disc">
|
|
||||||
<li>Developed web-based tools for the DevOps team to use</li>
|
|
||||||
<li>
|
|
||||||
Updated Jenkins pipelines that the team uses to manage one of the
|
|
||||||
most important pipelines that the team manages.
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
Created new scripts that were used to clean up multiple terabytes of
|
|
||||||
unused data that led to improvements in the performance of the other
|
|
||||||
scripts running on the same server as well as the performance of the
|
|
||||||
backup system
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-2"></div>
|
||||||
|
|
||||||
|
<div class="w-[100vw] flex items-center flex-col">
|
||||||
|
<div class="text-black w-[210mm] bg-white p-4 rounded-lg">
|
||||||
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<h1>Associate Devops Engineer @ Sky UK</h1>
|
<h1>Associate Devops Engineer @ Sky UK</h1>
|
||||||
<div class="ml-5">
|
<div class="ml-5">
|
||||||
@ -122,8 +172,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="p-5"></div>
|
<div class="p-5"></div>
|
||||||
<div class="bg-white p-3 text-black rounded-lg">
|
|
||||||
|
<div class="bg-white p-3 text-black rounded-lg w-[210mm]">
|
||||||
<h2 class="pb-2 text-3xl">Education</h2>
|
<h2 class="pb-2 text-3xl">Education</h2>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
@ -134,9 +187,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--div class="p-5"></div>
|
<!--div class="p-5"></div>
|
||||||
<div>TODO: Previous projetcs</div -->
|
<div>TODO: Previous projetcs</div -->
|
||||||
<!-- div class="p-5"></div>
|
<!-- div class="p-5"></div>
|
||||||
<div>TODO: Info form</div -->
|
<div>TODO: Info form</div -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
22
site/src/routes/work-area/DropZone.svelte
Normal file
22
site/src/routes/work-area/DropZone.svelte
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { applicationStore } from '$lib/ApplicationsStore.svelte';
|
||||||
|
import { preventDefault } from '$lib/utils';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
|
let { ondrop, icon, children }: { ondrop: () => void, icon: string, children: Snippet } = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="grid place-items-center w-full card p-2 rounded-lg"
|
||||||
|
role="none"
|
||||||
|
ondragover={preventDefault(() => {})}
|
||||||
|
ondragenter={preventDefault(() => {})}
|
||||||
|
{ondrop}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="bi bi-{icon} text-7xl absolute"
|
||||||
|
class:animate-bounce={applicationStore.dragging}
|
||||||
|
></span>
|
||||||
|
<span class="bi bi-{icon} text-7xl opacity-0"></span>
|
||||||
|
<div class="text-xl">{@render children()}</div>
|
||||||
|
</div>
|
@ -11,6 +11,7 @@
|
|||||||
import ExtractTextDialog from './ExtractTextDialog.svelte';
|
import ExtractTextDialog from './ExtractTextDialog.svelte';
|
||||||
import Flair from '../flair/Flair.svelte';
|
import Flair from '../flair/Flair.svelte';
|
||||||
import NewUrlDialog from './NewUrlDialog.svelte';
|
import NewUrlDialog from './NewUrlDialog.svelte';
|
||||||
|
import DropZone from './DropZone.svelte';
|
||||||
import { userStore } from '$lib/UserStore.svelte';
|
import { userStore } from '$lib/UserStore.svelte';
|
||||||
|
|
||||||
let activeItem: Application | undefined = $state();
|
let activeItem: Application | undefined = $state();
|
||||||
@ -42,6 +43,7 @@
|
|||||||
|
|
||||||
if (item.status === 0) {
|
if (item.status === 0) {
|
||||||
openWindow(item.url);
|
openWindow(item.url);
|
||||||
|
openCV(item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -76,6 +78,14 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openCV(id?: string) {
|
||||||
|
window.open(
|
||||||
|
`/cv?id=${id ?? activeItem!.id}`,
|
||||||
|
'cv viwer',
|
||||||
|
`location,height=${window.screen.height},width=${window.screen.width},scrollbars,status,toolbar,menubar,popup`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
async function loadActive() {
|
async function loadActive() {
|
||||||
try {
|
try {
|
||||||
activeItem = await get('application/active');
|
activeItem = await get('application/active');
|
||||||
@ -107,7 +117,9 @@
|
|||||||
|
|
||||||
function setExtData() {
|
function setExtData() {
|
||||||
if (!lastExtData || !activeItem) return;
|
if (!lastExtData || !activeItem) return;
|
||||||
activeItem.title = `${lastExtData.company} - ${lastExtData.jobTitle}`;
|
activeItem.title = lastExtData.jobTitle;
|
||||||
|
activeItem.company = lastExtData.company;
|
||||||
|
activeItem.payrange = lastExtData.money;
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
save();
|
save();
|
||||||
lastExtData = undefined;
|
lastExtData = undefined;
|
||||||
@ -203,6 +215,16 @@
|
|||||||
{statusMapping}
|
{statusMapping}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<fieldset class="grow">
|
||||||
|
<label class="flabel" for="title">Company</label>
|
||||||
|
<input class="finput" id="title" bind:value={activeItem.company} onchange={save} />
|
||||||
|
</fieldset>
|
||||||
|
<fieldset class="grow">
|
||||||
|
<label class="flabel" for="title">Recruiter</label>
|
||||||
|
<input class="finput" id="title" bind:value={activeItem.recruiter} onchange={save} />
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<label class="flabel" for="title">Title</label>
|
<label class="flabel" for="title">Title</label>
|
||||||
<input class="finput" id="title" bind:value={activeItem.title} onchange={save} />
|
<input class="finput" id="title" bind:value={activeItem.title} onchange={save} />
|
||||||
@ -262,10 +284,7 @@
|
|||||||
>
|
>
|
||||||
Open
|
Open
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button class="btn-primary" onclick={openCV}>
|
||||||
class="btn-primary"
|
|
||||||
onclick={() => window.open(`/cv?id=${activeItem!.id}`, '_blank')}
|
|
||||||
>
|
|
||||||
Open CV
|
Open CV
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-primary" onclick={() => extractTokens.showModal()}>
|
<button class="btn-primary" onclick={() => extractTokens.showModal()}>
|
||||||
@ -284,100 +303,49 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if applicationStore.dragging}
|
{#if applicationStore.dragging}
|
||||||
<div class="flex w-full flex-grow rounded-lg p-1 gap-2">
|
<div class="flex w-full flex-grow rounded-lg p-1 gap-2">
|
||||||
|
|
||||||
|
<!-- Do nothing -->
|
||||||
|
<DropZone icon="box-arrow-down" ondrop={() => {
|
||||||
|
moveStatus(ApplicationStatus.ToApply);
|
||||||
|
}}>
|
||||||
|
To apply
|
||||||
|
</DropZone>
|
||||||
|
|
||||||
<!-- Ignore -->
|
<!-- Ignore -->
|
||||||
<div
|
<DropZone icon="trash-fill" ondrop={() => {
|
||||||
class="grid place-items-center w-full card p-2 rounded-lg"
|
|
||||||
role="none"
|
|
||||||
ondragover={preventDefault(() => {})}
|
|
||||||
ondragenter={preventDefault(() => {})}
|
|
||||||
ondrop={() => {
|
|
||||||
moveStatus(ApplicationStatus.Ignore);
|
moveStatus(ApplicationStatus.Ignore);
|
||||||
}}
|
}}>
|
||||||
>
|
Ignore it
|
||||||
<span
|
</DropZone>
|
||||||
class="bi bi-trash-fill text-7xl absolute"
|
|
||||||
class:animate-bounce={applicationStore.dragging}
|
|
||||||
></span>
|
|
||||||
<span class="bi bi-trash-fill text-7xl opacity-0"></span>
|
|
||||||
<div class="text-xl">Drop Application Ignore it.</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Expired -->
|
<!-- Expired -->
|
||||||
<div
|
<DropZone icon="clock-fill text-orange-500" ondrop={() => {
|
||||||
class="grid place-items-center w-full card p-2 rounded-lg"
|
|
||||||
role="none"
|
|
||||||
ondragover={preventDefault(() => {})}
|
|
||||||
ondragenter={preventDefault(() => {})}
|
|
||||||
ondrop={() => {
|
|
||||||
if (activeItem && activeItem.status === ApplicationStatus.Expired) {
|
if (activeItem && activeItem.status === ApplicationStatus.Expired) {
|
||||||
moveStatus(ApplicationStatus.ToApply);
|
moveStatus(ApplicationStatus.ToApply);
|
||||||
} else {
|
} else {
|
||||||
moveStatus(ApplicationStatus.Expired);
|
moveStatus(ApplicationStatus.Expired);
|
||||||
}
|
}
|
||||||
}}
|
}}>
|
||||||
>
|
Mark as expired
|
||||||
<span
|
</DropZone>
|
||||||
class="bi bi-clock-fill text-7xl text-orange-500 absolute"
|
|
||||||
class:animate-bounce={applicationStore.dragging}
|
|
||||||
></span>
|
|
||||||
<span class="bi bi-clock-fill text-7xl text-orange-500 opacity-0"></span>
|
|
||||||
<div class="text-orange-500 text-xl">Mark as expired.</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Repeated -->
|
<!-- Repeated -->
|
||||||
<div
|
<DropZone icon="trash-fill text-danger" ondrop={() => remove()}>
|
||||||
class="grid place-items-center w-full card p-2 rounded-lg"
|
Delete it
|
||||||
role="none"
|
</DropZone>
|
||||||
ondragover={preventDefault(() => {})}
|
|
||||||
ondragenter={preventDefault(() => {})}
|
|
||||||
ondrop={() => {
|
|
||||||
remove();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="bi bi-trash-fill text-7xl text-danger absolute"
|
|
||||||
class:animate-bounce={applicationStore.dragging}
|
|
||||||
></span>
|
|
||||||
<span class="bi bi-trash-fill text-7xl text-danger opacity-0"></span>
|
|
||||||
<div class="text-danger text-xl">This is repeated</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Applyed -->
|
<!-- Applyed -->
|
||||||
<div
|
<DropZone icon="server text-confirm" ondrop={async () => {
|
||||||
class="grid place-items-center w-full card p-2 rounded-lg"
|
|
||||||
role="none"
|
|
||||||
ondragover={preventDefault(() => {})}
|
|
||||||
ondragenter={preventDefault(() => {})}
|
|
||||||
ondrop={async () => {
|
|
||||||
await moveStatus(ApplicationStatus.Applyed);
|
await moveStatus(ApplicationStatus.Applyed);
|
||||||
applicationStore.loadAplyed(true);
|
applicationStore.loadAplyed(true);
|
||||||
}}
|
}}>
|
||||||
>
|
Apply
|
||||||
<span
|
</DropZone>
|
||||||
class="bi bi-server text-7xl text-confirm absolute"
|
|
||||||
class:animate-bounce={applicationStore.dragging}
|
|
||||||
></span>
|
|
||||||
<span class="bi bi-server text-7xl text-confirm opacity-0"></span>
|
|
||||||
<div class="text-confirm text-xl">Apply</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Rejected -->
|
<!-- Rejected -->
|
||||||
<div
|
<DropZone icon="fire text-danger" ondrop={() => moveStatus(ApplicationStatus.ApplyedButSaidNo)}>
|
||||||
class="grid place-items-center w-full card p-2 rounded-lg"
|
I was rejeted :(
|
||||||
role="none"
|
</DropZone>
|
||||||
ondragover={preventDefault(() => {})}
|
|
||||||
ondragenter={preventDefault(() => {})}
|
|
||||||
ondrop={() => {
|
|
||||||
moveStatus(ApplicationStatus.ApplyedButSaidNo);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
class="bi bi-fire text-danger text-7xl absolute"
|
|
||||||
class:animate-bounce={applicationStore.dragging}
|
|
||||||
></span>
|
|
||||||
<span class="bi bi-fire text-7xl text-danger opacity-0"></span>
|
|
||||||
<div class="text-danger text-xl">I was rejeted :(.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
|
Loading…
Reference in New Issue
Block a user