diff --git a/apps/web/src/app/[lang]/dashboard/[name]/overview/page.tsx b/apps/web/src/app/[lang]/dashboard/[name]/overview/page.tsx index 76c17fa..633e1dd 100644 --- a/apps/web/src/app/[lang]/dashboard/[name]/overview/page.tsx +++ b/apps/web/src/app/[lang]/dashboard/[name]/overview/page.tsx @@ -47,7 +47,7 @@ export default async function DashboardOverviewPage({
- +
}> diff --git a/apps/web/src/app/[lang]/dashboard/[name]/project/[id]/page.tsx b/apps/web/src/app/[lang]/dashboard/[name]/project/[id]/page.tsx index 6ef5ad3..0f1cc33 100644 --- a/apps/web/src/app/[lang]/dashboard/[name]/project/[id]/page.tsx +++ b/apps/web/src/app/[lang]/dashboard/[name]/project/[id]/page.tsx @@ -37,10 +37,11 @@ export default async function ProjectPage({ params }: ProjectPageProps) { return redirect("/404"); } - const [languages, languagesErr] = await getYoutubeSupportedLanguages( - params.lang, - ); - const [categories, categoriesErr] = await getYoutubeCategories(params.lang); + const [[languages, languagesErr], [categories, categoriesErr]] = + await Promise.all([ + getYoutubeSupportedLanguages(params.lang), + getYoutubeCategories(params.lang), + ]); if (languagesErr !== null || categoriesErr !== null) { throw new Error("Something went wrong on our end"); diff --git a/apps/web/src/app/[lang]/dashboard/[name]/settings/layout.tsx b/apps/web/src/app/[lang]/dashboard/[name]/settings/layout.tsx index dbb7297..5e788d5 100644 --- a/apps/web/src/app/[lang]/dashboard/[name]/settings/layout.tsx +++ b/apps/web/src/app/[lang]/dashboard/[name]/settings/layout.tsx @@ -3,17 +3,21 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; import type { PropsWithChildren } from "react"; +import { useTranslation } from "~/i18n/client"; +import type { SupportedLanguages } from "~/i18n/settings"; import { cn } from "~/lib/utils"; type SettingsProps = { params: { name: string; + lang: SupportedLanguages; }; } & PropsWithChildren; export default function Settings({ params, children }: SettingsProps) { const pathname = usePathname(); + const { t } = useTranslation(params.lang, "settings"); return (
@@ -30,7 +34,7 @@ export default function Settings({ params, children }: SettingsProps) { : "border-transparent hover:border-slate-300", )} > - general + {t("general.title")}
@@ -44,7 +48,7 @@ export default function Settings({ params, children }: SettingsProps) { : "border-transparent hover:border-slate-300", )} > - members + {t("members.title")}
diff --git a/apps/web/src/app/[lang]/dashboard/[name]/settings/page.tsx b/apps/web/src/app/[lang]/dashboard/[name]/settings/page.tsx index a2291a3..fce2f07 100644 --- a/apps/web/src/app/[lang]/dashboard/[name]/settings/page.tsx +++ b/apps/web/src/app/[lang]/dashboard/[name]/settings/page.tsx @@ -34,6 +34,7 @@ import { getOwnOrganizationByName, updateOrganizationName, } from "~/server/actions/organization"; +import LocaleSelect from "~/components/locale-select"; type SettingsMembersViewProps = { params: { @@ -137,6 +138,13 @@ export default function SettingsGeneralPage({

{t("title")}

+

{t('language_section.title')}:

+ +
+ +
+

{t('organization_section.title')}

+ -
+
@@ -97,10 +97,6 @@ export default async function HomePage({ params }: HomePageProps) {

{t("feature_section.title")}

- -

- {t("feature_section.description")} -

diff --git a/apps/web/src/app/api/organizations/[name]/projects/route.ts b/apps/web/src/app/api/organizations/[name]/projects/route.ts index 779652d..12a4f20 100644 --- a/apps/web/src/app/api/organizations/[name]/projects/route.ts +++ b/apps/web/src/app/api/organizations/[name]/projects/route.ts @@ -13,7 +13,7 @@ export async function GET( if (err !== null) { if (err === "Not found") { - return redirect("404"); + return redirect("/404"); } return NextResponse.json( @@ -38,7 +38,11 @@ export async function GET( ); } - const projectsResponse = await getOrganizationProjects(organization.id, +page, query); + const projectsResponse = await getOrganizationProjects( + organization.id, + +page, + query, + ); return NextResponse.json(projectsResponse); } diff --git a/apps/web/src/components/create-project/project-create-form.tsx b/apps/web/src/components/create-project/project-create-form.tsx index b2c5435..c45dccf 100644 --- a/apps/web/src/components/create-project/project-create-form.tsx +++ b/apps/web/src/components/create-project/project-create-form.tsx @@ -82,26 +82,7 @@ export default function ProjectCreateForm({ }, [video, channel]); function onSuccess(data: TProjectForm) { - const formData = new FormData(); - - formData.append("license", data.license!); - formData.append("title", data.title!); - formData.append("description", data.description!); - formData.append("categoryId", data.categoryId!); - formData.append("defaultLanguage", data.defaultLanguage!); - formData.append("tags", data.tags!); - formData.append("embeddable", `${data.embeddable!}`); - formData.append("privacyStatus", data.privacyStatus!); - formData.append("publicStatsViewable", `${data.publicStatsViewable!}`); - formData.append( - "selfDeclaredMadeForKids", - `${data.selfDeclaredMadeForKids!}`, - ); - formData.append("notifySubscribers", `${data.notifySubscribers!}`); - formData.append("channelId", data.channelId); - formData.append("video", data.video); - - mutate(formData); + mutate(data); } function onError(errors: FieldErrors) { @@ -333,7 +314,7 @@ export default function ProjectCreateForm({ }} className="rounded-full max-w-max" > - {showMore ? t("show_more") : t("show_less")} + {showMore ? t("show_less") : t("show_more")} {showMore ? ( diff --git a/apps/web/src/components/dashboard/project-form.tsx b/apps/web/src/components/dashboard/project-form.tsx index abab1f8..c8de886 100644 --- a/apps/web/src/components/dashboard/project-form.tsx +++ b/apps/web/src/components/dashboard/project-form.tsx @@ -18,7 +18,7 @@ import { } from "../ui/form"; import { Input } from "../ui/input"; import { Textarea } from "../ui/textarea"; -import { Suspense, useEffect, useState } from "react"; +import { Suspense, useState } from "react"; import InputSkeleton from "../ui/skeletons/input-skeleton"; import { Tooltip, @@ -41,13 +41,16 @@ import { Checkbox } from "../ui/checkbox"; import type { UseCreateProjectMutationResult } from "~/lib/mutations/useCreateProjectMutation"; import CategorySelect from "../create-project/categories-select"; import LanguageSelect from "../create-project/language-select"; +import type { UseEditProjectMutationResult } from "~/lib/mutations/useEditProjectMutation"; import type { SupportedLanguages } from "~/i18n/settings"; import { useTranslation } from "~/i18n/client"; import { Trans } from "react-i18next"; interface ProjectFormProps { defaultValues: InsertProject; - mutate: UseCreateProjectMutationResult["mutate"]; + mutate: + | UseCreateProjectMutationResult["mutate"] + | UseEditProjectMutationResult["mutate"]; isPending?: UseCreateProjectMutationResult["isPending"]; lang: SupportedLanguages; } @@ -65,12 +68,6 @@ export default function ProjectForm({ const { t } = useTranslation(lang, "project-form"); - const formValues = form.watch(); - - useEffect(() => { - console.log(formValues); - }, [formValues]); - const [showMore, setShowMore] = useState(false); function onSuccess(data: TProjectForm) { @@ -264,7 +261,7 @@ export default function ProjectForm({ }} className="rounded-full max-w-max" > - {showMore ? t("show_more") : t("show_less")} + {showMore ? t("show_less") : t("show_more")} {showMore ? ( diff --git a/apps/web/src/components/dashboard/project-pagination.tsx b/apps/web/src/components/dashboard/project-pagination.tsx index 3cbf9a8..b05fa12 100644 --- a/apps/web/src/components/dashboard/project-pagination.tsx +++ b/apps/web/src/components/dashboard/project-pagination.tsx @@ -12,17 +12,22 @@ import { } from "../ui/pagination"; import type { Organization } from "~/lib/validators/organization"; import { useProjectsPaginatedQuery } from "~/lib/queries/useProjectsQuery"; +import type { SupportedLanguages } from "~/i18n/settings"; +import { useTranslation } from "~/i18n/client"; interface ProjectPaginationProps { organizationName: Organization["name"]; + lang: SupportedLanguages; } export default function ProjectPagination({ organizationName, + lang, }: ProjectPaginationProps) { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); + const { t } = useTranslation(lang, "overview", { keyPrefix: "" }); const page = searchParams.get("page") ?? "1"; const query = searchParams.get("q") ?? ""; @@ -47,7 +52,9 @@ export default function ProjectPagination({ onClick={() => { if (+page! > 1) changePage(+page! - 1); }} - /> + > + {t("next_page_button")} +
@@ -89,7 +96,7 @@ export default function ProjectPagination({ pages.push( { changePage(i); }} @@ -125,7 +132,9 @@ export default function ProjectPagination({ onClick={() => { if (data.hasNextPage) changePage(+page! + 1); }} - /> + > + {t("previous_page_button")} + diff --git a/apps/web/src/components/dashboard/project-view.tsx b/apps/web/src/components/dashboard/project-view.tsx index 22cd15f..d3d18d7 100644 --- a/apps/web/src/components/dashboard/project-view.tsx +++ b/apps/web/src/components/dashboard/project-view.tsx @@ -5,12 +5,21 @@ import Image from "next/image"; import { useEffect, useState } from "react"; import type { Project } from "~/lib/validators/project"; import { Button } from "../ui/button"; -import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { useQueryClient } from "@tanstack/react-query"; import ProjectForm from "./project-form"; import { Badge } from "../ui/badge"; -import { GitPullRequestClosed, Merge } from "lucide-react"; +import { GitPullRequestClosed, Loader2, Merge } from "lucide-react"; import { useLanguagesQuery } from "~/lib/queries/useLanguagesQuery"; import { useCategoriesQuery } from "~/lib/queries/useCategoriesQuery"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "../ui/tooltip"; +import { useProjectStatusMutation } from "~/lib/mutations/useProjectStatusMutation"; +import { useProjectQuery } from "~/lib/queries/useProjectsQuery"; +import { useEditProjectMutation } from "~/lib/mutations/useEditProjectMutation"; import type { SupportedLanguages } from "~/i18n/settings"; import { useTranslation } from "~/i18n/client"; @@ -24,10 +33,6 @@ function ProjectDisplay({ channel, project, lang }: ProjectDisplayProps) { const [showWholeDescription, setShowWholeDescription] = useState(false); const descriptionLines = project.description.split("\n"); - const { t } = useTranslation(lang, "project-page", { - keyPrefix: "project_display", - }); - const { data: languages } = useLanguagesQuery(lang); const language = languages?.find( (language) => language.id === project.defaultLanguage, @@ -38,6 +43,18 @@ function ProjectDisplay({ channel, project, lang }: ProjectDisplayProps) { (category) => category.id === project.categoryId, ); + const { t } = useTranslation(lang, "project-page", { + keyPrefix: "project_display", + }); + + const queryClient = useQueryClient(); + + const { mutate, isPending } = useProjectStatusMutation(project.id, { + onSuccess: () => { + queryClient.refetchQueries({ queryKey: ["project", project.id] }); + }, + }); + return ( <>

{project.title}

@@ -73,12 +90,14 @@ function ProjectDisplay({ channel, project, lang }: ProjectDisplayProps) {

{descriptionLines[0]}

)} - + {descriptionLines.length > 1 && ( + + )}
@@ -128,15 +147,53 @@ function ProjectDisplay({ channel, project, lang }: ProjectDisplayProps) {
- - - + {project.status === "unlisted" ? ( + <> + + + + + +
+ +
+
+ + + {t("unable_to_publish_info")} + +
+
+ + ) : ( + + )}
); @@ -151,7 +208,7 @@ interface ProjectViewProps { } export default function ProjectView({ - project, + project: initialProject, channel, languages, categories, @@ -173,7 +230,16 @@ export default function ProjectView({ } }, []); - const { mutate } = useMutation({}); + const { data: project, refetch } = useProjectQuery(initialProject.id, { + initialData: initialProject, + }); + + const { mutate, isPending } = useEditProjectMutation(project!.id, { + onSuccess: () => { + refetch(); + setIsEditing(false); + }, + }); return (
@@ -193,7 +259,7 @@ export default function ProjectView({