Skip to content

Commit

Permalink
support avec email client, fix cleaned worker avant la fin, fix unlin…
Browse files Browse the repository at this point in the history
…k mastodon
  • Loading branch information
FannyCaulfield committed Jan 6, 2025
1 parent 6c97fe2 commit de5b441
Show file tree
Hide file tree
Showing 18 changed files with 511 additions and 74 deletions.
26 changes: 26 additions & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -306,5 +306,31 @@
"hqxNewsletter": "Receive updates from HelloQuitX",
"oepNewsletter": "Be informed about On est prêt initiatives"
}
},
"support": {
"modal": {
"title": "A problem occured ?",
"description": "Send us a message and we'll get back to you as soon as possible.",
"error": {
"send": "Error sending message",
"unknown": "An unexpected error occurred"
},
"form": {
"email": {
"label": "Your email address",
"placeholder": "[email protected]"
},
"subject": {
"label": "Subject",
"placeholder": "Your subject"
},
"message": {
"label": "Message",
"placeholder": "Your message"
},
"submit": "Send",
"submitting": "Sending..."
}
}
}
}
26 changes: 26 additions & 0 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -294,5 +294,31 @@
"hqxNewsletter": "Recevoir les updates de HelloQuitteX",
"oepNewsletter": "Être informé.e des initiatives de On est prêt"
}
},
"support": {
"modal": {
"title": "Un problème ?",
"description": "Envoyez-nous un message et nous vous répondrons dans les plus brefs délais.",
"error": {
"send": "Erreur lors de l'envoi du message",
"unknown": "Une erreur inattendue s'est produite"
},
"form": {
"email": {
"label": "Votre adresse email",
"placeholder": "[email protected]"
},
"subject": {
"label": "Sujet",
"placeholder": "Votre sujet"
},
"message": {
"label": "Message",
"placeholder": "Votre message"
},
"submit": "Envoyer",
"submitting": "Envoi en cours..."
}
}
}
}
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"next": "15.0.3",
"next-auth": "^5.0.0-beta.25",
"next-intl": "^3.26.3",
"nodemailer": "^6.9.16",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^5.4.0",
Expand Down
3 changes: 0 additions & 3 deletions src/app/[locale]/auth/signin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ import LoginSea from "@/app/_components/LoginSea"
import Footer from "@/app/_components/Footer";
import { useTranslations } from 'next-intl'

// import logoHQXFR from '../../../../../public/logoxHQX/HQX-rose-FR.svg';
// import logoHQXEN from '../../../../../public/logoxHQX/HQX-pink-UK.svg';

