Filtro para posicións, enquisa para comprobar compatibilidade
mar., 7 de mar. de 2023
Motivación
Aínda que pareza mentira, debido á alta demanda de desarrolladores de todo tipo no mercado por parte das empresas, moitos recruiters e headhunters volvéronse máquinas do copy paste. Non sei a cifra ou a cantidade diaria de mensaxes que envían a todos os perfís da súa rede que fan "match" coa posición nova que teñen dispoñible, pero apostaría que non son poucos. E non é que non me guste que me envíen mensaxes, pero gustaríame que me enviasen mensaxes que realmente me interesen e que me fagan pensar que viron o meu perfil, o meu código ou algún dos meus traballos e que realmente me queren contratar polas miñas habilidades.
Non adoita ser así, moitos usan programas para automatizar o proceso de procura de perfís como Hiretual ou Jobvite, envían mensaxes a todos os usuarios "que fan match" e en ocasións isto non funciona moi ben. Xa que no teu perfil pon claramente desarrollador Frontend, a túa experiencia di o mesmo... pero, eles teñen unha posición Xava con microservicios incrible para ti.
Outras veces métese a pata e envíanche unha mensaxe co nome do teu compañeiro de equipo:
A idea
Cantas veces tiveches unha chamada con preguntas como:
- Por que buscas un cambio ?
- Coñeces os principios SOLID ?
- Cuantos anos dirías que has traballo con React ? E Typescript ?
- Sabes o que é a integración continua ?
Para que despois ofrézanche un salario inferior ao que tes, ou que che pidan o CV para non volver dicirche nunca nada.
How many times bro ?
A idea é filtrar ti antes que che filtren a ti.
Solución
10 simples preguntas sobre puntos que consideres importantes, requisitos, valores.. ou basicamente o que che de a gana e se se cumpren, o recruiter obterá información de contacto para poder entrar en detalle de todo o proceso.
É un win win, ambos aforramos tempo, non ?
Código
Cunha compoñente contedora ou páxina, un par de botóns, radiobuttons e un array de objectos tes máis que suficiente, no meu caso:
Teño a miña páxina:
import Dialog from '@/components/Dialog';
import styles from '@/styles/survey.module.css';
import ControlButtons from '@/components/ControlButtons';
import Confetti from 'react-confetti';
import SEO from '@/components/SEO';
import useWindowResize from '@/hooks/useWidowResize';
import useSurvey from '@/hooks/useSurvey';
import NavigationArrows from '@/components/NavigationArrows';
const { width, height } = useWindowResize();
<Confetti width={width} height={height} numberOfPieces={100} run={surveySuccess} />
title: 'Averigua si hago match con la posición en 1 minuto',
description: 'Click para continuar',
<div className={styles.header}>
{currentQuestionNum > 0 && currentQuestionNum < 11 && (
{currentQuestionNum} / {totalQuestions - 2}
// TODO: Move to a component
<div className={styles.container}>
(question: any, index: number) =>
currentQuestionNum === index && (
<div key={index} className={styles.question}>
dangerouslySetInnerHTML={{ __html: question.questionHtml }}
className={styles.questionHtml}
{question.answerOptions?.map((answerOption: any) => (
<label htmlFor={answerOption.answerText} key={answerOption.answerText}>
handleAnswerOptionClick({
question: question.questionText,
isCorrect: answerOption.isCorrect,
id={answerOption.answerText}
value={answerOption.answerText}
checked={answers[index]?.answer === answerOption.answerText}
{answerOption.answerText}
<div className={styles.buttons}>
hidden={currentQuestionNum < 1 || currentQuestionNum > 10}
disabledLeft={currentQuestionNum < 2}
disabledRight={questionsDoneNum < currentQuestionNum}
onClickLeft={handlePreviousQuestion}
onClickRight={handleNextQuestion}
Meu hook con loxica de negocio:
import { useRouter } from 'next/router';
import { useReducer, useEffect, useRef } from 'react';
const reducer = (state: any, action: any) => {
...ya sabes como funciona un switch no?
const useSurvey = () => {
const { query } = useRouter();
const { name = '👋' } = query;
const emailRef = useRef<boolean>(false);
const [state, dispatch] = useReducer(reducer, initialState);
questionText: '¿ Que chegou antes o ovo ou a galiña ?',
questionHtml: `<h2>¿ Que chegou antes o ovo ou a galiña ?</h2>`,
answerOptions: [{ answerText: 'Ovo', isCorrect: true, }, { answerText: 'Galiña', isCorrect: false }],
if (state.currentQuestion === questions.length - 1 && !emailRef.current) {
await fetch('/api/email', {
'Content-Type': 'application/json',
subject: `Job survey from ${name} - ${new Date().toLocaleString()}`,
<code> ${navigator.userAgent} </code>
`<li> ${answer.question} : ${answer.answer} - ${
answer.isCorrect ? '✅' : '🚫'
}, [state, name, questions.length]);
const handlePreviousQuestion = () => {
if (state.currentQuestion > 1) dispatch({ type: 'PREVIOUS_QUESTION' });
const handleNextQuestion = () => {
if (state.currentQuestion != 0 && state.questionsDone >= state.currentQuestion)
dispatch({ type: 'NEXT_QUESTION' });
const handleAnswerOptionClick = (payload: {
}) => dispatch({ type: 'ADD_ANSWER', payload });
surveySuccess: state.success,
currentQuestionNum: state.currentQuestion,
questionsDoneNum: state.questionsDone,
totalQuestions: questions.length,
export default useSurvey;
Meu backend
import type { NextApiRequest, NextApiResponse } from 'next';
import nodemailer from 'nodemailer';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const transporter = nodemailer.createTransport({
service: process.env.EMAIL_HOST,
pass: process.env.EMAIL_PASSWORD,
const { subject, message } = req.body;
await transporter.sendMail(mailOptions);
res.status(200).json({ success: true });
res.status(500).json({ success: error });
Resultado
Proba ti mesmo: Ligazón ao resultado