Skip to content
Draft
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# vscode
.vscode/settings.json
5 changes: 5 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ const tools: {
description: "Test your speed and practice typing code.",
href: "https://wpm.silver.dev",
},
{
title: "Roast My Setup",
description: "Recíbi feedback de tu setup.",
href: "/roast-my-setup",
},
],
},
{
Expand Down
68 changes: 68 additions & 0 deletions src/app/roast-my-setup/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"use client";

import { Metadata } from "next";
import Description from "@/components/description";
import Heading from "@/components/heading";
import Section from "@/components/section";
import Spacer from "@/components/spacer";
import { Button } from "@/components/ui/button";
import ErrorBadge from "@/components/ui/error-badge";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { useState } from "react";

export const metadata: Metadata = {
title: "Roast My Setup",
description: "Submit your setup and get a roast for improvement.",
openGraph: {
title: "Roast My Setup • Open Silver",
description: "Show off your setup and get roasted for fun and improvement.",
type: "website",
},
};

export default function Home() {
const router = useRouter();
const [error, setError] = useState<Error | null>(null);

const requestCameraAndMicrophone = () => {
navigator.mediaDevices
.getUserMedia({ video: true, audio: true })
.then((stream) => {
router.push("/roast-my-setup/roaster");
})
.catch((err) => {
setError(new Error("Access to microphone not granted."));
});
};

return (
<Section>
<ErrorBadge error={error} />
<Heading size="lg" center>
<span className="text-primary">Roast</span> My{" "}
<span className="text-primary">Setup</span>
</Heading>

<Description center>Get feedback from your setup.</Description>
<Description center>Como te ven los demas?</Description>

<div className="flex items-center justify-center pt-4">
<Button
variant="default"
size="lg"
onClick={requestCameraAndMicrophone}
>
Roast Me
</Button>
</div>

<Spacer size="lg" />
<div className="text-center">
<Link href="/roast-my-setup/privacy" className="link">
Política de Privacidad
</Link>
</div>
</Section>
);
}
65 changes: 65 additions & 0 deletions src/app/roast-my-setup/privacy/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import Heading from "@/components/heading";
import Section from "@/components/section";
import Spacer from "@/components/spacer";

export default function Page() {
return (
<Section>
<Heading>Política de Privacidad</Heading>
<Spacer />
<p className="mb-6">
Gracias por utilizar Roast my Setup. Su privacidad es muy importante
para nosotros, y estamos comprometidos a ser transparentes sobre cómo
manejamos sus datos. A continuación, encontrará los detalles sobre
nuestras prácticas de privacidad:
</p>
<ul className="list-disc pl-4">
<li className="mb-4">
<p className="font-bold mb-2">
No almacenamos grabaciónes, audio ni información personal
</p>
<p>
La herramienta Roast my Setup no almacena los videos ni ninguna
información contenida en ellos en nuestros servidores ni en ningún
otro lugar. Una vez que su documento es procesado, todos los datos
se eliminan de forma inmediata.
</p>
</li>
<li className="mb-4">
<p className="font-bold mb-2">
Uso de tecnología de inteligencia artificial
</p>
<p>
Para el análisis y retroalimentación del contenido, la herramienta
utiliza Gemini AI. Este proceso se realiza de manera segura y no se
retiene ningún dato después del análisis.
</p>
</li>
<li className="mb-4">
<p className="font-bold mb-2">Seguridad de los datos</p>
<p>
Nos aseguramos de que sus datos sean procesados en un entorno
seguro. Dado que no almacenamos información, no existe riesgo de
acceso no autorizado ni de uso indebido de sus datos.
</p>
</li>
<li className="mb-4">
<p className="font-bold mb-2">Servicios de terceros</p>
<p>
La herramienta Roast My Setup utiliza [Redacted] para el análisis
del contenido y la generación de feedback. [Redacted] opera bajo sus
propias políticas de privacidad y seguridad, diseñadas para manejar
sus datos de manera responsable.
</p>
</li>
<li className="mb-4">
<p className="font-bold mb-2">Su consentimiento</p>
<p>
Al utilizar la herramienta Roast my Setup, usted acepta los términos
descritos en esta Política de Privacidad.
</p>
</li>
</ul>
</Section>
);
}
36 changes: 36 additions & 0 deletions src/app/roast-my-setup/roaster/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client";

import { Card } from "@/components/ui/card";
import { useEffect, useRef } from "react";

export default function Roaster() {
const videoRef = useRef<HTMLVideoElement | null>(null);

useEffect(() => {
navigator.mediaDevices
.getUserMedia({ video: true })
.then((stream) => {
if (videoRef.current) {
videoRef.current.srcObject = stream;
}
})
.catch((err) => {
console.error("Error al acceder a la cámara:", err);
});
}, []);

return (
<div className="flex justify-center gap-4">
<div>
<video
ref={videoRef}
autoPlay
muted
playsInline
className="min-w-[50%]"
/>
</div>
<Card className="min-w-[50%]">Say &quot;Roast my Setup&quot;</Card>
</div>
);
}
2 changes: 1 addition & 1 deletion src/resume-checker/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Heading from "@/components/heading";
import Section from "@/components/section";
import Spacer, { spaceSizes } from "@/components/spacer";
import { Button } from "@/components/ui/button";
import ErrorBadge from "@/resume-checker/components/error-badge";
import ErrorBadge from "@/components/ui/error-badge";
import { useFormState } from "@/resume-checker/hooks/form-context";
import { useMutationState } from "@tanstack/react-query";
import Link from "next/link";
Expand Down