export default function SignIn() {
const { data: session, status } = useSession()
const router = useRouter()
Expand Down
7 changes: 4 additions & 3 deletions src/app/[locale]/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export default function DashboardPage() {
const hasTwitter = session?.user?.twitter_id;
const hasOnboarded = session?.user?.has_onboarded;

const connectedServicesCount = [hasMastodon, hasBluesky, hasTwitter].filter(Boolean).length;

// Ajoutez cette vérification
useEffect(() => {
if (status === "unauthenticated" ) {
Expand Down Expand Up @@ -286,7 +288,6 @@ export default function DashboardPage() {
</div>
)}

{!hasOnboarded && (
<>
<div className="flex justify-center relative z-10">
<div className="w-full max-w-2xl flex gap-4">
Expand All @@ -302,7 +303,7 @@ export default function DashboardPage() {
<span className="text-lg font-semibold">{t('addSocialNetwork')}</span>
<Link className="w-6 h-6 opacity-90" />
</motion.button>

{!hasOnboarded && (
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
Expand All @@ -318,6 +319,7 @@ export default function DashboardPage() {
<span className="text-lg font-semibold">{t('importButton')}</span>
<Ship className="w-6 h-6 opacity-90" />
</motion.button>
)}
</div>
</div>

Expand Down Expand Up @@ -370,7 +372,6 @@ export default function DashboardPage() {
</>
)}
</>
)}
</div>
</div>
</div>
Expand Down
69 changes: 60 additions & 9 deletions src/app/[locale]/upload/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import { validateTwitterData, extractTargetFiles } from '../../_components/Uploa
import Image from 'next/image';
import seaBackground from '../../../public/sea.svg'
import { plex } from '../../fonts/plex';
import logoHQX from '../../../../public/logoxHQX/HQX-rose-FR.svg'
import { motion } from 'framer-motion';
import { AlertCircle } from 'lucide-react';
import boat1 from '../../../public/boats/boat-1.svg'
import Footer from "@/app/_components/Footer";
import LoadingIndicator from '@/app/_components/LoadingIndicator';

import SupportModal from '../../_components/SupportModale';
import logoHQXFR from '../../../../public/logoxHQX/HQX-rose-FR.svg';
import logoHQXEN from '../../../../public/logoxHQX/HQX-pink-UK.svg';

const UploadButton = dynamic(() => import('../../_components/UploadButton'), {
loading: () => <div className="animate-pulse bg-gray-200 h-12 w-48 rounded-lg"></div>,
Expand All @@ -43,7 +45,11 @@ export default function UploadPage() {
const [isUploading, setIsUploading] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [showHelpModal, setShowHelpModal] = useState(false);
const [showSupportModal, setShowSupportModal] = useState(false);
const t = useTranslations('upload');
const tSupport = useTranslations('support');
const locale = params.locale as string;
const logoHQX = locale === 'fr' ? logoHQXFR : logoHQXEN;

useEffect(() => {
if (status === "unauthenticated") {
Expand Down Expand Up @@ -141,11 +147,22 @@ export default function UploadPage() {
};

const validateFileType = (file: File): boolean => {

console.log("File Type =", file.type)
const validTypes = ['application/javascript', 'text/javascript', 'application/zip', 'application/x-javascript'];
const validTypes = [
'application/javascript',
'text/javascript',
'application/zip',
'application/x-javascript',
'text/ecmascript',
'application/ecmascript',
'application/x-ecmascript',
'text/x-javascript',
'text/jsx',
'text/plain',
'module'
];
return validTypes.includes(file.type);
};
};

const sanitizeContent = (content: Uint8Array): Uint8Array => {
const text = new TextDecoder().decode(content);
Expand Down Expand Up @@ -404,8 +421,7 @@ export default function UploadPage() {
}

return (
<div className="min-h-screen bg-[#2a39a9] relative w-full max-w-[90rem] m-auto">
<Header />
<div className="min-h-screen bg-[#2a39a9] relative w-full max-w-[90rem] m-auto"> <Header />
<div className="relative z-10 pt-12">
<Image
src={logoHQX}
Expand All @@ -416,6 +432,7 @@ export default function UploadPage() {
priority
/>
</div>

<div className="flex justify-center items-center min-h-[60vh]">
<motion.div
initial={{ opacity: 0, y: 20 }}
Expand Down Expand Up @@ -443,20 +460,54 @@ export default function UploadPage() {
</p>

{!isUploading && (
<div className="mt-8">
<div className="space-y-4">
<UploadButton onFilesSelected={handleFilesSelected} onError={handleUploadError} />
<motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={() => setShowSupportModal(true)}
className="w-full flex items-center justify-center gap-2 py-3 px-6 bg-white/10 hover:bg-white/20 backdrop-blur-lg rounded-xl text-white"
>
<AlertCircle className="w-5 h-5" />
<span>{tSupport('modal.title')}</span>
</motion.button>
</div>
)}

{isUploading && (
<div className="flex items-center justify-center space-x-2">
<div className="animate-spin rounded-full h-5 w-5 border-t-2 border-b-2 border-white"></div>
<span>{t('loading')}</span>
<p className="text-white">{t('uploading')}</p>
</div>
)}
</div>
</div>

</motion.div>

{/* Modal de Support */}
<SupportModal
isOpen={showSupportModal}
onClose={() => setShowSupportModal(false)}
/>

{/* </motion.div> */}

{/* <motion.button
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={() => setShowSupportModal(true)}
className="fixed bottom-4 right-4 bg-white/10 hover:bg-white/20 backdrop-blur-lg rounded-full p-3 text-white shadow-lg flex items-center gap-2"
>
<AlertCircle className="w-5 h-5" />
<span>{tSupport('button')}</span>
</motion.button> */}

{/* Modal de Support */}
<SupportModal
isOpen={showSupportModal}
onClose={() => setShowSupportModal(false)}
/>
</div>

{/* Modals */}
Expand Down
36 changes: 31 additions & 5 deletions src/app/_components/DashboardLoginButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,36 @@ export default function DashboardLoginButtons({
const t = useTranslations('dashboardLoginButtons')

const handleSignIn = async (provider: string) => {
onLoadingChange(true)
await signIn(provider, {
callbackUrl: '/dashboard?linking=true'
})
try {
onLoadingChange(true)
const result = await signIn(provider, {
redirect: false,
callbackUrl: '/dashboard?linking=true'
})

if (result?.error) {
// Redirect to error page with appropriate error code
if (result.error.includes("temporairement indisponible")) {
window.location.href = `/auth/error?error=RateLimit`;
} else if (result.error.includes("Configuration")) {
window.location.href = `/auth/error?error=Configuration`;
} else if (result.error.includes("OAuthSignin")) {
window.location.href = `/auth/error?error=OAuthSignin`;
} else if (result.error.includes("OAuthCallback")) {
window.location.href = `/auth/error?error=OAuthCallback`;
} else if (result.error.includes("AccessDenied")) {
window.location.href = `/auth/error?error=AccessDenied`;
} else {
window.location.href = `/auth/error?error=Default&message=${encodeURIComponent(result.error)}`;
}
} else if (result?.ok && result.url) {
window.location.href = result.url;
}
} catch (err: any) {
window.location.href = `/auth/error?error=Default&message=${encodeURIComponent(err.message || "Une erreur inattendue s'est produite")}`;
} finally {
onLoadingChange(false)
}
}

if (!hasUploadedArchive) {
Expand Down Expand Up @@ -218,7 +244,7 @@ export default function DashboardLoginButtons({
variants={itemVariants}
whileHover={{ scale: 1.01, y: -2 }}
whileTap={{ scale: 0.99 }}
onClick={() => handleSignIn("mastodon-piaille")}
onClick={() => handleSignIn("piaille")}
className="w-full flex items-center justify-center gap-3 px-4 py-4
bg-gradient-to-br from-purple-500/80 to-purple-600/80 rounded-xl
hover:from-purple-500 hover:to-purple-600
Expand Down
17 changes: 12 additions & 5 deletions src/app/_components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
'use client';

import { useTranslations } from 'next-intl';
import { memo } from 'react';
import { memo, useState } from 'react';
import { Github, Mail } from 'lucide-react';
import SupportModal from './SupportModale';

const FooterLink = memo(({ href, children }: { href: string; children: React.ReactNode }) => (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
className="text-indigo-300 hover:text-pink-400 transition-colors duration-200"
>
{children}
Expand All @@ -20,6 +19,7 @@ FooterLink.displayName = 'FooterLink';
const Footer = memo(() => {
const t = useTranslations('footer');
const year = new Date().getFullYear();
const [isSupportModalOpen, setIsSupportModalOpen] = useState(false);

const hostedText = t.raw('hosted.text');
const cnrsText = t.raw('hosted.cnrs');
Expand Down Expand Up @@ -58,12 +58,19 @@ const Footer = memo(() => {
<FooterLink href="https://github.com/FannyCaulfield/helloquittex">
<Github className="w-5 h-5" />
</FooterLink>
<FooterLink href="mailto:[email protected]">
<button
onClick={() => setIsSupportModalOpen(true)}
className="text-indigo-300 hover:text-pink-400 transition-colors duration-200"
>
<Mail className="w-5 h-5" />
</FooterLink>
</button>
</div>
</div>
</div>
<SupportModal
isOpen={isSupportModalOpen}
onClose={() => setIsSupportModalOpen(false)}
/>
</footer>
);
});
Expand Down
Loading

0 comments on commit de5b441

Please sign in to comment.