diff --git a/.env.example b/.env.example index 94d96ff4..e2e6f37b 100644 --- a/.env.example +++ b/.env.example @@ -7,9 +7,13 @@ GAMMA_ROOT_URL=http://localhost:8081 ACTIVE_GROUP_TYPES="committee,society" NEXTAUTH_SECRET=secret NEXTAUTH_URL=http://localhost:3000/api/auth +BASE_URL="http://localhost:3000" MEDIA_PATH="./media" ADMIN_GROUPS="styrit" +PAGE_EDITOR_GROUPS="snit,motespresidit" CORPORATE_RELATIONS_GROUP="armit" -BASE_URL="http://localhost:3000" # Ensures that the dev enviroment is the same as the production enviroment. Hydration issues can be missed in dev without otherwise. TZ=UTC + +SUBSCRIBE_SLACK_URL_SV="https://" +SUBSCRIBE_SLACK_URL_EN="https://" diff --git a/src/app/[locale]/(main-content)/page.tsx b/src/app/[locale]/(main-content)/page.tsx index 2fdd1a31..048a85fd 100644 --- a/src/app/[locale]/(main-content)/page.tsx +++ b/src/app/[locale]/(main-content)/page.tsx @@ -5,6 +5,7 @@ import ContactCard from '@/components/ContactCard/ContactCard'; import Lunch from '@/components/Lunch/Lunch'; import Sponsors from '@/components/Sponsors/Sponsors'; import Calendar from '@/components/Calendar/Calendar'; +import SubscribeOptions from '@/components/SubscribeOptions/SubscribeOptions'; export const revalidate = 3600; @@ -34,6 +35,7 @@ export default async function Home(props: { const LeftBar = ({ locale }: { locale: string }) => { return (
+
diff --git a/src/components/NewsList/NewsClient.tsx b/src/components/NewsList/NewsClient.tsx index d47f3e84..a2df1f62 100644 --- a/src/components/NewsList/NewsClient.tsx +++ b/src/components/NewsList/NewsClient.tsx @@ -10,7 +10,6 @@ import NewsCard from './NewsCard/NewsCard'; import styles from './NewsList.module.scss'; import clientStyles from './NewsListClient.module.scss'; import NewsPost from './NewsPost/NewsPost'; -import RssFeedButton from './RssFeedButton'; import ViewToggle from './ViewToggle'; interface NewsClientProps { @@ -34,7 +33,6 @@ const NewsClient = ({ news, canPost, locale }: NewsClientProps) => {

{l.news.title}

-
(null); + + const handleClick = async (e: React.MouseEvent) => { + e.preventDefault(); + try { + await navigator.clipboard.writeText(window.location.origin + rssUrl); + setTooltipVisible(true); + if (tooltipTimeout.current) clearTimeout(tooltipTimeout.current); + tooltipTimeout.current = setTimeout(() => setTooltipVisible(false), 1500); + } catch { + window.open(rssUrl, '_blank', 'noopener,noreferrer'); + } + }; + + return ( + + ); +} diff --git a/src/components/SubscribeOptions/SubscribeOptions.module.scss b/src/components/SubscribeOptions/SubscribeOptions.module.scss new file mode 100644 index 00000000..d66dd86b --- /dev/null +++ b/src/components/SubscribeOptions/SubscribeOptions.module.scss @@ -0,0 +1,67 @@ +.title { + font-size: 1.35rem; + font-weight: 700; + text-align: left; + margin-bottom: 1rem; +} + +.optionsContainer { + display: flex; + flex-direction: row; + gap: 0.5rem; +} + +.iconButton { + display: flex; + align-items: center; + justify-content: center; + width: 2.5rem; + height: 2.5rem; + background-color: transparent; + border: 1px solid var(--subscribe-border-color, var(--text-color, #333)); + border-radius: 0.5rem; + color: inherit; + cursor: pointer; + transition: all 0.2s ease; + font-size: 1.3rem; + position: relative; + padding: 0; + + &:hover:not(:disabled) { + background-color: var(--subscribe-hover-bg, rgba(0, 0, 0, 0.05)); + border-color: var(--subscribe-hover-border-color, var(--text-color, #333)); + } + + &:focus-visible { + outline: 2px solid currentColor; + outline-offset: 2px; + } + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } +} + +.tooltip { + position: absolute; + top: 50%; + left: calc(100% + 8px); + transform: translateY(-50%); + background: var(--background-color, #24292f); + color: var(--news-view-toggle-selected-color, #fff); + padding: 6px 12px; + border-radius: 6px; + font-size: 0.85rem; + white-space: nowrap; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15); + opacity: 0; + pointer-events: none; + user-select: none; + transition: opacity 0.2s cubic-bezier(0.4, 0, 0.2, 1); + z-index: 10; +} + +.tooltipVisible { + opacity: 1; +} diff --git a/src/components/SubscribeOptions/SubscribeOptions.tsx b/src/components/SubscribeOptions/SubscribeOptions.tsx new file mode 100644 index 00000000..b50ba25b --- /dev/null +++ b/src/components/SubscribeOptions/SubscribeOptions.tsx @@ -0,0 +1,55 @@ +import i18nService from '@/services/i18nService'; +import Link from 'next/link'; +import { MdEmail } from 'react-icons/md'; +import { SiSlack } from 'react-icons/si'; +import ContentPane from '../ContentPane/ContentPane'; +import RssButton from './RssButton'; +import styles from './SubscribeOptions.module.scss'; +import getSlackSubscribeLink from '@/hooks/getSlackSubscribeLink'; + +interface SubscribeOptionsProps { + locale: string; +} + +export default async function SubscribeOptions({ + locale +}: SubscribeOptionsProps) { + const l = i18nService.getLocale(locale); + const slackSubscribeUrl = await getSlackSubscribeLink(); + + return ( + +

{l.news.subscribe}

+
+ {slackSubscribeUrl && ( + + + + )} + + + + +
+
+ ); +} diff --git a/src/dictionaries/en.json b/src/dictionaries/en.json index 33f49ded..83961e8a 100644 --- a/src/dictionaries/en.json +++ b/src/dictionaries/en.json @@ -10,7 +10,8 @@ "close": "Close", "save": "Save", "manage": "Manage", - "add": "Add" + "add": "Add", + "comingSoon": "Comming soon" }, "site": { "siteTitle": "IT at Chalmers", @@ -41,6 +42,8 @@ "by": "by", "unknown": "unknown author", "subscribe": "Subscribe to news feed", + "subscribeViaRss": "Follow us via RSS", + "subscribeViaSlack": "Join our Slack", "confirmDelete": "Are you sure you want to delete this post? This action cannot be undone.", "deleting": "Deleting...", "deleted": "Deleted!", diff --git a/src/dictionaries/sv.json b/src/dictionaries/sv.json index 41690486..80c3fd82 100644 --- a/src/dictionaries/sv.json +++ b/src/dictionaries/sv.json @@ -10,7 +10,8 @@ "close": "Stäng", "save": "Spara", "manage": "Hantera", - "add": "Lägg till" + "add": "Lägg till", + "comingSoon": "Kommer snart" }, "site": { "siteTitle": "IT på Chalmers", @@ -41,6 +42,8 @@ "by": "av", "unknown": "okänd användare", "subscribe": "Prenumerera på nyheter", + "subscribeViaRss": "Följ oss via RSS", + "subscribeViaSlack": "Gå med i vår Slack", "confirmDelete": "Vill du radera nyheten? Detta går inte att ångra!", "deleting": "Raderar...", "deleted": "Raderad!", diff --git a/src/hooks/getSlackSubscribeLink.ts b/src/hooks/getSlackSubscribeLink.ts new file mode 100644 index 00000000..8924507a --- /dev/null +++ b/src/hooks/getSlackSubscribeLink.ts @@ -0,0 +1,10 @@ +'use server'; + +import i18nService from '@/services/i18nService'; + +const { SUBSCRIBE_SLACK_URL_EN: EN, SUBSCRIBE_SLACK_URL_SV: SV } = process.env; + +export default async function getSlackSubscribeLink(): Promise { + const isEn = i18nService.getLocale().en; + return (isEn ? EN : SV) || null; +}