Skip to content
This repository was archived by the owner on May 18, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/(app)/categories/[categoryId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';
import ThreadItem from '@/components/OnlyApp/ThreadListing/ThreadItem';
import LoadingSpinner from '@/components/LoadingSpinner';
import ErrorAlert from '@/components/Form/ErrorAlert';
import { Thread } from '@/types';
import { fetchThreads } from '@/services/thread/threadService';
import { Hash } from 'lucide-react';
import { fetchCategories } from '@/services/thread/categoryService';
import { useAuthLoading } from '@/hooks';
import RetryAgain from '@/components/OnlyApp/RetryAgain';

export default function CategoryDiscussionsPage() {
const { isAuthLoadingOrRedirecting } = useAuthLoading();
Expand Down Expand Up @@ -67,7 +67,7 @@ export default function CategoryDiscussionsPage() {
}

if (error) {
return <ErrorAlert message={error} />;
return <RetryAgain error={error} handleRetry={() => window.location.reload()} />;
}

return (
Expand Down
2 changes: 1 addition & 1 deletion src/app/(app)/discussions/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export default function NewDiscussionPage() {

if (error && !isSubmitting) {
return (
<RetryAgain
<RetryAgain
error={error}
handleRetry={() => window.location.reload()}
/>
Expand Down
24 changes: 8 additions & 16 deletions src/app/(app)/profile-settings/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { AuthMethod } from '@/utils/api/signup/validateSignupForm';
import Image from 'next/image';
import { useAuth, useAuthRedirect } from '@/hooks';
import { isSuperAdminByRole } from '@/utils/role';
import RetryAgain from '@/components/OnlyApp/RetryAgain';

export default function ProfilePage() {
const router = useRouter();
Expand Down Expand Up @@ -54,11 +55,9 @@ export default function ProfilePage() {
});
} else {
setError(result.error?.message || RESPONSE_MESSAGES.profile.DEFAULT);
toast.error(result.error?.message || RESPONSE_MESSAGES.profile.DEFAULT);
}
} catch {
setError(RESPONSE_MESSAGES.profile.DEFAULT);
toast.error(RESPONSE_MESSAGES.profile.DEFAULT);
} finally {
setIsLoadingProfile(false);
}
Expand All @@ -85,7 +84,6 @@ export default function ProfilePage() {
const validationErrors = validateProfileForm(formData);
if (Object.keys(validationErrors).length > 0) {
setError(Object.values(validationErrors)[0]);
toast.error(Object.values(validationErrors)[0]);
setIsSubmitting(false);
return;
}
Expand Down Expand Up @@ -200,19 +198,13 @@ export default function ProfilePage() {

if (error && !isSubmitting) {
return (
<div className="space-y-4">
<ErrorAlert message={error} />
<Button
onClick={() => {
window.location.reload();
router.refresh();
}}
variant="outline"
color="secondary"
>
تحديث حالة الحساب
</Button>
</div>
<RetryAgain
error={error}
handleRetry={() => {
window.location.reload();
router.refresh();
}}
/>
);
}

Expand Down
19 changes: 6 additions & 13 deletions src/components/AdminsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import LoadingSpinner from "@/components/LoadingSpinner";
import ErrorAlert from "./Form/ErrorAlert";
import Button from "./Button";
import SearchField from "./OnlyApp/SearchField";
import Divider from "./Divider";
import UsersBadge from "./OnlyApp/Badge/UsersBadge";
import UserCardItem from "./OnlyApp/UserCardItem";
import { ArrowUpDown, RefreshCw, UserPlus } from "lucide-react";
import { ArrowUpDown, UserPlus } from "lucide-react";
import { Admin } from "@/types";
import { adminService } from "@/services/admin/adminService";
import RESPONSE_MESSAGES from "@/utils/constants/RESPONSE_MESSAGES";
import ItemNotFound from '@/components/OnlyApp/NotFound/ItemNotFound';
import RetryAgain from "./OnlyApp/RetryAgain";

export default function AdminsListing() {
const [isLoading, setIsLoading] = useState(true);
Expand Down Expand Up @@ -92,17 +92,10 @@ export default function AdminsListing() {

if (error) {
return (
<div className="space-y-4">
<ErrorAlert message={error} />
<Button
onClick={handleRetry}
variant="outline"
icon={<RefreshCw className="w-4" />}
color="secondary"
>
إعادة المحاولة
</Button>
</div>
<RetryAgain
error={error}
handleRetry={handleRetry}
/>
);
}

Expand Down
1 change: 1 addition & 0 deletions src/components/OnlyApp/AppNavbar/UserDropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function UserDropdownMenu() {
role={role}
photoPath={photoPath}
name={username}
isUsername={true}
hideDetailsOnSmallScreens={true}
>
<ChevronDown className={cn(
Expand Down
8 changes: 5 additions & 3 deletions src/components/OnlyApp/CategoriesListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import Input from "../Input";
import { updateCategory, deleteCategory } from "@/services/admin/categoryService";
import { toast } from "react-hot-toast";
import ConfirmModal from "../Modal/ConfirmModal";
import ErrorAlert from "../Form/ErrorAlert";
import Link from 'next/link';
import RetryAgain from "./RetryAgain";
import ItemNotFound from "./NotFound/ItemNotFound";

interface CategoriesListingProps {
allowManagement?: boolean;
Expand All @@ -20,6 +21,7 @@ interface CategoriesListingProps {
maxChars?: number;
error?: string;
}

function CategoriesListing({
allowManagement = false,
categories,
Expand Down Expand Up @@ -99,9 +101,9 @@ function CategoriesListing({
<LoadingSpinner size="sm" color="primary" />
</div>
) : error ? (
error && <ErrorAlert message={error} />
<RetryAgain error={error} handleRetry={() => window.location.reload()} />
) : categories.length === 0 ? (
<p className="text-sm text-gray-500 px-3 py-2">لا توجد تصنيفات متاحة</p>
<ItemNotFound description="لا توجد تصنيفات متاحة" />
) : (
categories.map((category) => (
<div
Expand Down
23 changes: 7 additions & 16 deletions src/components/OnlyApp/ThreadListing/ThreadListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import ThreadListingHeader from "./ThreadListingHeader";
import { useState, useEffect, useCallback } from "react";
import toast from "react-hot-toast";
import { Thread } from "@/types";
import ErrorAlert from "@/components/Form/ErrorAlert";
import { RefreshCw } from "lucide-react";
import LoadingSpinner from "@/components/LoadingSpinner";
import Button from "@/components/Button";
import { useInfiniteScroll } from "@/hooks";
import { deleteThread, fetchThreads } from "@/services/thread/threadService";
import { userService } from "@/services/userService";
import { ApiSuccess } from "@/types";
import RetryAgain from "../RetryAgain";
import { logger } from "@/utils/logger";

interface ThreadListingProps {
emptyMessage?: string;
Expand Down Expand Up @@ -81,7 +80,6 @@ const ThreadListing = ({
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'حدث خطأ أثناء تحميل المناقشات';
setError(errorMessage);
toast.error(errorMessage);
} finally {
if (isInitialLoad) {
setIsLoading(false);
Expand Down Expand Up @@ -135,7 +133,7 @@ const ThreadListing = ({
setPage((prev) => prev + 1);
} catch (err) {
const errorMessage = err instanceof Error ? err.message : 'حدث خطأ أثناء تحميل المزيد من المناقشات';
toast.error(errorMessage);
logger().error(errorMessage);
} finally {
setIsFetchingMore(false);
}
Expand Down Expand Up @@ -184,17 +182,10 @@ const ThreadListing = ({

if (error) {
return (
<div className="space-y-4">
<ErrorAlert message={error} />
<Button
onClick={handleRetry}
variant="outline"
icon={<RefreshCw className="w-4" />}
color="secondary"
>
إعادة المحاولة
</Button>
</div>
<RetryAgain
error={error}
handleRetry={handleRetry}
/>
);
}

Expand Down
10 changes: 8 additions & 2 deletions src/components/OnlyApp/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface UserInfoProps {
isDeleted?: boolean;
username?: string;
linkToProfile?: boolean;
isUsername?: boolean;
}

function UserInfo({
Expand All @@ -29,9 +30,11 @@ function UserInfo({
isDeleted = false,
username,
linkToProfile = false,
isUsername = false,
}: UserInfoProps) {
const isSmall = size === "sm";
const displayName = isDeleted || !name ? "مستخدم محذوف" : getDisplayName(name);
const displayName = isDeleted || !name ? "مستخدم محذوف" : getDisplayName(name, true);
const formattedUsername = `@${name}`;
const displayPhotoPath = isDeleted ? undefined : photoPath;
const profileLink = username ? `/${username}` : undefined;

Expand All @@ -49,8 +52,11 @@ function UserInfo({
>
<span
className={`${isSmall ? "text-xs" : "text-[14px]"} font-semibold text-gray-700 leading-none flex items-center gap-1`}
style={{
direction: isUsername ? 'ltr' : 'rtl',
}}
>
{displayName}
{isUsername ? formattedUsername : displayName}
</span>
{date && <DateBadge label={date} size="xs" />}
</div>
Expand Down
28 changes: 8 additions & 20 deletions src/components/OnlyApp/pages/DiscussionPageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import Button from "@/components/Button";
import { useState, ChangeEvent, useEffect, useCallback } from "react";
import { Thread } from "@/types";
import { toast } from "react-hot-toast";
import ErrorAlert from "@/components/Form/ErrorAlert";
import LoadingSpinner from "@/components/LoadingSpinner";
import CommentListing from "@/components/OnlyApp/Comment/CommentListing";
import { RefreshCw } from "lucide-react";
import RESPONSE_MESSAGES from "@/utils/constants/RESPONSE_MESSAGES";
import ItemNotFound from "../NotFound/ItemNotFound";
import { useAuth, useInfiniteScroll } from "@/hooks";
import { deleteThread, fetchThreadById, fetchThreads } from "@/services/thread/threadService";
import { createComment } from "@/services/thread/commentService";
import { logger } from "@/utils/logger";
import RetryAgain from "../RetryAgain";

function DiscussionPageContent({ discussionId }: { discussionId: string }) {
const router = useRouter();
Expand Down Expand Up @@ -52,12 +52,10 @@ function DiscussionPageContent({ discussionId }: { discussionId: string }) {
setThread(threadData);
} else {
setError(threadResult.error.message || 'حدث خطأ أثناء تحميل المناقشة');
toast.error(threadResult.error.message || 'حدث خطأ أثناء تحميل المناقشة');
}
} catch {
const errorMessage = 'حدث خطأ أثناء تحميل المناقشة';
setError(errorMessage);
toast.error(errorMessage);
} finally {
setIsLoading(false);
}
Expand All @@ -82,7 +80,7 @@ function DiscussionPageContent({ discussionId }: { discussionId: string }) {
setPage(2);
}
} catch {
toast.error("حدث خطأ أثناء تحميل المناقشات المشابهة");
logger().error("حدث خطأ أثناء تحميل المناقشات المشابهة");
} finally {
setIsLoadingSimilar(false);
}
Expand All @@ -107,7 +105,6 @@ function DiscussionPageContent({ discussionId }: { discussionId: string }) {
}
} catch (err) {
console.error("Error loading more threads:", err);
toast.error("حدث خطأ أثناء تحميل المزيد من المناقشات");
} finally {
setIsLoadingSimilar(false);
}
Expand Down Expand Up @@ -194,9 +191,7 @@ function DiscussionPageContent({ discussionId }: { discussionId: string }) {
const result = await fetchThreadById(thread.thread_id);
if (result.success) {
setThread(result.data);
} else {
toast.error(result.error.message || RESPONSE_MESSAGES.thread.DEFAULT);
}
}
};

useEffect(() => {
Expand All @@ -215,17 +210,10 @@ function DiscussionPageContent({ discussionId }: { discussionId: string }) {

if (error) {
return (
<div className="space-y-4">
<ErrorAlert message={error} />
<Button
onClick={loadThread}
variant="outline"
icon={<RefreshCw className="w-4" />}
color="secondary"
>
إعادة المحاولة
</Button>
</div>
<RetryAgain
error={error}
handleRetry={loadThread}
/>
);
}

Expand Down
18 changes: 6 additions & 12 deletions src/components/StudentsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import LoadingSpinner from "@/components/LoadingSpinner";
import ErrorAlert from "./Form/ErrorAlert";
import Button from "./Button";
import SearchField from "./OnlyApp/SearchField";
import Select from "./Select";
import Divider from "./Divider";
import UsersBadge from "./OnlyApp/Badge/UsersBadge";
import UserCardItem from "./OnlyApp/UserCardItem";
import { ArrowUpDown, RefreshCw } from "lucide-react";
import { ArrowUpDown } from "lucide-react";
import { Student, ApprovalStatus } from "@/types";
import { fetchStudents, approveStudent, rejectStudent } from "@/services/admin/studentService";
import RetryAgain from "./OnlyApp/RetryAgain";

const StudentsListing = () => {
const [isLoading, setIsLoading] = useState(true);
Expand Down Expand Up @@ -46,7 +46,6 @@ const StudentsListing = () => {

const errorMessage = err instanceof Error ? err.message : 'حدث خطأ أثناء تحميل الطلاب';
setError(`${errorMessage}. يرجى المحاولة مرة أخرى.`);
toast.error(errorMessage);
} finally {
setIsLoading(false);
setIsFiltering(false);
Expand Down Expand Up @@ -188,15 +187,10 @@ const StudentsListing = () => {

{error ? (
<div className="space-y-4">
<ErrorAlert message={error} />
<Button
onClick={handleRetry}
variant="outline"
icon={<RefreshCw className="w-4" />}
color="secondary"
>
إعادة المحاولة
</Button>
<RetryAgain
error={error}
handleRetry={handleRetry}
/>
</div>
) : isLoading || isFiltering ? (
<div className="min-h-[200px] flex items-center justify-center">
Expand Down
Loading