feat: add terms and privacy pages, replace favorite with share on job cards
This commit is contained in:
parent
cf761a70e4
commit
1b897eeb8e
5 changed files with 78 additions and 64 deletions
|
|
@ -26,6 +26,18 @@ export function Footer() {
|
|||
{t("footerMain.info.contact")}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/terms" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
{t("footerMain.info.terms") || "Termos de Uso"}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="flex items-center gap-2">
|
||||
<span className="w-1.5 h-1.5 bg-gray-400 rounded-full inline-block"></span>
|
||||
<Link href="/privacy" className="text-sm text-gray-600 hover:text-primary transition-colors">
|
||||
{t("footerMain.info.privacy") || "Política de Privacidade"}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,14 +9,25 @@ import {
|
|||
} from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
MapPin,
|
||||
Briefcase,
|
||||
Clock,
|
||||
Building2,
|
||||
Heart,
|
||||
Share2,
|
||||
Zap,
|
||||
Link2,
|
||||
MessageCircle,
|
||||
Linkedin,
|
||||
Twitter,
|
||||
Facebook
|
||||
} from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { motion } from "framer-motion";
|
||||
|
|
@ -35,53 +46,27 @@ interface JobCardProps {
|
|||
export function JobCard({ job, isApplied, applicationStatus }: JobCardProps) {
|
||||
const { t } = useTranslation();
|
||||
const { user } = useAuth();
|
||||
const [isFavorited, setIsFavorited] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const notify = useNotify();
|
||||
const handleShare = (platform: string) => {
|
||||
const url = typeof window !== "undefined" ? `${window.location.origin}/jobs/${job.id}` : `https://local.gohorsejobs.com/jobs/${job.id}`;
|
||||
const text = `Confira esta vaga: ${job.title} na ${job.company}`;
|
||||
|
||||
useEffect(() => {
|
||||
const checkFavorite = async () => {
|
||||
if (!user) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await jobsApi.checkFavorite(job.id);
|
||||
setIsFavorited(res.isFavorite);
|
||||
} catch {
|
||||
// User not logged in or error - ignore
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
checkFavorite();
|
||||
}, [job.id, user]);
|
||||
|
||||
const handleFavorite = async () => {
|
||||
if (isLoading) return;
|
||||
if (!user) {
|
||||
notify.error("Erro", "Faça login para salvar vagas.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isFavorited) {
|
||||
await jobsApi.removeFavorite(job.id);
|
||||
setIsFavorited(false);
|
||||
} else {
|
||||
await jobsApi.addFavorite(job.id);
|
||||
setIsFavorited(true);
|
||||
notify.info(
|
||||
t('jobs.favorites.added.title'),
|
||||
t('jobs.favorites.added.desc', { title: job.title }),
|
||||
{
|
||||
actionUrl: "/dashboard/favorites",
|
||||
actionLabel: t('jobs.favorites.action'),
|
||||
}
|
||||
);
|
||||
}
|
||||
} catch {
|
||||
notify.error("Erro", "Faça login para salvar vagas.");
|
||||
switch (platform) {
|
||||
case 'whatsapp':
|
||||
window.open(`https://wa.me/?text=${encodeURIComponent(text + " " + url)}`, '_blank');
|
||||
break;
|
||||
case 'linkedin':
|
||||
window.open(`https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`, '_blank');
|
||||
break;
|
||||
case 'twitter':
|
||||
window.open(`https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`, '_blank');
|
||||
break;
|
||||
case 'facebook':
|
||||
window.open(`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`, '_blank');
|
||||
break;
|
||||
case 'copy':
|
||||
navigator.clipboard.writeText(url);
|
||||
notify.success("Link copiado!", "Link da vaga copiado para a área de transferência.");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -169,19 +154,30 @@ export function JobCard({ job, isApplied, applicationStatus }: JobCardProps) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleFavorite}
|
||||
className="shrink-0"
|
||||
>
|
||||
<Heart
|
||||
className={`h-4 w-4 transition-colors ${isFavorited
|
||||
? "fill-red-500 text-red-500"
|
||||
: "text-muted-foreground hover:text-red-500"
|
||||
}`}
|
||||
/>
|
||||
</Button>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="shrink-0 text-muted-foreground hover:text-primary transition-colors">
|
||||
<Share2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="w-48">
|
||||
<DropdownMenuItem onClick={() => handleShare('whatsapp')} className="gap-2 cursor-pointer">
|
||||
<MessageCircle className="h-4 w-4 text-green-600" /> WhatsApp
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleShare('linkedin')} className="gap-2 cursor-pointer">
|
||||
<Linkedin className="h-4 w-4 text-blue-600" /> LinkedIn
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleShare('twitter')} className="gap-2 cursor-pointer">
|
||||
<Twitter className="h-4 w-4 text-sky-500" /> Twitter/X
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleShare('facebook')} className="gap-2 cursor-pointer">
|
||||
<Facebook className="h-4 w-4 text-blue-700" /> Facebook
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleShare('copy')} className="gap-2 cursor-pointer border-t mt-1 pt-1">
|
||||
<Link2 className="h-4 w-4 text-gray-500" /> Copiar Link
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
|
|
|
|||
|
|
@ -1379,7 +1379,9 @@
|
|||
"info": {
|
||||
"title": "Information",
|
||||
"about": "About Us",
|
||||
"contact": "Contact"
|
||||
"contact": "Contact",
|
||||
"terms": "Terms of Use",
|
||||
"privacy": "Privacy Policy"
|
||||
},
|
||||
"candidates": {
|
||||
"title": "For Candidates",
|
||||
|
|
|
|||
|
|
@ -1380,7 +1380,9 @@
|
|||
"info": {
|
||||
"title": "Información",
|
||||
"about": "Sobre nosotros",
|
||||
"contact": "Contacto"
|
||||
"contact": "Contacto",
|
||||
"terms": "Términos de Uso",
|
||||
"privacy": "Política de Privacidad"
|
||||
},
|
||||
"candidates": {
|
||||
"title": "Para Candidatos",
|
||||
|
|
|
|||
|
|
@ -1386,9 +1386,11 @@
|
|||
},
|
||||
"footerMain": {
|
||||
"info": {
|
||||
"title": "Informações",
|
||||
"title": "Informação",
|
||||
"about": "Sobre nós",
|
||||
"contact": "Contato"
|
||||
"contact": "Contato",
|
||||
"terms": "Termos de Uso",
|
||||
"privacy": "Política de Privacidade"
|
||||
},
|
||||
"candidates": {
|
||||
"title": "Para Candidatos",
|
||||
|
|
|
|||
Loading…
Reference in a new issue