Skip to content

Commit

Permalink
feat: added contribute page
Browse files Browse the repository at this point in the history
  • Loading branch information
ZibanPirate committed Aug 31, 2024
1 parent 00b0f9e commit 49d7c9f
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 48 deletions.
44 changes: 4 additions & 40 deletions web/src/components/locale/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,6 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Meet the DzCode i/o mobile app and stay up-to-date with the state of Algerian open-source software on iOS and Android.",
ar: "تعرف على تطبيق DzCode i / o للجوال وابق على اطلاع دائم بأحدث البرامج مفتوحة المصدر الجزائرية على iOS و Android.",
},
"landing-milestones-error": {
en: "Oops, an error occurred while loading the milestones list, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل قائمة خارطة الطريق ، يرجى المحاولة مرة أخرى ...",
},
"landing-milestones-try-again": {
en: "Try Again",
ar: "حاول مرة أخري",
},
"landing-milestones-title": {
en: "Project roadmap",
ar: "خارطة طريق المشروع",
Expand All @@ -219,14 +211,6 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Meet and connect with all the contributors of all the listed projects on dzcode.io website",
ar: "تعرف على جميع المساهمين في جميع المشاريع المدرجة وتواصل معهم على موقع dzcode.io الإلكتروني",
},
"team-error": {
en: "Oops, an error occurred while loading the articles list, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل قائمة المقالات ، يرجى المحاولة مرة أخرى ...",
},
"team-try-again": {
en: "Try Again",
ar: "حاول مرة أخري",
},
"team-header-title": {
en: "Get to know our team 💻",
ar: "تعرف على فريقنا 💻",
Expand All @@ -247,14 +231,6 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Browse a growing list of Algerian open-source projects and be up-to-date with the state of open-source software in Algeria, you can also add your project to the list!",
ar: "تصفح قائمة متزايدة من المشاريع الجزائرية مفتوحة المصدر وكن على اطلاع دائم بأحدث البرامج مفتوحة المصدر في الجزائر ، كما يمكنك إضافة مشروعك إلى القائمة!",
},
"projects-error": {
en: "Oops, an error occurred while loading the projects list, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل قائمة المشاريع ، يرجى المحاولة مرة أخرى ...",
},
"projects-try-again": {
en: "Try Again",
ar: "حاول مرة أخري",
},
"projects-header-title": {
en: "Open Source Projects",
ar: "مشاريع مفتوحة المصدر",
Expand Down Expand Up @@ -320,14 +296,6 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Browse, read or modify a growing list of articles written by Algerian developers, or Add your own article to the list!",
ar: "تصفح أو اقرأ أو عدل قائمة متزايدة من المقالات التي كتبها مطورون جزائريون ، أو أضف مقالك الخاص إلى القائمة!",
},
"articles-list-error": {
en: "Oops, an error occurred while loading the articles list, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل قائمة المقالات ، يرجى المحاولة مرة أخرى ...",
},
"articles-content-error": {
en: "Ops, an error occurred while loading the selected article, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل المقالة ، يرجى المحاولة مرة أخرى ...",
},
"articles-content-back": {
en: "Back to the list",
ar: "عد إلى القائمة",
Expand All @@ -349,14 +317,6 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
en: "Learn and share your knowledge with other Algerian developers!",
ar: "تعلم وشارك معرفتك مع مطورين جزائريين آخرين!",
},
"learn-list-error": {
en: "Oops, an error occurred while loading the articles list, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل قائمة المقالات ، يرجى المحاولة مرة أخرى ...",
},
"learn-content-error": {
en: "Ops, an error occurred while loading the selected article, please try again...",
ar: "عفوًا ، حدث خطأ أثناء تحميل المقالة ، يرجى المحاولة مرة أخرى ...",
},
"learn-content-back": {
en: "Back to the list",
ar: "عد إلى القائمة",
Expand All @@ -372,6 +332,10 @@ Besides the open tasks on [/Contribute](/Contribute) page, you can also contribu
"ui-theme-DARK": { en: "Dark", ar: "داكن" },
"ui-theme-LIGHT": { en: "Light", ar: "فاتح" },
"ui-theme-AUTO": { en: "Auto", ar: "تلقائي" },
"global-generic-error": {
en: "Oops, something went wrong, please try again...",
ar: "عفوًا ، حدث خطأ ما ، يرجى المحاولة مرة أخرى ...",
},
"global-error-email-us": {
en: "Email us 📩",
ar: "راسلنا 📩",
Expand Down
104 changes: 101 additions & 3 deletions web/src/pages/contribute/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,108 @@
import { Text } from "src/components/text";
import { useEffect } from "react";
import { Link } from "src/components/link";
import { Loading } from "src/components/loading";
import { Locale, useLocale } from "src/components/locale";
import { Markdown } from "src/components/markdown";
import { TryAgain } from "src/components/try-again";
import { fetchContributionsListAction } from "src/redux/actions/contributions";
import { useAppDispatch, useAppSelector } from "src/redux/store";
import { getElapsedTime } from "src/utils/elapsed-time";

// ts-prune-ignore-next
export default function Page(): JSX.Element {
const { localize } = useLocale();
const { contributionsList } = useAppSelector((state) => state.contributionsPage);
const dispatch = useAppDispatch();

useEffect(() => {
dispatch(fetchContributionsListAction());
}, [dispatch]);

// @TODO-ZM: add filters and search
return (
<main>
<Text>Contribution Page</Text>
<main className="flex flex-col self-center">
<h1 className="text-xl font-bold m-2 mt-8 self-center">
<Locale contribute-title />
</h1>

<div className="flex flex-col self-center">
{contributionsList === "ERROR" ? (
<TryAgain
error={localize("global-generic-error")}
action={localize("global-try-again")}
onClick={() => {
dispatch(fetchContributionsListAction());
}}
/>
) : contributionsList === null ? (
<Loading />
) : (
<div className="flex flex-row flex-wrap gap-4 justify-between p-4">
{contributionsList.map((contribution, contributionIndex) => (
<div
dir="ltr"
className="card card-compact bg-base-300 w-96 flex-auto"
key={contributionIndex}
>
<div className="card-body markdown">
<div className="card-body">
<h2 className="card-title">
<Markdown content={contribution.title} />
</h2>
<span className="card-normal flex-1 ">{contribution.project.name}</span>
<div className="flex flex-row flex-wrap gap-1">
{contribution.labels.map((label, labelIndex) => (
<span key={`label-${labelIndex}`} className="badge">
{label}
</span>
))}
{contribution.languages.map((language, languageIndex) => (
<span key={`language-${languageIndex}`} className="badge">
{language}
</span>
))}
</div>
<div className="card-actions justify-end mt-4 gap-4">
<img
className="w-6 h-6 rounded-full"
src={contribution.createdBy.avatarUrl}
/>
<div className="flex-1" />
<div className="flex flex-row">
{getElapsedTime(contribution.updatedAt, localize("elapsed-time-suffixes"))}
</div>
{contribution.commentsCount > 0 && (
<div className="flex flex-row">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="size-6"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 0 1-.825-.242m9.345-8.334a2.126 2.126 0 0 0-.476-.095 48.64 48.64 0 0 0-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0 0 11.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155"
/>
</svg>
<span className="">{contribution.commentsCount}</span>
</div>
)}
<Link href={contribution.url} className="link">
{contribution.type === "issue"
? localize("contribute-read-issue")
: localize("contribute-review-changes")}
</Link>
</div>
</div>
</div>
</div>
))}
</div>
)}
</div>
</main>
);
}
4 changes: 2 additions & 2 deletions web/src/pages/projects/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export default function Page(): JSX.Element {
<div className="flex flex-col self-center">
{projectsList === "ERROR" ? (
<TryAgain
error={localize("projects-error")}
action={localize("projects-try-again")}
error={localize("global-generic-error")}
action={localize("global-try-again")}
onClick={() => {
dispatch(fetchProjectsListAction());
}}
Expand Down
5 changes: 2 additions & 3 deletions web/src/pages/team/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useEffect } from "react";
import { Link } from "src/components/link";
import { Loading } from "src/components/loading";
import { Locale, useLocale } from "src/components/locale";
import { Text } from "src/components/text";
import { TryAgain } from "src/components/try-again";
import { fetchContributorsListAction } from "src/redux/actions/contributors";
import { useAppDispatch, useAppSelector } from "src/redux/store";
Expand All @@ -27,8 +26,8 @@ export default function Page(): JSX.Element {
<div className="flex flex-col self-center">
{contributorsList === "ERROR" ? (
<TryAgain
error={localize("team-error")}
action={localize("team-try-again")}
error={localize("global-generic-error")}
action={localize("global-try-again")}
onClick={() => {
dispatch(fetchContributorsListAction());
}}
Expand Down
18 changes: 18 additions & 0 deletions web/src/redux/actions/contributions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Action, ThunkAction } from "@reduxjs/toolkit";
import { contributionsPageSlice } from "src/redux/slices/contributions-page";
import { AppState } from "src/redux/store";
import { fetchV2 } from "src/utils/fetch";

export const fetchContributionsListAction =
(): ThunkAction<void, AppState, unknown, Action> => async (dispatch) => {
try {
dispatch(contributionsPageSlice.actions.set({ contributionsList: null }));
const { contributions } = await fetchV2("api:Contributions", { query: [] });

dispatch(contributionsPageSlice.actions.set({ contributionsList: contributions }));
} catch (error) {
dispatch(contributionsPageSlice.actions.set({ contributionsList: "ERROR" }));
// @TODO-ZM: Uncomment this line when sentry is added
// Sentry.captureException(error, { tags: { type: "WEB_FETCH" } });
}
};
20 changes: 20 additions & 0 deletions web/src/redux/slices/contributions-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { GetContributionsResponseDto } from "@dzcode.io/api/dist/contribution/types";
import { createSlice } from "@reduxjs/toolkit";
import { setReducerFactory } from "src/redux/utils";
import { LOADABLE } from "src/utils/loadable";

export interface ContributionsPageState {
contributionsList: LOADABLE<GetContributionsResponseDto["contributions"]>;
}

const initialState: ContributionsPageState = {
contributionsList: null,
};

export const contributionsPageSlice = createSlice({
name: "contributions-page",
initialState,
reducers: {
set: setReducerFactory(),
},
});
2 changes: 2 additions & 0 deletions web/src/redux/store.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { configureStore } from "@reduxjs/toolkit";
import { PropsWithChildren, useState } from "react";
import { Provider as ReduxProvider, useDispatch, useSelector } from "react-redux";

import { contributionsPageSlice } from "./slices/contributions-page";
import { contributorsPageSlice } from "./slices/contributors-page";
import { projectsPageSlice } from "./slices/projects-page";
import { settingsSlice } from "./slices/settings";
Expand All @@ -12,6 +13,7 @@ const makeAppStore = () => {
settings: settingsSlice.reducer,
projectsPage: projectsPageSlice.reducer,
contributorsPage: contributorsPageSlice.reducer,
contributionsPage: contributionsPageSlice.reducer,
},
});
};
Expand Down
26 changes: 26 additions & 0 deletions web/src/utils/elapsed-time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @TODO-ZM: move localization logic into the Dictionary files
export const getElapsedTime = (time: string | number | Date, localizedSuffixes: string) => {
const timePassed = new Date().getTime() - new Date(time).getTime();
const years = Math.floor(timePassed / 31536000000);
const months = Math.floor((timePassed - years * 31536000000) / 2628000000);
const days = Math.floor((timePassed - months * 2628000000) / 86400000);
const hours = Math.floor((timePassed - days * 86400000) / 3600000);
const minutes = Math.floor((timePassed - hours * 3600000) / 60000);
const [year, month, day, hour, minute, now] = localizedSuffixes.split("|");

return `${
years > 0
? `${years}${year}`
: `${
months > 0
? `${months}${month}`
: `${
days > 0
? `${days}${day}`
: `${
hours > 0 ? `${hours}${hour}` : `${minutes > 0 ? `${minutes}${minute}` : now}`
}`
}`
}`
}`;
};

0 comments on commit 49d7c9f

Please sign in to comment.