chore: added the ability for recruiter to search skills in the cv page

This commit is contained in:
Andre Henriques 2024-10-06 17:37:49 +01:00
parent 92e3b91176
commit dd9d174449
4 changed files with 143 additions and 42 deletions

View File

@ -4,5 +4,8 @@ spring.datasource.username=applications
spring.datasource.password=applications spring.datasource.password=applications
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
# Disable the trace on the error responses
server.error.include-stacktrace=never
# spring.sql.init.schema-locations=classpath:schema.sql # spring.sql.init.schema-locations=classpath:schema.sql
# spring.sql.init.mode=always # spring.sql.init.mode=always

View File

@ -3,6 +3,7 @@ package com.andr3h3nriqu3s.applications
import java.sql.ResultSet import java.sql.ResultSet
import java.util.UUID import java.util.UUID
import org.springframework.http.MediaType import org.springframework.http.MediaType
import org.springframework.http.HttpStatus
import org.springframework.jdbc.core.JdbcTemplate import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.jdbc.core.RowMapper import org.springframework.jdbc.core.RowMapper
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
@ -15,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController import org.springframework.web.bind.annotation.RestController
import org.springframework.web.server.ResponseStatusException
data class CreateFlair( data class CreateFlair(
var color: String, var color: String,
@ -26,7 +28,11 @@ data class CreateFlair(
@RestController @RestController
@ControllerAdvice @ControllerAdvice
@RequestMapping("/api/flair") @RequestMapping("/api/flair")
class FlairController(val sessionService: SessionService, val flairService: FlairService) { class FlairController(
val sessionService: SessionService,
val flairService: FlairService,
val applicationService: ApplicationService
) {
@PutMapping(path = ["/"], produces = [MediaType.APPLICATION_JSON_VALUE]) @PutMapping(path = ["/"], produces = [MediaType.APPLICATION_JSON_VALUE])
public fun create( public fun create(
@ -61,6 +67,16 @@ class FlairController(val sessionService: SessionService, val flairService: Flai
return flairService.listUser(user) return flairService.listUser(user)
} }
@GetMapping(path = ["/simple/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
public fun listSimple(@PathVariable id: String): List<SimpleFlair> {
var application = applicationService.findApplicationByIdNoUser(id)
if (application == null) {
throw ResponseStatusException(HttpStatus.NOT_FOUND, "Application Not Found", null)
}
return flairService.listUserId(application.user_id).map { it.toFlairSimple() }
}
@DeleteMapping(path = ["/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE]) @DeleteMapping(path = ["/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE])
public fun delete(@PathVariable id: String, @RequestHeader("token") token: String): Flair { public fun delete(@PathVariable id: String, @RequestHeader("token") token: String): Flair {
val user = sessionService.verifyTokenThrow(token) val user = sessionService.verifyTokenThrow(token)
@ -96,7 +112,7 @@ data class Flair(
} }
fun toFlairSimple(): SimpleFlair { fun toFlairSimple(): SimpleFlair {
return SimpleFlair(this.name, this.description, this.color); return SimpleFlair(this.name, this.description, this.color)
} }
} }
@ -151,7 +167,20 @@ public class FlairService(val db: JdbcTemplate) {
.toList() .toList()
public fun listUser(user: UserDb): List<Flair> = public fun listUser(user: UserDb): List<Flair> =
db.query("select * from flair where user_id=? order by name asc;", arrayOf(user.id), Flair).toList() db.query(
"select * from flair where user_id=? order by name asc;",
arrayOf(user.id),
Flair
)
.toList()
public fun listUserId(id: String): List<Flair> =
db.query(
"select * from flair where user_id=? and description != '' order by name asc;",
arrayOf(id),
Flair
)
.toList()
public fun getById(user: UserDb, id: String): Flair? { public fun getById(user: UserDb, id: String): Flair? {
val items = val items =

View File

@ -65,6 +65,7 @@ browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
}); });
async function startup() { async function startup() {
console.log("Exp startup application")
await browser.storage.local.set({ await browser.storage.local.set({
windows: null, windows: null,
interesetWindows: [], interesetWindows: [],

View File

@ -49,10 +49,24 @@
} }
return 0; return 0;
}); });
loadFlairs();
} catch (e) { } catch (e) {
console.log('TODO show this to the user', e); console.log('TODO show this to the user', e);
} }
} }
// Other skills search
let otherSearch = $state('');
let flairs: SimpleFlair[] = $state([]);
async function loadFlairs() {
try {
flairs = await get(`flair/simple/${id ?? ''}`);
} catch (e) {
console.log('TODO inform the user', e);
}
}
</script> </script>
<svelte:head> <svelte:head>
@ -75,9 +89,15 @@
<ul> <ul>
<li class="px-1"> <li class="px-1">
{#if id} {#if id}
<a class="underline" href="https://www.andr3h3nriqu3s.com/cv?id={id}">andr3h3nriqu3s.com</a> <a
class="underline"
href="https://www.andr3h3nriqu3s.com/cv?id={id}"
>andr3h3nriqu3s.com</a
>
{:else} {:else}
<a class="underline" href="https://www.andr3h3nriqu3s.com/cv">andr3h3nriqu3s.com</a> <a class="underline" href="https://www.andr3h3nriqu3s.com/cv"
>andr3h3nriqu3s.com</a
>
{/if} {/if}
</li> </li>
<li class="px-1"> <li class="px-1">
@ -128,8 +148,17 @@
{/if} {/if}
{#if application.flairs.length > 0} {#if application.flairs.length > 0}
<div class="p-3 bg-white w-[190mm] rounded-lg"> <div class="p-3 bg-white w-[190mm] rounded-lg">
<h1>Your Ad & My skills</h1> <h1 class="flex gap-5 items-end">
Your Ad & My skills {#if flairs.length > 0}<input
placeholder="Loking for other skills search?"
class="flex-grow text-blue-500 print:hidden"
bind:value={otherSearch}
/>
<span class="hidden print:inline text-slate-600 text-sm"><a href="https://www.andr3h3nriqu3s.com/cv?id={id}">Looking for other skills?</a></span>
{/if}
</h1>
<div class="flex flex-wrap gap-2 py-2"> <div class="flex flex-wrap gap-2 py-2">
{#if otherSearch === ''}
{#each application.flairs as flair} {#each application.flairs as flair}
<div class="min-w-0 {flair.description ? 'flex-grow w-full' : ''}"> <div class="min-w-0 {flair.description ? 'flex-grow w-full' : ''}">
{#if flair.description} {#if flair.description}
@ -158,6 +187,45 @@
{/if} {/if}
</div> </div>
{/each} {/each}
{:else}
{@const filtered_list = flairs.filter((a) =>
a.name.match(new RegExp(otherSearch, 'i'))
)}
{#if filtered_list.length == 0}
<div class="w-full text-center text-blue-500 font-bold text-2xl py-10">
Could not find the skill you are looking for.
</div>
{:else}
{#each filtered_list as flair}
<div class="min-w-0 {flair.description ? 'flex-grow w-full' : ''}">
{#if flair.description}
<div
class="p-2 rounded-lg forced-color-adjust-none"
style="background: {flair.color};"
>
<div
class="rounded-lg print:p-2 print:inline-block"
style="background: {flair.color}; print-color-adjust: exact !important;"
>
{flair.name}
</div>
<span class="hidden print:inline">:</span>
<div class="bg-white my-1 print:inline p-1 rounded-md">
{flair.description}
</div>
</div>
{:else}
<div
class="p-2 rounded-lg forced-color-adjust-none"
style="background: {flair.color}; print-color-adjust: exact !important;"
>
{flair.name}
</div>
{/if}
</div>
{/each}
{/if}
{/if}
</div> </div>
</div> </div>
{/if} {/if}