Skip to content

Commit bf90afd

Browse files
committed
fix setting skeleton and loading btn
1 parent e64ccaf commit bf90afd

14 files changed

Lines changed: 442 additions & 103 deletions

File tree

src/components/Button.jsx

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
import styled from "styled-components";
2-
import loaderGif from "../assets/gif/ajax-loader.gif";
32

43
const ButtonElement = styled.button`
54
border-radius: 10px;
65
white-space: nowrap;
76
background-color: ${(props) =>
87
props.color
9-
? props.disabled
10-
? `${props.color}80` // Add 50% transparency when disabled
11-
: props.color
8+
? props.disabled === "pending"
9+
? props.color // همان رنگ اصلی، فقط مات میشه
10+
: props.disabled
11+
? `${props.color}80`
12+
: props.color
1213
: props.grayTheme
1314
? props.theme.colors.newColors.otherColors.garyBtn
1415
: props.disabled === "pending"
15-
? "#3B3B3B"
16-
: props.theme.colors.primary};
16+
? props.theme.colors.primary // رنگ اصلی، فقط مات میشه
17+
: props.disabled
18+
? `${props.theme.colors.primary}80`
19+
: props.theme.colors.primary};
1720
border: none;
1821
padding: ${(props) => (props.large ? "0 20px" : "10px 22px")};
1922
width: ${(props) =>
@@ -32,7 +35,7 @@ const ButtonElement = styled.button`
3235
cursor: ${(props) => (props.disabled ? "not-allowed" : "pointer")};
3336
color: ${(props) =>
3437
props.disabled === "pending"
35-
? "#949494"
38+
? props.theme.colors.newColors.primaryText
3639
: props.grayTheme
3740
? props.theme.colors.newColors.otherColors.grayBtnText
3841
: props.theme.colors.newColors.primaryText};
@@ -41,8 +44,10 @@ const ButtonElement = styled.button`
4144
display: flex;
4245
align-items: center;
4346
justify-content: center;
44-
opacity: ${(props) => (props.disabled ? "0.5" : "1")};
47+
gap: 8px;
48+
opacity: ${(props) => (props.disabled === "pending" ? "0.6" : props.disabled ? "0.5" : "1")};
4549
pointer-events: ${(props) => (props.disabled ? "none" : "auto")};
50+
4651
@media (max-width: 840px) {
4752
width: ${(props) => (props.row ? "55px" : props.full && "100%")};
4853
height: ${(props) => props.row && "35px"};
@@ -52,10 +57,21 @@ const ButtonElement = styled.button`
5257
@media (min-width: 998px) {
5358
height: ${(props) => (props.large ? "40px" : "50px")};
5459
}
55-
& img {
56-
width: 25px;
57-
height: 25px;
58-
margin: 0 3px;
60+
`;
61+
62+
// اسپینر دایره‌ای
63+
const Spinner = styled.span`
64+
width: 18px;
65+
height: 18px;
66+
border: 2px solid rgba(255, 255, 255, 0.5);
67+
border-top: 2px solid white;
68+
border-radius: 50%;
69+
animation: spin 0.8s linear infinite;
70+
display: inline-block;
71+
72+
@keyframes spin {
73+
0% { transform: rotate(0deg); }
74+
100% { transform: rotate(360deg); }
5975
}
6076
`;
6177

@@ -91,9 +107,9 @@ const Button = ({
91107
style={style}
92108
>
93109
{label}
94-
{disabled === "pending" && <img src={loaderGif} alt="Loading..." />}
110+
{disabled === "pending" && <Spinner />}
95111
</ButtonElement>
96112
);
97113
};
98114

99-
export default Button;
115+
export default Button;

src/components/Common/SkeletonGrid.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ const shimmer = keyframes`
99
const LoadingContainer = styled(Container)`
1010
display: flex;
1111
gap: 20px;
12-
padding: 20px;
12+
1313
`;
1414

1515
const SkeletonCard = styled.div`
1616
flex: 1;
17-
height: 280px;
18-
border-radius: 10px;
17+
height: 66px;
18+
border-radius: 4px;
1919
background: linear-gradient(
2020
90deg,
21-
#dcdcdc 25%,
22-
#e9e9e9 37%,
23-
#dcdcdc 63%
21+
${(props) => props.theme.colors.newColors.shades.bg02},
22+
${(props) => props.theme.colors.newColors.shades.bg002},
23+
${(props) => props.theme.colors.newColors.shades.bg0002}
2424
);
2525
background-size: 1000px 100%;
2626
animation: ${shimmer} 1.2s infinite linear;

src/pages/Report/reports/ErrorReportTab/ErrorReportTab.jsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { useLocation } from "react-router-dom";
1414
import Container from "../../../../components/Common/Container";
1515
import ErrorMessage from "../../../../components/ErrorMessage";
1616
import getModalHeaderFromPrevious from "../../../../services/TitleManager";
17+
1718
const StyledContent = styled.div`
1819
p {
1920
margin: 10px 0;
@@ -31,11 +32,11 @@ const ErrorReportTab = () => {
3132
const location = useLocation();
3233
const [title, setTitle] = useState("");
3334
const [subdomain, SetSubdomain] = useState("");
35+
const [isSending, setIsSending] = useState(false); // حالت لودینگ دکمه
36+
3437
useEffect(() => {
3538
const basePath = location.state?.from ?? location.pathname;
36-
3739
const { title, page } = getModalHeaderFromPrevious(basePath);
38-
3940
setTitle(title);
4041
SetSubdomain(page);
4142
}, [location]);
@@ -53,13 +54,16 @@ const ErrorReportTab = () => {
5354
dispatch({ type: "SET_DESCRIPTION", payload: "" });
5455
dispatch({ type: "SET_FILES", payload: [] });
5556
};
57+
5658
const sendReport = async () => {
5759
if (
5860
state.subject &&
5961
state.title &&
6062
state.description &&
6163
state.files.length > 0
6264
) {
65+
setIsSending(true); // شروع لودینگ
66+
6367
const formData = {
6468
title: state.title,
6569
content: state.description,
@@ -73,6 +77,7 @@ const ErrorReportTab = () => {
7377

7478
if (attachments.length > 5) {
7579
setError("The attachment must not have more than 5 items.");
80+
setIsSending(false);
7681
return;
7782
}
7883

@@ -95,11 +100,21 @@ const ErrorReportTab = () => {
95100
}, 3000);
96101
} catch (error) {
97102
console.error("❌ Report submission failed:", error);
98-
99103
setError(getFieldTranslationByNames("1387"));
104+
} finally {
105+
setIsSending(false); // پایان لودینگ
100106
}
101107
}
102108
};
109+
110+
// بررسی غیرفعال بودن دکمه
111+
const isDisabled = !(
112+
state.subject &&
113+
state.title &&
114+
state.description &&
115+
state.files.length > 0
116+
);
117+
103118
return (
104119
<Container ref={containerRef}>
105120
{alert && (
@@ -119,6 +134,7 @@ const ErrorReportTab = () => {
119134
fit
120135
label={getFieldTranslationByNames("193")}
121136
onclick={sendReport}
137+
disabled={isDisabled ? true : isSending ? "pending" : false}
122138
/>
123139
</div>
124140
<ErrorMessage
@@ -132,4 +148,4 @@ const ErrorReportTab = () => {
132148
);
133149
};
134150

135-
export default ErrorReportTab;
151+
export default ErrorReportTab;

src/pages/Sanad/Tabs/WriteVodTab.jsx

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
getFieldTranslationByNames,
1212
ToastError,
1313
} from "../../../services/Utility";
14-
1514
import useRequest from "../../../services/Hooks/useRequest";
1615
import Container from "../../../components/Common/Container";
1716

@@ -20,6 +19,7 @@ const WriteVodTab = () => {
2019
const { alert, setAlert } = useContext(AlertContext);
2120
const { Request, HTTP_METHOD } = useRequest();
2221
const containerRef = useRef(null);
22+
const [isSending, setIsSending] = useState(false);
2323

2424
const resetForm = () => {
2525
dispatch({ type: "SET_SUBJECT", payload: "" });
@@ -36,6 +36,8 @@ const WriteVodTab = () => {
3636
state.description &&
3737
state.files.length > 0
3838
) {
39+
setIsSending(true);
40+
3941
const filesData = new FormData();
4042

4143
filesData.append("title", state.title);
@@ -68,11 +70,11 @@ const WriteVodTab = () => {
6870
setAlert(false);
6971
}, 2000);
7072
})
71-
7273
.catch((error) => {
73-
74-
ToastError(error.response.data.message);
75-
74+
ToastError(error.response?.data?.message || "خطا در ارسال تیکت");
75+
})
76+
.finally(() => {
77+
setIsSending(false);
7678
});
7779
}
7880
};
@@ -90,6 +92,14 @@ const WriteVodTab = () => {
9092
}
9193
}, [alert, setAlert]);
9294

95+
// بررسی غیرفعال بودن دکمه
96+
const isDisabled = !(
97+
state.subject &&
98+
state.title &&
99+
state.description &&
100+
state.files.length > 0
101+
);
102+
93103
return (
94104
<Container ref={containerRef}>
95105
<Title title={getFieldTranslationByNames("1314")} right />
@@ -105,7 +115,12 @@ const WriteVodTab = () => {
105115
<Description />
106116
<SendFiles files={state.files} onFilesChange={handleFilesChange} />
107117

108-
<Button fit label={getFieldTranslationByNames("730")} onclick={sendVod} />
118+
<Button
119+
fit
120+
label={getFieldTranslationByNames("730")}
121+
onclick={sendVod}
122+
disabled={isDisabled ? true : isSending ? "pending" : false}
123+
/>
109124
</Container>
110125
);
111126
};

src/pages/Sanad/Tabs/notes/WriteNote.jsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const Container = styled.div`
2121
width: 50%;
2222
}
2323
`;
24+
2425
const Subject = styled.div`
2526
input {
2627
background-color: ${(props) =>
@@ -58,14 +59,17 @@ const WriteNote = () => {
5859
const [title, setTitle] = useState("");
5960
const [description, setDescription] = useState("");
6061
const [files, setFiles] = useState([]);
62+
const [isSending, setIsSending] = useState(false); // حالت لودینگ
6163

6264
const { Request, HTTP_METHOD } = useRequest();
65+
6366
useEffect(() => {
6467
if (alert) {
6568
const timer = setTimeout(() => setAlert(false), 2000);
6669
return () => clearTimeout(timer);
6770
}
6871
}, [alert, setAlert]);
72+
6973
const handleSaveNote = () => {
7074
if (!title.trim() || !description.trim()) {
7175
setError(getFieldTranslationByNames(1644));
@@ -78,6 +82,7 @@ const WriteNote = () => {
7882
}
7983

8084
setError("");
85+
setIsSending(true); // شروع لودینگ
8186

8287
const formData = new FormData();
8388
formData.append("title", title);
@@ -93,7 +98,10 @@ const WriteNote = () => {
9398
setAlert(true);
9499
resetForm();
95100
})
96-
.catch(() => setError(getFieldTranslationByNames(1645)));
101+
.catch(() => setError(getFieldTranslationByNames(1645)))
102+
.finally(() => {
103+
setIsSending(false); // پایان لودینگ
104+
});
97105
};
98106

99107
const resetForm = () => {
@@ -102,6 +110,9 @@ const WriteNote = () => {
102110
setFiles([]);
103111
};
104112

113+
// بررسی غیرفعال بودن دکمه
114+
const isDisabled = !title.trim() || !description.trim() || files.length > 5;
115+
105116
return (
106117
<Container>
107118
<Title right title={getFieldTranslationByNames("1354")} />
@@ -121,11 +132,12 @@ const WriteNote = () => {
121132
fit
122133
label={getFieldTranslationByNames("629")}
123134
onclick={handleSaveNote}
135+
disabled={isDisabled ? true : isSending ? "pending" : false}
124136
/>
125137
</div>
126138
{error && <ErrorMessage>{error}</ErrorMessage>}
127139
</Container>
128140
);
129141
};
130142

131-
export default WriteNote;
143+
export default WriteNote;

src/pages/Sanad/Tabs/sent/SentList.jsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,28 @@ const rows_items = [
140140
];
141141
const SentList = ({ setShowDetails }) => {
142142
const [rows, setRows] = useState([]);
143+
const [loading, setLoading] = useState(true);
143144
const [searched, setSearched] = useState("");
144145
const [status, setStatus] = useState({
145146
pending: false,
146147
confirmed: false,
147148
failed: false,
148149
read: false,
149150
});
150-
151+
useEffect(() => {
152+
setLoading(true);
153+
Request("tickets?recieved=1")
154+
.then((response) => {
155+
setRows(response.data.data || []);
156+
})
157+
.catch((error) => {
158+
console.error("Error fetching tickets:", error);
159+
setRows([]);
160+
})
161+
.finally(() => {
162+
setLoading(false);
163+
});
164+
}, []);
151165
const { Request } = useRequest();
152166

153167
useEffect(() => {
@@ -203,6 +217,7 @@ const SentList = ({ setShowDetails }) => {
203217
status={status}
204218
rows={filteredItems}
205219
mode=""
220+
isLoading={loading}
206221
/>
207222
</Container>
208223
);

0 commit comments

Comments
 (0)